1
0
Fork 0

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);
}
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
load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native,
MetaCrtcKms *crtc_kms,
@ -614,23 +706,15 @@ load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native,
MetaKmsCrtc *kms_crtc;
uint64_t cursor_width, cursor_height;
g_autoptr (MetaDrmBuffer) buffer = NULL;
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
g_autoptr (MetaDeviceFile) device_file = NULL;
g_autoptr (GError) error = NULL;
graphene_point_t hotspot;
cursor_renderer_gpu_data =
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
if (!cursor_renderer_gpu_data)
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)
if (!get_optimal_cursor_size (crtc_kms,
width, height,
&cursor_width, &cursor_height))
{
meta_warning ("Invalid theme cursor size (must be at most %ux%u)",
(unsigned int)cursor_width, (unsigned int)cursor_height);
meta_warning ("Can't handle cursor size %ux%u)", width, height);
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));
MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
uint64_t cursor_width, cursor_height;
CoglTexture *texture;
uint width, height;
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
* memory (and possibly tiled too), so if we don't get the right size, we
* 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);
width = cogl_texture_get_width (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;
}

View file

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

View file

@ -56,11 +56,19 @@ struct _MetaKmsPlane
*/
GHashTable *formats_modifiers;
MetaKmsPlaneCursorSizeHints size_hints;
MetaKmsPlanePropTable prop_table;
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)
MetaKmsDevice *
@ -83,6 +91,12 @@ meta_kms_plane_get_plane_type (MetaKmsPlane *plane)
return plane->type;
}
const MetaKmsPlaneCursorSizeHints *
meta_kms_plane_get_cursor_size_hints (MetaKmsPlane *plane)
{
return &plane->size_hints;
}
uint32_t
meta_kms_plane_get_prop_id (MetaKmsPlane *plane,
MetaKmsPlaneProp prop)
@ -348,6 +362,48 @@ update_formats (MetaKmsPlane *plane,
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
set_formats_from_array (MetaKmsPlane *plane,
const uint32_t *formats,
@ -426,6 +482,7 @@ meta_kms_plane_read_state (MetaKmsPlane *plane,
META_KMS_PLANE_N_PROPS);
update_formats (plane, impl_device);
update_cursor_size_hints (plane, impl_device);
update_rotations (plane);
update_legacy_formats (plane, drm_plane);
@ -534,6 +591,11 @@ init_properties (MetaKmsPlane *plane,
.name = "HOTSPOT_Y",
.type = DRM_MODE_PROP_SIGNED_RANGE,
},
[META_KMS_PLANE_PROP_SIZE_HINTS] =
{
.name = "SIZE_HINTS",
.type = DRM_MODE_PROP_BLOB,
},
},
.rotation_bitmask = {
[META_KMS_PLANE_ROTATION_BIT_ROTATE_0] =
@ -627,6 +689,8 @@ meta_kms_plane_finalize (GObject *object)
MetaKmsPlane *plane = META_KMS_PLANE (object);
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);
}

View file

@ -31,6 +31,14 @@ enum _MetaKmsPlaneType
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 ()
G_DECLARE_FINAL_TYPE (MetaKmsPlane, meta_kms_plane,
META, KMS_PLANE, GObject)
@ -44,6 +52,9 @@ uint32_t meta_kms_plane_get_id (MetaKmsPlane *plane);
META_EXPORT_TEST
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,
MetaMonitorTransform transform);