kms: fix incorrect capture region on intel when playing a fullscreen game with a lower resolution (on some wayland compositors)

This commit is contained in:
dec05eba
2025-11-17 23:54:09 +01:00
parent cc43ca0336
commit 92f4bd5f95
4 changed files with 22 additions and 24 deletions

2
TODO
View File

@@ -61,8 +61,6 @@ Remove follow focused option.
Exit if X11/Wayland killed (if drm plane dead or something?) Exit if X11/Wayland killed (if drm plane dead or something?)
Use SRC_W and SRC_H for screen plane instead of crtc_w and crtc_h.
Test if p2 state can be worked around by using pure nvenc api and overwriting cuInit/cuCtxCreate* to not do anything. Cuda might be loaded when using nvenc but it might not be used, with certain record options? (such as h264 p5). Test if p2 state can be worked around by using pure nvenc api and overwriting cuInit/cuCtxCreate* to not do anything. Cuda might be loaded when using nvenc but it might not be used, with certain record options? (such as h264 p5).
nvenc uses cuda when using b frames and rgb->yuv conversion, so convert the image ourselves instead.- nvenc uses cuda when using b frames and rgb->yuv conversion, so convert the image ourselves instead.-

View File

@@ -59,8 +59,8 @@ struct gsr_kms_response_item {
gsr_kms_rotation rotation; gsr_kms_rotation rotation;
int x; int x;
int y; int y;
int crtc_w; int src_w;
int crtc_h; int src_h;
struct hdr_output_metadata hdr_metadata; struct hdr_output_metadata hdr_metadata;
}; };

View File

