backend/native: Adds support for SIZE_HINTS Cursor Plane Property

Reads exposed size hints for the given cursor plane. Chooses nearest
minimum cursor size out of the hints with respect to the user chosen
cursor size from the UI. Allocates optimized Hardare cursor size,
hence drm buffer

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3165>
This commit is contained in:
adarshgm 2023-08-18 05:24:54 +00:00 committed by Marge Bot
parent 297ae74771
commit 0ca933baec
4 changed files with 174 additions and 18 deletions

View File

@ -590,6 +590,98 @@ calculate_crtc_cursor_hotspot (MetaCursorSprite *cursor_sprite,
*hotspot = GRAPHENE_POINT_INIT (hot_x * scale, hot_y * scale); *hotspot = GRAPHENE_POINT_INIT (hot_x * scale, hot_y * scale);
} }
static gboolean
get_optimal_cursor_size (MetaCrtcKms *crtc_kms,
int required_width,
int required_height,
uint64_t *out_cursor_width,
uint64_t *out_cursor_height)
{
MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms));
MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
MetaKmsPlane *kms_plane;
const MetaKmsPlaneCursorSizeHints *size_hints;
size_t i;
cursor_renderer_gpu_data =
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
if (!cursor_renderer_gpu_data)
return FALSE;
kms_plane = meta_crtc_kms_get_assigned_cursor_plane (crtc_kms);
if (!kms_plane)
return FALSE;
size_hints = meta_kms_plane_get_cursor_size_hints (kms_plane);
for (i = 0; i < size_hints->num_of_size_hints; i++)
{
if (size_hints->cursor_width[i] >= required_width &&
size_hints->cursor_height[i] >= required_height)
{
*out_cursor_width = size_hints->cursor_width[i];
*out_cursor_height = size_hints->cursor_height[i];
return TRUE;
}
}
if (!size_hints->has_size_hints &&
cursor_renderer_gpu_data->cursor_width >= required_width &&
cursor_renderer_gpu_data->cursor_height >= required_height)
{
*out_cursor_width = cursor_renderer_gpu_data->cursor_width;
*out_cursor_height = cursor_renderer_gpu_data->cursor_height;
return TRUE;
}
return FALSE;
}
static gboolean
supports_exact_cursor_size (MetaCrtcKms *crtc_kms,
int required_width,
int required_height)
{
MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms));
MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
MetaKmsPlane *kms_plane;
const MetaKmsPlaneCursorSizeHints *size_hints;
size_t i;
cursor_renderer_gpu_data =
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
if (!cursor_renderer_gpu_data)
return FALSE;
kms_plane = meta_crtc_kms_get_assigned_cursor_plane (crtc_kms);
if (!kms_plane)
return FALSE;
size_hints = meta_kms_plane_get_cursor_size_hints (kms_plane);
for (i = 0; i < size_hints->num_of_size_hints; i++)
{
if (size_hints->cursor_width[i] == required_width &&
size_hints->cursor_height[i] == required_height)
{
return TRUE;
}
}
if (!size_hints->has_size_hints &&
cursor_renderer_gpu_data->cursor_width == required_width &&
cursor_renderer_gpu_data->cursor_height == required_height)
{
return TRUE;
}
return FALSE;
}
static gboolean static gboolean
load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native, load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native,
MetaCrtcKms *crtc_kms, MetaCrtcKms *crtc_kms,
@ -614,23 +706,15 @@ load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native,
MetaKmsCrtc *kms_crtc; MetaKmsCrtc *kms_crtc;
uint64_t cursor_width, cursor_height; uint64_t cursor_width, cursor_height;
g_autoptr (MetaDrmBuffer) buffer = NULL; g_autoptr (MetaDrmBuffer) buffer = NULL;
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
g_autoptr (MetaDeviceFile) device_file = NULL; g_autoptr (MetaDeviceFile) device_file = NULL;
g_autoptr (GError) error = NULL; g_autoptr (GError) error = NULL;
graphene_point_t hotspot; graphene_point_t hotspot;
cursor_renderer_gpu_data = if (!get_optimal_cursor_size (crtc_kms,
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); width, height,
if (!cursor_renderer_gpu_data) &cursor_width, &cursor_height))
return FALSE;
cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width;
cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height;
if (width > cursor_width || height > cursor_height)
{ {
meta_warning ("Invalid theme cursor size (must be at most %ux%u)", meta_warning ("Can't handle cursor size %ux%u)", width, height);
(unsigned int)cursor_width, (unsigned int)cursor_height);
return FALSE; return FALSE;
} }
@ -834,7 +918,6 @@ realize_cursor_sprite_from_wl_buffer_for_crtc (MetaCursorRenderer *renderer
MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms));
MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
uint64_t cursor_width, cursor_height;
CoglTexture *texture; CoglTexture *texture;
uint width, height; uint width, height;
MetaWaylandBuffer *buffer; MetaWaylandBuffer *buffer;
@ -950,16 +1033,13 @@ realize_cursor_sprite_from_wl_buffer_for_crtc (MetaCursorRenderer *renderer
* access to the data, but it's not possible if the buffer is in GPU * access to the data, but it's not possible if the buffer is in GPU
* memory (and possibly tiled too), so if we don't get the right size, we * memory (and possibly tiled too), so if we don't get the right size, we
* fallback to GL. */ * fallback to GL. */
cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width;
cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height;
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
width = cogl_texture_get_width (texture); width = cogl_texture_get_width (texture);
height = cogl_texture_get_height (texture); height = cogl_texture_get_height (texture);
if (width != cursor_width || height != cursor_height) if (!supports_exact_cursor_size (crtc_kms, width, height))
{ {
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors"); meta_warning ("Invalid cursor size %ux%u, falling back to SW GL cursors)", width, height);
return FALSE; return FALSE;
} }

