cursor-renderer/native: Add support for viewports

[jadahl] Rework hotspot calculations

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3859>
This commit is contained in:
Robert Mader 2024-07-01 00:09:02 +02:00 committed by Sebastian Wick
parent e674c7e454
commit 19669a3d9d

View File

@ -188,22 +188,6 @@ meta_cursor_renderer_native_finalize (GObject *object)
G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
}
static float
calculate_cursor_crtc_sprite_scale (MetaBackend *backend,
MetaCursorSprite *cursor_sprite,
MetaLogicalMonitor *logical_monitor)
{
if (meta_backend_is_stage_views_scaled (backend))
{
return (meta_logical_monitor_get_scale (logical_monitor) *
meta_cursor_sprite_get_texture_scale (cursor_sprite));
}
else
{
return meta_cursor_sprite_get_texture_scale (cursor_sprite);
}
}
static void
disable_hw_cursor_for_gpu (MetaGpuKms *gpu_kms,
const GError *error)
@ -575,24 +559,6 @@ create_cursor_drm_buffer (MetaGpuKms *gpu_kms,
}
}
static void
calculate_crtc_cursor_hotspot (MetaCursorSprite *cursor_sprite,
float scale,
MtkMonitorTransform transform,
graphene_point_t *hotspot)
{
int hot_x, hot_y;
int width, height;
meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
width = meta_cursor_sprite_get_width (cursor_sprite);
height = meta_cursor_sprite_get_height (cursor_sprite);
mtk_monitor_transform_transform_point (transform,
&width, &height,
&hot_x, &hot_y);
*hotspot = GRAPHENE_POINT_INIT (hot_x * scale, hot_y * scale);
}
static gboolean
get_optimal_cursor_size (MetaCrtcKms *crtc_kms,
int required_width,
@ -693,7 +659,7 @@ load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native,
uint width,
uint height,
int rowstride,
float scale,
graphene_point_t *hotspot,
MtkMonitorTransform transform,
uint32_t gbm_format)
{
@ -711,7 +677,6 @@ load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native,
g_autoptr (MetaDrmBuffer) buffer = NULL;
g_autoptr (MetaDeviceFile) device_file = NULL;
g_autoptr (GError) error = NULL;
graphene_point_t hotspot;
if (!get_optimal_cursor_size (crtc_kms,
width, height,
@ -748,29 +713,28 @@ load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native,
return FALSE;
}
calculate_crtc_cursor_hotspot (cursor_sprite, scale, transform, &hotspot);
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
meta_kms_cursor_manager_update_sprite (kms_cursor_manager,
kms_crtc,
buffer,
transform,
&hotspot);
hotspot);
return TRUE;
}
static CoglTexture *
scale_and_transform_cursor_sprite_cpu (MetaCursorRendererNative *cursor_renderer_native,
ClutterColorState *target_color_state,
MetaCursorSprite *cursor_sprite,
uint8_t *pixels,
CoglPixelFormat pixel_format,
int width,
int height,
int rowstride,
float scale,
MtkMonitorTransform transform,
GError **error)
scale_and_transform_cursor_sprite_cpu (MetaCursorRendererNative *cursor_renderer_native,
ClutterColorState *target_color_state,
MetaCursorSprite *cursor_sprite,
uint8_t *pixels,
CoglPixelFormat pixel_format,
int width,
int height,
int rowstride,
const graphene_matrix_t *matrix,
int dst_width,
int dst_height,
GError **error)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
@ -781,14 +745,7 @@ scale_and_transform_cursor_sprite_cpu (MetaCursorRendererNative *cursor_rendere
g_autoptr (CoglTexture) dst_texture = NULL;
g_autoptr (CoglOffscreen) offscreen = NULL;
g_autoptr (CoglPipeline) pipeline = NULL;
graphene_matrix_t matrix;
MtkMonitorTransform pipeline_transform;
ClutterColorState *color_state;
int dst_width;
int dst_height;
dst_width = (int) ceilf (width * scale);
dst_height = (int) ceilf (height * scale);
src_texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
@ -809,11 +766,8 @@ scale_and_transform_cursor_sprite_cpu (MetaCursorRendererNative *cursor_rendere
pipeline = cogl_pipeline_new (cogl_context);
graphene_matrix_init_identity (&matrix);
pipeline_transform = mtk_monitor_transform_invert (transform);
mtk_monitor_transform_transform_matrix (pipeline_transform, &matrix);
cogl_pipeline_set_layer_texture (pipeline, 0, src_texture);
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
cogl_pipeline_set_layer_matrix (pipeline, 0, matrix);
color_state = meta_cursor_sprite_get_color_state (cursor_sprite);
clutter_color_state_add_pipeline_transform (color_state,
@ -849,29 +803,108 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native,
MetaCrtc *crtc = META_CRTC (crtc_kms);
MetaLogicalMonitor *logical_monitor;
MetaMonitor *monitor;
float monitor_scale;
MtkMonitorTransform logical_transform;
float relative_scale;
float relative_scale_x;
float relative_scale_y;
float cursor_scale;
MtkMonitorTransform cursor_transform;
MtkMonitorTransform relative_transform;
MtkMonitorTransform pipeline_transform;
const graphene_rect_t *src_rect;
graphene_matrix_t matrix;
CoglTexture *sprite_texture;
int tex_width, tex_height;
int dst_width;
int dst_height;
int crtc_dst_width;
int crtc_dst_height;
ClutterColorState *cursor_color_state;
gboolean retval = FALSE;
graphene_point_t hotspot;
int hot_x, hot_y;
monitor = meta_output_get_monitor (meta_crtc_get_outputs (crtc)->data);
logical_monitor = meta_monitor_get_logical_monitor (monitor);
relative_scale = calculate_cursor_crtc_sprite_scale (priv->backend,
cursor_sprite,
logical_monitor);
logical_transform = meta_logical_monitor_get_transform (logical_monitor);
cursor_transform = meta_cursor_sprite_get_texture_transform (cursor_sprite);
relative_transform = mtk_monitor_transform_transform (
mtk_monitor_transform_invert (
meta_cursor_sprite_get_texture_transform (cursor_sprite)),
mtk_monitor_transform_invert (cursor_transform),
meta_monitor_logical_to_crtc_transform (monitor, logical_transform));
src_rect = meta_cursor_sprite_get_viewport_src_rect (cursor_sprite);
sprite_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
tex_width = cogl_texture_get_width (sprite_texture);
tex_height = cogl_texture_get_height (sprite_texture);
if (meta_backend_is_stage_views_scaled (priv->backend))
monitor_scale = meta_logical_monitor_get_scale (logical_monitor);
else
monitor_scale = 1.0f;
if (meta_cursor_sprite_get_viewport_dst_size (cursor_sprite,
&dst_width,
&dst_height))
{
float scale_x;
float scale_y;
scale_x = (float) dst_width / tex_width;
scale_y = (float) dst_height / tex_height;
relative_scale_x = scale_x * monitor_scale;
relative_scale_y = scale_y * monitor_scale;
crtc_dst_width = (int) ceilf (dst_width * monitor_scale);
crtc_dst_height = (int) ceilf (dst_height * monitor_scale);
}
else if (src_rect)
{
relative_scale_x = monitor_scale;
relative_scale_y = monitor_scale;
crtc_dst_width = (int) ceilf (src_rect->size.width * relative_scale_x);
crtc_dst_height = (int) ceilf (src_rect->size.height * relative_scale_y);
}
else
{
relative_scale_x = relative_scale_y =
monitor_scale * meta_cursor_sprite_get_texture_scale (cursor_sprite);
if (mtk_monitor_transform_is_rotated (cursor_transform))
{
crtc_dst_width = (int) ceilf (height * relative_scale_x);
crtc_dst_height = (int) ceilf (width * relative_scale_y);
}
else
{
crtc_dst_width = (int) ceilf (width * relative_scale_x);
crtc_dst_height = (int) ceilf (height * relative_scale_y);
}
}
graphene_matrix_init_identity (&matrix);
pipeline_transform = mtk_monitor_transform_invert (relative_transform);
cursor_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite);
mtk_compute_viewport_matrix (&matrix,
width,
height,
cursor_scale,
pipeline_transform,
src_rect);
cursor_color_state = meta_cursor_sprite_get_color_state (cursor_sprite);
if (!G_APPROX_VALUE (relative_scale, 1.f, FLT_EPSILON) ||
relative_transform != MTK_MONITOR_TRANSFORM_NORMAL ||
meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
hot_x = (int) roundf (hot_x * relative_scale_x);
hot_y = (int) roundf (hot_y * relative_scale_y);
mtk_monitor_transform_transform_point (relative_transform,
&crtc_dst_width, &crtc_dst_height,
&hot_x, &hot_y);
hotspot = GRAPHENE_POINT_INIT (hot_x, hot_y);
if (width != crtc_dst_width || height != crtc_dst_height ||
!graphene_matrix_is_identity (&matrix) ||
gbm_format != GBM_FORMAT_ARGB8888 ||
!clutter_color_state_equals (cursor_color_state, target_color_state))
{
@ -880,7 +913,7 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native,
g_autoptr (CoglTexture) texture = NULL;
g_autofree uint8_t *cursor_data = NULL;
int bpp;
int cursor_width, cursor_height, cursor_rowstride;
int cursor_rowstride;
format_info = meta_format_info_from_drm_format (gbm_format);
if (!format_info)
@ -894,8 +927,9 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native,
width,
height,
rowstride,
relative_scale,
relative_transform,
&matrix,
crtc_dst_width,
crtc_dst_height,
&error);
if (!texture)
{
@ -907,10 +941,8 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native,
bpp =
cogl_pixel_format_get_bytes_per_pixel (COGL_PIXEL_FORMAT_BGRA_8888_PRE,
0);
cursor_width = cogl_texture_get_width (texture);
cursor_height = cogl_texture_get_height (texture);
cursor_rowstride = cursor_width * bpp;
cursor_data = g_malloc (cursor_height * cursor_rowstride);
cursor_rowstride = crtc_dst_width * bpp;
cursor_data = g_malloc (crtc_dst_height * cursor_rowstride);
cogl_texture_get_data (texture, COGL_PIXEL_FORMAT_BGRA_8888_PRE,
cursor_rowstride,
cursor_data);
@ -920,10 +952,10 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native,
crtc_kms,
cursor_sprite,
cursor_data,
cursor_width,
cursor_height,
crtc_dst_width,
crtc_dst_height,
cursor_rowstride,
relative_scale,
&hotspot,
relative_transform,
GBM_FORMAT_ARGB8888);
}
@ -936,9 +968,9 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native,
width,
height,
rowstride,
relative_scale,
relative_transform,
gbm_format);
&hotspot,
MTK_MONITOR_TRANSFORM_NORMAL,
GBM_FORMAT_ARGB8888);
}
return retval;