From 22a0a01553debd549e1f1f0058bc516cec28196b Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 22 Jul 2023 02:57:38 +0200 Subject: AMD/Intel capture cursor --- kms/kms_shared.h | 5 +++ kms/server/kms_server.c | 107 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 89 insertions(+), 23 deletions(-) (limited to 'kms') diff --git a/kms/kms_shared.h b/kms/kms_shared.h index e0687b2..616af43 100644 --- a/kms/kms_shared.h +++ b/kms/kms_shared.h @@ -31,6 +31,11 @@ typedef struct { uint64_t modifier; uint32_t connector_id; /* 0 if unknown */ bool is_combined_plane; + bool is_cursor; + int x; + int y; + int src_w; + int src_h; } gsr_kms_response_fd; typedef struct { diff --git a/kms/server/kms_server.c b/kms/server/kms_server.c index 4ed11fa..33f5dd4 100644 --- a/kms/server/kms_server.c +++ b/kms/server/kms_server.c @@ -85,7 +85,28 @@ static bool connector_get_property_by_name(int drmfd, drmModeConnectorPtr props, return false; } -static bool plane_is_cursor_plane(int drmfd, uint32_t plane_id) { +typedef enum { + PLANE_PROPERTY_X = 1 << 0, + PLANE_PROPERTY_Y = 1 << 1, + PLANE_PROPERTY_SRC_X = 1 << 2, + PLANE_PROPERTY_SRC_Y = 1 << 3, + PLANE_PROPERTY_SRC_W = 1 << 4, + PLANE_PROPERTY_SRC_H = 1 << 5, + PLANE_PROPERTY_IS_CURSOR = 1 << 6, +} plane_property_mask; + +/* Returns plane_property_mask */ +static uint32_t plane_get_properties(int drmfd, uint32_t plane_id, bool *is_cursor, int *x, int *y, int *src_x, int *src_y, int *src_w, int *src_h) { + *is_cursor = false; + *x = 0; + *y = 0; + *src_x = 0; + *src_y = 0; + *src_w = 0; + *src_h = 0; + + plane_property_mask property_mask = 0; + drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(drmfd, plane_id, DRM_MODE_OBJECT_PLANE); if(!props) return false; @@ -95,26 +116,42 @@ static bool plane_is_cursor_plane(int drmfd, uint32_t plane_id) { if(!prop) continue; + // SRC_* values are fixed 16.16 points const uint32_t type = prop->flags & (DRM_MODE_PROP_LEGACY_TYPE | DRM_MODE_PROP_EXTENDED_TYPE); - if((type & DRM_MODE_PROP_ENUM) && strcmp(prop->name, "type") == 0) { + if((type & DRM_MODE_PROP_SIGNED_RANGE) && strcmp(prop->name, "CRTC_X") == 0) { + *x = (int)props->prop_values[i]; + property_mask |= PLANE_PROPERTY_X; + } else if((type & DRM_MODE_PROP_SIGNED_RANGE) && strcmp(prop->name, "CRTC_Y") == 0) { + *y = (int)props->prop_values[i]; + property_mask |= PLANE_PROPERTY_Y; + } else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "SRC_X") == 0) { + *src_x = (int)(props->prop_values[i] >> 16); + property_mask |= PLANE_PROPERTY_SRC_X; + } else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "SRC_Y") == 0) { + *src_y = (int)(props->prop_values[i] >> 16); + property_mask |= PLANE_PROPERTY_SRC_Y; + } else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "SRC_W") == 0) { + *src_w = (int)(props->prop_values[i] >> 16); + property_mask |= PLANE_PROPERTY_SRC_W; + } else if((type & DRM_MODE_PROP_RANGE) && strcmp(prop->name, "SRC_H") == 0) { + *src_h = (int)(props->prop_values[i] >> 16); + property_mask |= PLANE_PROPERTY_SRC_H; + } else if((type & DRM_MODE_PROP_ENUM) && strcmp(prop->name, "type") == 0) { const uint64_t current_enum_value = props->prop_values[i]; - bool is_cursor = false; - for(int j = 0; j < prop->count_enums; ++j) { if(prop->enums[j].value == current_enum_value && strcmp(prop->enums[j].name, "Cursor") == 0) { - is_cursor = true; + *is_cursor = true; + property_mask |= PLANE_PROPERTY_IS_CURSOR; break; } } - - drmModeFreeProperty(prop); - return is_cursor; } + drmModeFreeProperty(prop); } drmModeFreeObjectProperties(props); - return false; + return property_mask; } /* Returns 0 if not found */ @@ -175,22 +212,27 @@ static int kms_get_plane_ids(gsr_drm *drm) { continue; } - if(!plane->fb_id) - goto next; - - if(plane_is_cursor_plane(drm->drmfd, plane->plane_id)) - goto next; - - // TODO: Fallback to getfb(1)? - drmfb = drmModeGetFB2(drm->drmfd, plane->fb_id); - if(drmfb) { - drm->plane_ids[drm->num_plane_ids] = plane->plane_id; - drm->connector_ids[drm->num_plane_ids] = get_connector_by_crtc_id(&c2crtc_map, plane->crtc_id); - ++drm->num_plane_ids; - drmModeFreeFB2(drmfb); + if(plane->fb_id) { + // TODO: Fallback to getfb(1)? + drmfb = drmModeGetFB2(drm->drmfd, plane->fb_id); + if(drmfb) { + drm->plane_ids[drm->num_plane_ids] = plane->plane_id; + drm->connector_ids[drm->num_plane_ids] = get_connector_by_crtc_id(&c2crtc_map, plane->crtc_id); + ++drm->num_plane_ids; + if(drmfb) + drmModeFreeFB2(drmfb); + } + } else { + bool is_cursor = false; + int x = 0, y = 0, src_x = 0, src_y = 0, src_w = 0, src_h = 0; + plane_get_properties(drm->drmfd, plane->plane_id, &is_cursor, &x, &y, &src_x, &src_y, &src_w, &src_h); + if(is_cursor) { + drm->plane_ids[drm->num_plane_ids] = plane->plane_id; + drm->connector_ids[drm->num_plane_ids] = 0; + ++drm->num_plane_ids; + } } - next: drmModeFreePlane(plane); } @@ -230,6 +272,9 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response) { goto next; } + if(!plane->fb_id) + goto next; + drmfb = drmModeGetFB2(drm->drmfd, plane->fb_id); if(!drmfb) { // Commented out for now because we get here if the cursor is moved to another monitor and we dont care about the cursor @@ -258,6 +303,10 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response) { continue; } + bool is_cursor = false; + int x = 0, y = 0, src_x = 0, src_y = 0, src_w = 0, src_h = 0; + plane_get_properties(drm->drmfd, plane->plane_id, &is_cursor, &x, &y, &src_x, &src_y, &src_w, &src_h); + response->fds[response->num_fds].fd = fb_fd; response->fds[response->num_fds].width = drmfb->width; response->fds[response->num_fds].height = drmfb->height; @@ -267,6 +316,18 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response) { response->fds[response->num_fds].modifier = drmfb->modifier; response->fds[response->num_fds].connector_id = drm->connector_ids[i]; response->fds[response->num_fds].is_combined_plane = drmfb_has_multiple_handles(drmfb); + response->fds[response->num_fds].is_cursor = is_cursor; + if(response->fds[response->num_fds].is_cursor) { + response->fds[response->num_fds].x = x; + response->fds[response->num_fds].y = y; + response->fds[response->num_fds].src_w = 0; + response->fds[response->num_fds].src_h = 0; + } else { + response->fds[response->num_fds].x = src_x; + response->fds[response->num_fds].y = src_y; + response->fds[response->num_fds].src_w = src_w; + response->fds[response->num_fds].src_h = src_h; + } ++response->num_fds; next: -- cgit v1.2.3