View File

@ -42,6 +42,7 @@ typedef enum _MetaKmsPlaneProp
META_KMS_PLANE_PROP_IN_FENCE_FD, META_KMS_PLANE_PROP_IN_FENCE_FD,
META_KMS_PLANE_PROP_HOTSPOT_X, META_KMS_PLANE_PROP_HOTSPOT_X,
META_KMS_PLANE_PROP_HOTSPOT_Y, META_KMS_PLANE_PROP_HOTSPOT_Y,
META_KMS_PLANE_PROP_SIZE_HINTS,
META_KMS_PLANE_N_PROPS META_KMS_PLANE_N_PROPS
} MetaKmsPlaneProp; } MetaKmsPlaneProp;

View File

@ -56,11 +56,19 @@ struct _MetaKmsPlane
*/ */
GHashTable *formats_modifiers; GHashTable *formats_modifiers;
MetaKmsPlaneCursorSizeHints size_hints;
MetaKmsPlanePropTable prop_table; MetaKmsPlanePropTable prop_table;
MetaKmsDevice *device; MetaKmsDevice *device;
}; };
/* Shall be removed once available on libdrm.*/
struct drm_plane_size_hint {
__u16 width;
__u16 height;
};
G_DEFINE_TYPE (MetaKmsPlane, meta_kms_plane, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaKmsPlane, meta_kms_plane, G_TYPE_OBJECT)
MetaKmsDevice * MetaKmsDevice *
@ -83,6 +91,12 @@ meta_kms_plane_get_plane_type (MetaKmsPlane *plane)
return plane->type; return plane->type;
} }
const MetaKmsPlaneCursorSizeHints *
meta_kms_plane_get_cursor_size_hints (MetaKmsPlane *plane)
{
return &plane->size_hints;
}
uint32_t uint32_t
meta_kms_plane_get_prop_id (MetaKmsPlane *plane, meta_kms_plane_get_prop_id (MetaKmsPlane *plane,
MetaKmsPlaneProp prop) MetaKmsPlaneProp prop)
@ -348,6 +362,48 @@ update_formats (MetaKmsPlane *plane,
drmModeFreePropertyBlob (blob); drmModeFreePropertyBlob (blob);
} }
static void
update_cursor_size_hints (MetaKmsPlane *plane,
MetaKmsImplDevice *impl_device)
{
MetaKmsProp *prop;
drmModePropertyBlobPtr size_hints_blob = NULL;
struct drm_plane_size_hint *size_hints_ptr;
uint32_t blob_id, i, num_of_size_hints;
int fd;
MetaKmsPlaneType type = meta_kms_plane_get_plane_type (plane);
if (type != META_KMS_PLANE_TYPE_CURSOR)
return;
prop = &plane->prop_table.props[META_KMS_PLANE_PROP_SIZE_HINTS];
if(!prop)
return;
blob_id = prop->value;
if (blob_id == 0)
return;
fd = meta_kms_impl_device_get_fd (impl_device);
size_hints_blob = drmModeGetPropertyBlob (fd, blob_id);
if (!size_hints_blob)
return;
plane->size_hints.has_size_hints = TRUE;
size_hints_ptr = size_hints_blob->data;
num_of_size_hints = size_hints_blob->length / sizeof (struct drm_plane_size_hint);
plane->size_hints.cursor_width = g_new0 (uint64_t, num_of_size_hints);
plane->size_hints.cursor_height = g_new0 (uint64_t, num_of_size_hints);
plane->size_hints.num_of_size_hints = num_of_size_hints;
for (i = 0; i < num_of_size_hints; i++)
{
plane->size_hints.cursor_width [i] = size_hints_ptr[i].width;
plane->size_hints.cursor_height [i] = size_hints_ptr[i].height;
}
}
static void static void
set_formats_from_array (MetaKmsPlane *plane, set_formats_from_array (MetaKmsPlane *plane,
const uint32_t *formats, const uint32_t *formats,
@ -426,6 +482,7 @@ meta_kms_plane_read_state (MetaKmsPlane *plane,
META_KMS_PLANE_N_PROPS); META_KMS_PLANE_N_PROPS);
update_formats (plane, impl_device); update_formats (plane, impl_device);
update_cursor_size_hints (plane, impl_device);
update_rotations (plane); update_rotations (plane);
update_legacy_formats (plane, drm_plane); update_legacy_formats (plane, drm_plane);
@ -534,6 +591,11 @@ init_properties (MetaKmsPlane *plane,
.name = "HOTSPOT_Y", .name = "HOTSPOT_Y",
.type = DRM_MODE_PROP_SIGNED_RANGE, .type = DRM_MODE_PROP_SIGNED_RANGE,
}, },
[META_KMS_PLANE_PROP_SIZE_HINTS] =
{
.name = "SIZE_HINTS",
.type = DRM_MODE_PROP_BLOB,
},
}, },
.rotation_bitmask = { .rotation_bitmask = {
[META_KMS_PLANE_ROTATION_BIT_ROTATE_0] = [META_KMS_PLANE_ROTATION_BIT_ROTATE_0] =
@ -627,6 +689,8 @@ meta_kms_plane_finalize (GObject *object)
MetaKmsPlane *plane = META_KMS_PLANE (object); MetaKmsPlane *plane = META_KMS_PLANE (object);
g_hash_table_destroy (plane->formats_modifiers); g_hash_table_destroy (plane->formats_modifiers);
g_clear_pointer (&plane->size_hints.cursor_width, g_free);
g_clear_pointer (&plane->size_hints.cursor_height, g_free);
G_OBJECT_CLASS (meta_kms_plane_parent_class)->finalize (object); G_OBJECT_CLASS (meta_kms_plane_parent_class)->finalize (object);
} }

