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:
parent
297ae74771
commit
0ca933baec
4 changed files with 174 additions and 18 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue