diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 197 |
1 files changed, 98 insertions, 99 deletions
diff --git a/src/utils.c b/src/utils.c index bad16d9..61ca856 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,5 @@ #include "../include/utils.h" +#include "../include/window/window.h" #include <time.h> #include <string.h> @@ -7,6 +8,7 @@ #include <fcntl.h> #include <stdlib.h> #include <sys/stat.h> +#include <sys/random.h> #include <errno.h> #include <assert.h> @@ -27,14 +29,23 @@ double clock_get_monotonic_seconds(void) { return (double)ts.tv_sec + (double)ts.tv_nsec * 0.000000001; } -static gsr_monitor_rotation wayland_transform_to_gsr_rotation(int32_t rot) { - switch(rot) { - case 0: return GSR_MONITOR_ROT_0; - case 1: return GSR_MONITOR_ROT_90; - case 2: return GSR_MONITOR_ROT_180; - case 3: return GSR_MONITOR_ROT_270; +bool generate_random_characters(char *buffer, int buffer_size, const char *alphabet, size_t alphabet_size) { + /* TODO: Use other functions on other platforms than linux */ + if(getrandom(buffer, buffer_size, 0) < buffer_size) { + fprintf(stderr, "Failed to get random bytes, error: %s\n", strerror(errno)); + return false; } - return GSR_MONITOR_ROT_0; + + for(int i = 0; i < buffer_size; ++i) { + unsigned char c = *(unsigned char*)&buffer[i]; + buffer[i] = alphabet[c % alphabet_size]; + } + + return true; +} + +bool generate_random_characters_standard_alphabet(char *buffer, int buffer_size) { + return generate_random_characters(buffer, buffer_size, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62); } static const XRRModeInfo* get_mode_info(const XRRScreenResources *sr, RRMode id) { @@ -71,6 +82,16 @@ static uint32_t x11_output_get_connector_id(Display *dpy, RROutput output, Atom return result; } +static vec2i get_monitor_size_rotated(int width, int height, gsr_monitor_rotation rotation) { + vec2i size = { .x = width, .y = height }; + if(rotation == GSR_MONITOR_ROT_90 || rotation == GSR_MONITOR_ROT_270) { + int tmp_x = size.x; + size.x = size.y; + size.y = tmp_x; + } + return size; +} + void for_each_active_monitor_output_x11_not_cached(Display *display, active_monitor_callback callback, void *userdata) { XRRScreenResources *screen_res = XRRGetScreenResources(display, DefaultRootWindow(display)); if(!screen_res) @@ -84,16 +105,23 @@ void for_each_active_monitor_output_x11_not_cached(Display *display, active_moni if(out_info && out_info->crtc && out_info->connection == RR_Connected) { XRRCrtcInfo *crt_info = XRRGetCrtcInfo(display, screen_res, out_info->crtc); if(crt_info && crt_info->mode) { + // We want to use the current mode info width/height (mode_info->width/height) instead of crtc info width/height (crt_info->width/height) because crtc info + // is scaled if the monitor is scaled (xrandr --output DP-1 --scale 1.5). Normally this is not an issue for x11 applications, + // but gpu screen recorder captures the drm framebuffer instead of x11 api. This drm framebuffer which doesn't increase in size when using xrandr scaling. + // Maybe a better option would be to get the drm crtc size instead. const XRRModeInfo *mode_info = get_mode_info(screen_res, crt_info->mode); if(mode_info && out_info->nameLen < (int)sizeof(display_name)) { snprintf(display_name, sizeof(display_name), "%.*s", (int)out_info->nameLen, out_info->name); + const gsr_monitor_rotation rotation = x11_rotation_to_gsr_rotation(crt_info->rotation); + const vec2i monitor_size = get_monitor_size_rotated(mode_info->width, mode_info->height, rotation); + const gsr_monitor monitor = { .name = display_name, .name_len = out_info->nameLen, .pos = { .x = crt_info->x, .y = crt_info->y }, - .size = { .x = (int)crt_info->width, .y = (int)crt_info->height }, + .size = monitor_size, .connector_id = x11_output_get_connector_id(display, screen_res->outputs[i], randr_connector_id_atom), - .rotation = x11_rotation_to_gsr_rotation(crt_info->rotation), + .rotation = rotation, .monitor_identifier = out_info->crtc }; callback(&monitor, userdata); @@ -109,31 +137,22 @@ void for_each_active_monitor_output_x11_not_cached(Display *display, active_moni XRRFreeScreenResources(screen_res); } -void for_each_active_monitor_output_x11(const gsr_egl *egl, active_monitor_callback callback, void *userdata) { - for(int i = 0; i < egl->x11.num_outputs; ++i) { - const gsr_x11_output *output = &egl->x11.outputs[i]; - const gsr_monitor monitor = { - .name = output->name, - .name_len = strlen(output->name), - .pos = output->pos, - .size = output->size, - .connector_id = output->connector_id, - .rotation = output->rotation, - .monitor_identifier = output->monitor_identifier - }; - callback(&monitor, userdata); - } +/* TODO: Support more connector types */ +int get_connector_type_by_name(const char *name) { + int len = strlen(name); + if(len >= 5 && strncmp(name, "HDMI-", 5) == 0) + return 1; + else if(len >= 3 && strncmp(name, "DP-", 3) == 0) + return 2; + else if(len >= 12 && strncmp(name, "DisplayPort-", 12) == 0) + return 3; + else if(len >= 4 && strncmp(name, "eDP-", 4) == 0) + return 4; + else + return -1; } -typedef struct { - int type; - int count; - int count_active; -} drm_connector_type_count; - -#define CONNECTOR_TYPE_COUNTS 32 - -static drm_connector_type_count* drm_connector_types_get_index(drm_connector_type_count *type_counts, int *num_type_counts, int connector_type) { +drm_connector_type_count* drm_connector_types_get_index(drm_connector_type_count *type_counts, int *num_type_counts, int connector_type) { for(int i = 0; i < *num_type_counts; ++i) { if(type_counts[i].type == connector_type) return &type_counts[i]; @@ -150,6 +169,10 @@ static drm_connector_type_count* drm_connector_types_get_index(drm_connector_typ return &type_counts[index]; } +uint32_t monitor_identifier_from_type_and_count(int monitor_type_index, int monitor_type_count) { + return ((uint32_t)monitor_type_index << 16) | ((uint32_t)monitor_type_count); +} + static bool connector_get_property_by_name(int drmfd, drmModeConnectorPtr props, const char *name, uint64_t *result) { for(int i = 0; i < props->count_props; ++i) { drmModePropertyPtr prop = drmModeGetProperty(drmfd, props->props[i]); @@ -165,61 +188,12 @@ static bool connector_get_property_by_name(int drmfd, drmModeConnectorPtr props, return false; } -/* TODO: Support more connector types */ -static int get_connector_type_by_name(const char *name) { - int len = strlen(name); - if(len >= 5 && strncmp(name, "HDMI-", 5) == 0) - return 1; - else if(len >= 3 && strncmp(name, "DP-", 3) == 0) - return 2; - else if(len >= 12 && strncmp(name, "DisplayPort-", 12) == 0) - return 3; - else if(len >= 4 && strncmp(name, "eDP-", 4) == 0) - return 4; - else - return -1; -} - -static uint32_t monitor_identifier_from_type_and_count(int monitor_type_index, int monitor_type_count) { - return ((uint32_t)monitor_type_index << 16) | ((uint32_t)monitor_type_count); -} - -static void for_each_active_monitor_output_wayland(const gsr_egl *egl, active_monitor_callback callback, void *userdata) { - drm_connector_type_count type_counts[CONNECTOR_TYPE_COUNTS]; - int num_type_counts = 0; - - for(int i = 0; i < egl->wayland.num_outputs; ++i) { - const gsr_wayland_output *output = &egl->wayland.outputs[i]; - if(!output->name) - continue; - - const int connector_type_index = get_connector_type_by_name(output->name); - drm_connector_type_count *connector_type = NULL; - if(connector_type_index != -1) - connector_type = drm_connector_types_get_index(type_counts, &num_type_counts, connector_type_index); - - if(connector_type) { - ++connector_type->count; - ++connector_type->count_active; - } - - const gsr_monitor monitor = { - .name = output->name, - .name_len = strlen(output->name), - .pos = { .x = output->pos.x, .y = output->pos.y }, - .size = { .x = output->size.x, .y = output->size.y }, - .connector_id = 0, - .rotation = wayland_transform_to_gsr_rotation(output->transform), - .monitor_identifier = connector_type ? monitor_identifier_from_type_and_count(connector_type_index, connector_type->count_active) : 0 - }; - callback(&monitor, userdata); - } -} - -static void for_each_active_monitor_output_drm(const gsr_egl *egl, active_monitor_callback callback, void *userdata) { - int fd = open(egl->card_path, O_RDONLY); - if(fd == -1) +static void for_each_active_monitor_output_drm(const char *card_path, active_monitor_callback callback, void *userdata) { + int fd = open(card_path, O_RDONLY); + if(fd == -1) { + fprintf(stderr, "gsr error: for_each_active_monitor_output_drm failed, failed to open \"%s\", error: %s\n", card_path, strerror(errno)); return; + } drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1); @@ -278,16 +252,14 @@ static void for_each_active_monitor_output_drm(const gsr_egl *egl, active_monito close(fd); } -void for_each_active_monitor_output(const gsr_egl *egl, gsr_connection_type connection_type, active_monitor_callback callback, void *userdata) { +void for_each_active_monitor_output(const gsr_window *window, const char *card_path, gsr_connection_type connection_type, active_monitor_callback callback, void *userdata) { switch(connection_type) { case GSR_CONNECTION_X11: - for_each_active_monitor_output_x11(egl, callback, userdata); - break; case GSR_CONNECTION_WAYLAND: - for_each_active_monitor_output_wayland(egl, callback, userdata); + gsr_window_for_each_active_monitor_output_cached(window, callback, userdata); break; case GSR_CONNECTION_DRM: - for_each_active_monitor_output_drm(egl, callback, userdata); + for_each_active_monitor_output_drm(card_path, callback, userdata); break; } } @@ -310,7 +282,7 @@ bool get_monitor_by_name(const gsr_egl *egl, gsr_connection_type connection_type userdata.name_len = strlen(name); userdata.monitor = monitor; userdata.found_monitor = false; - for_each_active_monitor_output(egl, connection_type, get_monitor_by_name_callback, &userdata); + for_each_active_monitor_output(egl->window, egl->card_path, connection_type, get_monitor_by_name_callback, &userdata); return userdata.found_monitor; } @@ -342,14 +314,14 @@ static void get_monitor_by_connector_id_callback(const gsr_monitor *monitor, voi } } -gsr_monitor_rotation drm_monitor_get_display_server_rotation(const gsr_egl *egl, const gsr_monitor *monitor) { - if(gsr_egl_get_display_server(egl) == GSR_DISPLAY_SERVER_WAYLAND) { +gsr_monitor_rotation drm_monitor_get_display_server_rotation(const gsr_window *window, const gsr_monitor *monitor) { + if(gsr_window_get_display_server(window) == GSR_DISPLAY_SERVER_WAYLAND) { { get_monitor_by_connector_id_userdata userdata; userdata.monitor = monitor; userdata.rotation = GSR_MONITOR_ROT_0; userdata.match_found = false; - for_each_active_monitor_output_wayland(egl, get_monitor_by_name_and_size_callback, &userdata); + gsr_window_for_each_active_monitor_output_cached(window, get_monitor_by_name_and_size_callback, &userdata); if(userdata.match_found) return userdata.rotation; } @@ -358,7 +330,7 @@ gsr_monitor_rotation drm_monitor_get_display_server_rotation(const gsr_egl *egl, userdata.monitor = monitor; userdata.rotation = GSR_MONITOR_ROT_0; userdata.match_found = false; - for_each_active_monitor_output_wayland(egl, get_monitor_by_connector_id_callback, &userdata); + gsr_window_for_each_active_monitor_output_cached(window, get_monitor_by_connector_id_callback, &userdata); return userdata.rotation; } } else { @@ -366,7 +338,7 @@ gsr_monitor_rotation drm_monitor_get_display_server_rotation(const gsr_egl *egl, userdata.monitor = monitor; userdata.rotation = GSR_MONITOR_ROT_0; userdata.match_found = false; - for_each_active_monitor_output_x11(egl, get_monitor_by_connector_id_callback, &userdata); + gsr_window_for_each_active_monitor_output_cached(window, get_monitor_by_connector_id_callback, &userdata); return userdata.rotation; } @@ -378,9 +350,13 @@ bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info) { bool supported = true; const unsigned char *gl_vendor = egl->glGetString(GL_VENDOR); const unsigned char *gl_renderer = egl->glGetString(GL_RENDERER); + const unsigned char *gl_version = egl->glGetString(GL_VERSION); info->gpu_version = 0; info->is_steam_deck = false; + info->driver_major = 0; + info->driver_minor = 0; + info->driver_patch = 0; if(!gl_vendor) { fprintf(stderr, "gsr error: failed to get gpu vendor\n"); @@ -418,11 +394,34 @@ bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info) { info->is_steam_deck = strstr((const char*)gl_renderer, "vangogh") != NULL; } + if(gl_version) { + const char *mesa_p = strstr((const char*)gl_version, "Mesa "); + if(mesa_p) { + mesa_p += 5; + int major = 0; + int minor = 0; + int patch = 0; + if(sscanf(mesa_p, "%d.%d.%d", &major, &minor, &patch) == 3) { + info->driver_major = major; + info->driver_minor = minor; + info->driver_patch = patch; + } + } + } + end: return supported; } -static bool try_card_has_valid_plane(const char *card_path) { +bool version_greater_than(int major, int minor, int patch, int other_major, int other_minor, int other_patch) { + return (major > other_major) || (major == other_major && minor > other_minor) || (major == other_major && minor == other_minor && patch > other_patch); +} + +bool gl_driver_version_greater_than(const gsr_gpu_info *gpu_info, int major, int minor, int patch) { + return version_greater_than(gpu_info->driver_major, gpu_info->driver_minor, gpu_info->driver_patch, major, minor, patch); +} + +bool try_card_has_valid_plane(const char *card_path) { drmVersion *ver = NULL; drmModePlaneResPtr planes = NULL; bool found_screen_card = false; @@ -841,7 +840,7 @@ bool vaapi_copy_egl_image_to_video_surface(gsr_egl *egl, EGLImage image, vec2i s } if(texture_num_planes <= 0 || texture_num_planes > 8) { - fprintf(stderr, "gsr error: gsr_capture_xcomposite_vaapi_tick: expected planes size to be 0<planes<8 for drm buf, got %d planes\n", texture_num_planes); + fprintf(stderr, "gsr error: gsr_capture_xcomposite_vaapi_tick: expected planes size to be 0<planes<=8 for drm buf, got %d planes\n", texture_num_planes); return false; } |