View File

@ -31,6 +31,14 @@ enum _MetaKmsPlaneType
META_KMS_PLANE_TYPE_OVERLAY, META_KMS_PLANE_TYPE_OVERLAY,
}; };
typedef struct _MetaKmsPlaneCursorSizeHints
{
gboolean has_size_hints;
uint64_t num_of_size_hints;
uint64_t *cursor_width;
uint64_t *cursor_height;
} MetaKmsPlaneCursorSizeHints;
#define META_TYPE_KMS_PLANE meta_kms_plane_get_type () #define META_TYPE_KMS_PLANE meta_kms_plane_get_type ()
G_DECLARE_FINAL_TYPE (MetaKmsPlane, meta_kms_plane, G_DECLARE_FINAL_TYPE (MetaKmsPlane, meta_kms_plane,
META, KMS_PLANE, GObject) META, KMS_PLANE, GObject)
@ -44,6 +52,9 @@ uint32_t meta_kms_plane_get_id (MetaKmsPlane *plane);
META_EXPORT_TEST META_EXPORT_TEST
MetaKmsPlaneType meta_kms_plane_get_plane_type (MetaKmsPlane *plane); MetaKmsPlaneType meta_kms_plane_get_plane_type (MetaKmsPlane *plane);
const MetaKmsPlaneCursorSizeHints *
meta_kms_plane_get_cursor_size_hints (MetaKmsPlane *plane);
gboolean meta_kms_plane_is_transform_handled (MetaKmsPlane *plane, gboolean meta_kms_plane_is_transform_handled (MetaKmsPlane *plane,
MetaMonitorTransform transform); MetaMonitorTransform transform);