@@ -141,21 +141,21 @@ typedef enum {
PLANE_PROPERTY_Y = 1 << 1, PLANE_PROPERTY_Y = 1 << 1,
PLANE_PROPERTY_SRC_X = 1 << 2, PLANE_PROPERTY_SRC_X = 1 << 2,
PLANE_PROPERTY_SRC_Y = 1 << 3, PLANE_PROPERTY_SRC_Y = 1 << 3,
PLANE_PROPERTY_CRTC_W = 1 << 4, PLANE_PROPERTY_SRC_W = 1 << 4,
PLANE_PROPERTY_CRTC_H = 1 << 5, PLANE_PROPERTY_SRC_H = 1 << 5,
PLANE_PROPERTY_IS_CURSOR = 1 << 6, PLANE_PROPERTY_IS_CURSOR = 1 << 6,
PLANE_PROPERTY_IS_PRIMARY = 1 << 7, PLANE_PROPERTY_IS_PRIMARY = 1 << 7,
PLANE_PROPERTY_ROTATION = 1 << 8, PLANE_PROPERTY_ROTATION = 1 << 8,
} plane_property_mask; } plane_property_mask;
/* Returns plane_property_mask */ /* Returns plane_property_mask */
static uint32_t plane_get_properties(int drmfd, uint32_t plane_id, int *x, int *y, int *src_x, int *src_y, int *crtc_w, int *crtc_h, gsr_kms_rotation *rotation) { static uint32_t plane_get_properties(int drmfd, uint32_t plane_id, int *x, int *y, int *src_x, int *src_y, int *src_w, int *src_h, gsr_kms_rotation *rotation) {
*x = 0; *x = 0;
*y = 0; *y = 0;
*src_x = 0; *src_x = 0;
*src_y = 0; *src_y = 0;
*crtc_w = 0; *src_w = 0;
*crtc_h = 0; *src_h = 0;
*rotation = KMS_ROT_0; *rotation = KMS_ROT_0;
plane_property_mask property_mask = 0; plane_property_mask property_mask = 0;
@@ -184,12 +184,12 @@ static uint32_t plane_get_properties(int drmfd, uint32_t plane_id, int *x, int *
} else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "SRC_Y") == 0) { } else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "SRC_Y") == 0) {
*src_y = (int)(props->prop_values[i] >> 16); *src_y = (int)(props->prop_values[i] >> 16);
property_mask |= PLANE_PROPERTY_SRC_Y; property_mask |= PLANE_PROPERTY_SRC_Y;
} else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "CRTC_W") == 0) { } else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "SRC_W") == 0) {
*crtc_w = props->prop_values[i]; *src_w = props->prop_values[i];
property_mask |= PLANE_PROPERTY_CRTC_W; property_mask |= PLANE_PROPERTY_SRC_W;
} else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "CRTC_H") == 0) { } else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "SRC_H") == 0) {
*crtc_h = props->prop_values[i]; *src_h = props->prop_values[i];
property_mask |= PLANE_PROPERTY_CRTC_H; property_mask |= PLANE_PROPERTY_SRC_H;
} else if((type & DRM_MODE_PROP_ENUM) && strcmp(prop->name, "type") == 0) { } else if((type & DRM_MODE_PROP_ENUM) && strcmp(prop->name, "type") == 0) {
const uint64_t current_enum_value = props->prop_values[i]; const uint64_t current_enum_value = props->prop_values[i];
for(int j = 0; j < prop->count_enums; ++j) { for(int j = 0; j < prop->count_enums; ++j) {
@@ -351,9 +351,9 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response) {
// TODO: Check if dimensions have changed by comparing width and height to previous time this was called. // TODO: Check if dimensions have changed by comparing width and height to previous time this was called.
// TODO: Support other plane formats than rgb (with multiple planes, such as direct YUV420 on wayland). // TODO: Support other plane formats than rgb (with multiple planes, such as direct YUV420 on wayland).
int x = 0, y = 0, src_x = 0, src_y = 0, crtc_w = 0, crtc_h = 0; int x = 0, y = 0, src_x = 0, src_y = 0, src_w = 0, src_h = 0;
gsr_kms_rotation rotation = KMS_ROT_0; gsr_kms_rotation rotation = KMS_ROT_0;
const uint32_t property_mask = plane_get_properties(drm->drmfd, plane->plane_id, &x, &y, &src_x, &src_y, &crtc_w, &crtc_h, &rotation); const uint32_t property_mask = plane_get_properties(drm->drmfd, plane->plane_id, &x, &y, &src_x, &src_y, &src_w, &src_h, &rotation);
if(!(property_mask & PLANE_PROPERTY_IS_PRIMARY) && !(property_mask & PLANE_PROPERTY_IS_CURSOR)) if(!(property_mask & PLANE_PROPERTY_IS_PRIMARY) && !(property_mask & PLANE_PROPERTY_IS_CURSOR))
continue; continue;
@@ -392,13 +392,13 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response) {
if(property_mask & PLANE_PROPERTY_IS_CURSOR) { if(property_mask & PLANE_PROPERTY_IS_CURSOR) {
response->items[item_index].x = x; response->items[item_index].x = x;
response->items[item_index].y = y; response->items[item_index].y = y;
response->items[item_index].crtc_w = 0; response->items[item_index].src_w = 0;
response->items[item_index].crtc_h = 0; response->items[item_index].src_h = 0;
} else { } else {
response->items[item_index].x = src_x; response->items[item_index].x = src_x;
response->items[item_index].y = src_y; response->items[item_index].y = src_y;
response->items[item_index].crtc_w = crtc_w; response->items[item_index].src_w = src_w;
response->items[item_index].crtc_h = crtc_h; response->items[item_index].src_h = src_h;
} }
++response->num_items; ++response->num_items;

View File

@@ -542,7 +542,7 @@ static void render_x11_cursor(gsr_capture_kms *self, gsr_color_conversion *color
} }
static void gsr_capture_kms_update_capture_size_change(gsr_capture_kms *self, gsr_color_conversion *color_conversion, vec2i target_pos, const gsr_kms_response_item *drm_fd) { static void gsr_capture_kms_update_capture_size_change(gsr_capture_kms *self, gsr_color_conversion *color_conversion, vec2i target_pos, const gsr_kms_response_item *drm_fd) {
if(target_pos.x != self->prev_target_pos.x || target_pos.y != self->prev_target_pos.y || drm_fd->crtc_w != self->prev_plane_size.x || drm_fd->crtc_h != self->prev_plane_size.y) { if(target_pos.x != self->prev_target_pos.x || target_pos.y != self->prev_target_pos.y || drm_fd->src_w != self->prev_plane_size.x || drm_fd->src_h != self->prev_plane_size.y) {
self->prev_target_pos = target_pos; self->prev_target_pos = target_pos;
self->prev_plane_size = self->capture_size; self->prev_plane_size = self->capture_size;
gsr_color_conversion_clear(color_conversion); gsr_color_conversion_clear(color_conversion);
@@ -621,7 +621,7 @@ static int gsr_capture_kms_capture(gsr_capture *cap, gsr_capture_metadata *captu
if(drm_fd->has_hdr_metadata && self->params.hdr && hdr_metadata_is_supported_format(&drm_fd->hdr_metadata)) if(drm_fd->has_hdr_metadata && self->params.hdr && hdr_metadata_is_supported_format(&drm_fd->hdr_metadata))
gsr_kms_set_hdr_metadata(self, drm_fd); gsr_kms_set_hdr_metadata(self, drm_fd);
self->capture_size = rotate_capture_size_if_rotated(self, (vec2i){ drm_fd->crtc_w, drm_fd->crtc_h }); self->capture_size = rotate_capture_size_if_rotated(self, (vec2i){ drm_fd->src_w, drm_fd->src_h });
if(self->params.region_size.x > 0 && self->params.region_size.y > 0) if(self->params.region_size.x > 0 && self->params.region_size.y > 0)
self->capture_size = self->params.region_size; self->capture_size = self->params.region_size;
@@ -665,7 +665,7 @@ static int gsr_capture_kms_capture(gsr_capture *cap, gsr_capture_metadata *captu
cursor_monitor_offset.y += self->params.region_position.y; cursor_monitor_offset.y += self->params.region_position.y;
render_x11_cursor(self, color_conversion, cursor_monitor_offset, target_pos, output_size); render_x11_cursor(self, color_conversion, cursor_monitor_offset, target_pos, output_size);
} else if(cursor_drm_fd) { } else if(cursor_drm_fd) {
const vec2i framebuffer_size = rotate_capture_size_if_rotated(self, (vec2i){ drm_fd->crtc_w, drm_fd->crtc_h }); const vec2i framebuffer_size = rotate_capture_size_if_rotated(self, (vec2i){ drm_fd->src_w, drm_fd->src_h });
render_drm_cursor(self, color_conversion, cursor_drm_fd, target_pos, output_size, framebuffer_size); render_drm_cursor(self, color_conversion, cursor_drm_fd, target_pos, output_size, framebuffer_size);
} }
} }