From e52641c4b68fe89afe6131b336d56250c41a4f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 21 Dec 2022 18:59:55 +0100 Subject: [PATCH] cursor-renderer/native: Replace HW cursor with KMS cursor manager This removes the old hardware cursor management code and outsources it to MetaKmsCursorManager. What the native cursor renderer still does, however, is the preprocessing i.e. rotating/scaling cursor that wouldn't otherwise be fit for a cursor plane. The cursor DRM buffers are instead of being per cursor sprite now per CRTC, meaning we don't need to stop doing hardware cursors if part of the cursor is on an output that doesn't support it. This is why the whole scale/transform code changed from being per GPU to per CRTC. Part-of: --- src/backends/meta-cursor-renderer.c | 45 +- .../native/meta-cursor-renderer-native.c | 1730 +++++------------ .../native/meta-cursor-renderer-native.h | 4 - src/backends/native/meta-renderer-native.c | 57 +- 4 files changed, 570 insertions(+), 1266 deletions(-) diff --git a/src/backends/meta-cursor-renderer.c b/src/backends/meta-cursor-renderer.c index a1abd4006..df25108a9 100644 --- a/src/backends/meta-cursor-renderer.c +++ b/src/backends/meta-cursor-renderer.c @@ -327,12 +327,11 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer) { } -graphene_rect_t -meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) +static gboolean +calculate_sprite_geometry (MetaCursorSprite *cursor_sprite, + graphene_size_t *size, + graphene_point_t *hotspot) { - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); CoglTexture *texture; int hot_x, hot_y; int width, height; @@ -341,23 +340,39 @@ meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, meta_cursor_sprite_realize_texture (cursor_sprite); texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); if (!texture) - return (graphene_rect_t) GRAPHENE_RECT_INIT_ZERO; + return FALSE; meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y); texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); width = cogl_texture_get_width (texture); height = cogl_texture_get_height (texture); - return (graphene_rect_t) { - .origin = { - .x = priv->current_x - (hot_x * texture_scale), - .y = priv->current_y - (hot_y * texture_scale) - }, - .size = { - .width = width * texture_scale, - .height = height * texture_scale - } + *size = (graphene_size_t) { + .width = width * texture_scale, + .height = height * texture_scale }; + *hotspot = (graphene_point_t) { + .x = hot_x * texture_scale, + .y = hot_y * texture_scale + }; + return TRUE; +} + +graphene_rect_t +meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, + MetaCursorSprite *cursor_sprite) +{ + MetaCursorRendererPrivate *priv = + meta_cursor_renderer_get_instance_private (renderer); + graphene_rect_t rect = GRAPHENE_RECT_INIT_ZERO; + graphene_point_t hotspot; + + if (!calculate_sprite_geometry (cursor_sprite, &rect.size, &hotspot)) + return GRAPHENE_RECT_INIT_ZERO; + + rect.origin = (graphene_point_t) { .x = -hotspot.x, .y = -hotspot.y }; + graphene_rect_offset (&rect, priv->current_x, priv->current_y); + return rect; } static float diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index 954678ae8..098dd40dc 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -43,12 +43,15 @@ #include "backends/native/meta-device-pool.h" #include "backends/native/meta-drm-buffer-dumb.h" #include "backends/native/meta-drm-buffer-gbm.h" +#include "backends/native/meta-input-thread.h" #include "backends/native/meta-frame-native.h" +#include "backends/native/meta-kms-cursor-manager.h" #include "backends/native/meta-kms-device.h" #include "backends/native/meta-kms-plane.h" #include "backends/native/meta-kms-update.h" #include "backends/native/meta-kms.h" #include "backends/native/meta-renderer-native.h" +#include "backends/native/meta-seat-native.h" #include "core/boxes-private.h" #include "meta/boxes.h" #include "meta/meta-backend.h" @@ -74,12 +77,13 @@ static GQuark quark_cursor_sprite = 0; -typedef struct _CrtcCursorData +typedef struct _CursorStageView { - MetaDrmBuffer *buffer; - gboolean needs_sync_position; - gboolean hw_state_invalidated; -} CrtcCursorData; + gboolean needs_emit_painted; + gboolean has_hw_cursor; + + gboolean is_hw_cursor_valid; +} CursorStageView; struct _MetaCursorRendererNative { @@ -90,10 +94,15 @@ struct _MetaCursorRendererNativePrivate { MetaBackend *backend; - gboolean has_hw_cursor; + MetaCursorSprite *current_cursor; + gulong texture_changed_handler_id; - MetaCursorSprite *last_cursor; guint animation_timeout_id; + + gulong pointer_position_changed_in_impl_handler_id; + gboolean input_disconnected; + GMutex input_mutex; + GCond input_cond; }; typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate; @@ -105,21 +114,6 @@ typedef struct _MetaCursorRendererNativeGpuData uint64_t cursor_height; } MetaCursorRendererNativeGpuData; -typedef enum _MetaCursorBufferState -{ - META_CURSOR_BUFFER_STATE_NONE, - META_CURSOR_BUFFER_STATE_SET, - META_CURSOR_BUFFER_STATE_INVALIDATED, -} MetaCursorBufferState; - -typedef struct _MetaCursorNativeGpuState -{ - MetaGpu *gpu; - unsigned int active_buffer_idx; - MetaCursorBufferState pending_buffer_state; - MetaDrmBuffer *buffers[HW_CURSOR_BUFFER_COUNT]; -} MetaCursorNativeGpuState; - typedef struct _MetaCursorNativePrivate { GHashTable *gpu_states; @@ -132,38 +126,44 @@ typedef struct _MetaCursorNativePrivate } MetaCursorNativePrivate; static GQuark quark_cursor_renderer_native_gpu_data = 0; +static GQuark quark_cursor_stage_view = 0; G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); -static void -kms_update_feedback_result (const MetaKmsFeedback *kms_feedback, - gpointer user_data); - -static void -realize_cursor_sprite (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus); - -static MetaCursorNativeGpuState * -get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms); - -static MetaCursorNativeGpuState * -ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms); - -static void -invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite); - -static MetaCursorNativePrivate * -ensure_cursor_priv (MetaCursorSprite *cursor_sprite); - -static MetaCursorNativePrivate * -get_cursor_priv (MetaCursorSprite *cursor_sprite); - static gboolean -is_cursor_scale_and_transform_valid (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite); +realize_cursor_sprite_for_crtc (MetaCursorRenderer *renderer, + MetaCrtcKms *crtc_kms, + MetaCursorSprite *cursor_sprite); + +static void +invalidate_cursor_gpu_state (MetaCursorRenderer *cursor_renderer, + MetaCursorSprite *cursor_sprite); + +static CursorStageView * +get_cursor_stage_view (MetaStageView *view) +{ + return g_object_get_qdata (G_OBJECT (view), + quark_cursor_stage_view); +} + +static CursorStageView * +ensure_cursor_stage_view (MetaStageView *view) +{ + CursorStageView *cursor_stage_view; + + cursor_stage_view = get_cursor_stage_view (view); + if (!cursor_stage_view) + { + cursor_stage_view = g_new0 (CursorStageView, 1); + cursor_stage_view->is_hw_cursor_valid = FALSE; + g_object_set_qdata_full (G_OBJECT (view), + quark_cursor_stage_view, + cursor_stage_view, + g_free); + } + + return cursor_stage_view; +} static MetaCursorRendererNativeGpuData * meta_cursor_renderer_native_gpu_data_from_gpu (MetaGpuKms *gpu_kms) @@ -193,193 +193,14 @@ meta_cursor_renderer_native_finalize (GObject *object) MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer); + g_clear_signal_handler (&priv->texture_changed_handler_id, + priv->current_cursor); + g_clear_object (&priv->current_cursor); g_clear_handle_id (&priv->animation_timeout_id, g_source_remove); G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object); } -static unsigned int -get_pending_cursor_sprite_buffer_index (MetaCursorNativeGpuState *cursor_gpu_state) -{ - return (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT; -} - -static MetaDrmBuffer * -get_pending_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state) -{ - unsigned int pending_buffer_idx; - - pending_buffer_idx = - get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - return cursor_gpu_state->buffers[pending_buffer_idx]; -} - -static MetaDrmBuffer * -get_active_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state) -{ - return cursor_gpu_state->buffers[cursor_gpu_state->active_buffer_idx]; -} - -static void -set_pending_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms, - MetaDrmBuffer *buffer) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - unsigned int pending_buffer_idx; - - cursor_priv = ensure_cursor_priv (cursor_sprite); - cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms); - - pending_buffer_idx = - get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - cursor_gpu_state->buffers[pending_buffer_idx] = buffer; - cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_SET; -} - -static void -calculate_crtc_cursor_hotspot (MetaCursorSprite *cursor_sprite, - int *cursor_hotspot_x, - int *cursor_hotspot_y) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - int hot_x, hot_y; - int width, height; - float scale; - MetaMonitorTransform transform; - - scale = cursor_priv->preprocess_state.current_relative_scale; - transform = cursor_priv->preprocess_state.current_relative_transform; - - 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); - meta_monitor_transform_transform_point (transform, - width, height, - hot_x, hot_y, - &hot_x, &hot_y); - *cursor_hotspot_x = (int) roundf (hot_x * scale); - *cursor_hotspot_y = (int) roundf (hot_y * scale); -} - -static CrtcCursorData * -ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms) -{ - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = meta_crtc_kms_get_cursor_renderer_private (crtc_kms); - if (!crtc_cursor_data) - { - crtc_cursor_data = g_new0 (CrtcCursorData, 1); - crtc_cursor_data->hw_state_invalidated = TRUE; - meta_crtc_kms_set_cursor_renderer_private (crtc_kms, - crtc_cursor_data, - g_free); - } - - return crtc_cursor_data; -} - -static const MetaKmsResultListenerVtable kms_update_listener_vtable = { - .feedback = kms_update_feedback_result, -}; - -static void -assign_cursor_plane (MetaCursorRendererNative *native, - ClutterFrame *frame, - MetaCrtcKms *crtc_kms, - int x, - int y, - MetaCursorSprite *cursor_sprite) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - MetaCursorNativeGpuState *cursor_gpu_state = - get_cursor_gpu_state (cursor_priv, gpu_kms); - MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *cursor_plane; - MetaDrmBuffer *buffer; - int cursor_width, cursor_height; - MetaFixed16Rectangle src_rect; - MetaRectangle dst_rect; - MetaDrmBuffer *crtc_buffer; - MetaKmsAssignPlaneFlag flags; - CrtcCursorData *crtc_cursor_data; - int cursor_hotspot_x; - int cursor_hotspot_y; - MetaKmsUpdate *kms_update; - MetaKmsPlaneAssignment *plane_assignment; - - if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) - buffer = get_pending_cursor_sprite_buffer (cursor_gpu_state); - else - buffer = get_active_cursor_sprite_buffer (cursor_gpu_state); - - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - kms_device = meta_kms_crtc_get_device (kms_crtc); - cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc); - g_return_if_fail (cursor_plane); - - cursor_width = cursor_renderer_gpu_data->cursor_width; - cursor_height = cursor_renderer_gpu_data->cursor_height; - src_rect = (MetaFixed16Rectangle) { - .x = meta_fixed_16_from_int (0), - .y = meta_fixed_16_from_int (0), - .width = meta_fixed_16_from_int (cursor_width), - .height = meta_fixed_16_from_int (cursor_height), - }; - dst_rect = (MetaRectangle) { - .x = x, - .y = y, - .width = cursor_width, - .height = cursor_height, - }; - - flags = META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL; - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_buffer = crtc_cursor_data->buffer; - if (!crtc_cursor_data->hw_state_invalidated && buffer == crtc_buffer) - flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED; - - kms_update = meta_frame_native_ensure_kms_update (frame_native, - kms_device); - plane_assignment = meta_kms_update_assign_plane (kms_update, - kms_crtc, - cursor_plane, - buffer, - src_rect, - dst_rect, - flags); - - calculate_crtc_cursor_hotspot (cursor_sprite, - &cursor_hotspot_x, - &cursor_hotspot_y); - meta_kms_plane_assignment_set_cursor_hotspot (plane_assignment, - cursor_hotspot_x, - cursor_hotspot_y); - - meta_kms_update_add_result_listener (kms_update, - &kms_update_listener_vtable, - NULL, - native, - NULL); - - crtc_cursor_data->buffer = buffer; - - if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) - { - cursor_gpu_state->active_buffer_idx = - (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT; - cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_NONE; - } -} - static float calculate_cursor_crtc_sprite_scale (MetaBackend *backend, MetaCursorSprite *cursor_sprite, @@ -396,127 +217,6 @@ calculate_cursor_crtc_sprite_scale (MetaBackend *backend, } } -static void -set_crtc_cursor (MetaCursorRendererNative *cursor_renderer_native, - ClutterFrame *frame, - MetaRendererView *view, - MetaCrtc *crtc, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaCursorRenderer *cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - MetaOutput *output = meta_crtc_get_outputs (crtc)->data; - MetaMonitor *monitor = meta_output_get_monitor (output); - MetaLogicalMonitor *logical_monitor = - meta_monitor_get_logical_monitor (monitor); - const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc); - graphene_rect_t rect; - graphene_rect_t local_crtc_rect; - graphene_rect_t local_cursor_rect; - float view_scale; - float crtc_cursor_x, crtc_cursor_y; - CoglTexture *texture; - int tex_width, tex_height; - float cursor_crtc_scale; - MetaRectangle cursor_rect; - MetaMonitorTransform transform; - MetaMonitorMode *monitor_mode; - MetaMonitorCrtcMode *monitor_crtc_mode; - const MetaCrtcModeInfo *crtc_mode_info; - - view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view)); - - rect = meta_cursor_renderer_calculate_rect (cursor_renderer, cursor_sprite); - local_cursor_rect = - GRAPHENE_RECT_INIT (rect.origin.x - logical_monitor->rect.x, - rect.origin.y - logical_monitor->rect.y, - rect.size.width, - rect.size.height); - - local_crtc_rect = crtc_config->layout; - graphene_rect_offset (&local_crtc_rect, - -logical_monitor->rect.x, - -logical_monitor->rect.y); - - crtc_cursor_x = (local_cursor_rect.origin.x - - local_crtc_rect.origin.x) * view_scale; - crtc_cursor_y = (local_cursor_rect.origin.y - - local_crtc_rect.origin.y) * view_scale; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - tex_width = cogl_texture_get_width (texture); - tex_height = cogl_texture_get_height (texture); - - cursor_crtc_scale = - calculate_cursor_crtc_sprite_scale (priv->backend, - cursor_sprite, - logical_monitor); - - cursor_rect = (MetaRectangle) { - .x = floorf (crtc_cursor_x), - .y = floorf (crtc_cursor_y), - .width = roundf (tex_width * cursor_crtc_scale), - .height = roundf (tex_height * cursor_crtc_scale) - }; - - transform = meta_logical_monitor_get_transform (logical_monitor); - transform = meta_monitor_logical_to_crtc_transform (monitor, transform); - - monitor_mode = meta_monitor_get_current_mode (monitor); - monitor_crtc_mode = meta_monitor_get_crtc_mode_for_output (monitor, - monitor_mode, - output); - crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode); - meta_rectangle_transform (&cursor_rect, - transform, - crtc_mode_info->width, - crtc_mode_info->height, - &cursor_rect); - - assign_cursor_plane (cursor_renderer_native, - frame, - META_CRTC_KMS (crtc), - cursor_rect.x, - cursor_rect.y, - cursor_sprite); -} - -static void -unset_crtc_cursor (MetaCursorRendererNative *native, - ClutterFrame *frame, - MetaCrtc *crtc) -{ - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); - CrtcCursorData *crtc_cursor_data; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *cursor_plane; - MetaDrmBuffer *crtc_buffer; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_buffer = crtc_cursor_data->buffer; - if (!crtc_cursor_data->hw_state_invalidated && !crtc_buffer) - return; - - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - kms_device = meta_kms_crtc_get_device (kms_crtc); - cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc); - - if (cursor_plane) - { - MetaKmsUpdate *kms_update; - - kms_update = meta_frame_native_ensure_kms_update (frame_native, - kms_device); - meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane); - } - - crtc_cursor_data->buffer = NULL; -} - static void disable_hw_cursor_for_gpu (MetaGpuKms *gpu_kms, const GError *error) @@ -530,17 +230,6 @@ disable_hw_cursor_for_gpu (MetaGpuKms *gpu_kms, cursor_renderer_gpu_data->hw_cursor_broken = TRUE; } -static void -disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc, - const GError *error) -{ - MetaCrtcKms *crtc_kms = meta_crtc_kms_from_kms_crtc (kms_crtc); - MetaCrtc *crtc = META_CRTC (crtc_kms); - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - - disable_hw_cursor_for_gpu (gpu_kms, error); -} - void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, MetaRendererView *view, @@ -548,380 +237,22 @@ meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_rend { MetaCursorRenderer *cursor_renderer = META_CURSOR_RENDERER (cursor_renderer_native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); + CursorStageView *cursor_stage_view; MetaCursorSprite *cursor_sprite; - graphene_rect_t cursor_rect; - cairo_rectangle_int_t view_layout; - graphene_rect_t view_rect; - CrtcCursorData *crtc_cursor_data; - - if (meta_monitor_manager_get_power_save_mode (monitor_manager) != - META_POWER_SAVE_ON) - return; - - if (!meta_crtc_get_gpu (crtc)) - return; - - crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc)); - if (!crtc_cursor_data->hw_state_invalidated && - !crtc_cursor_data->needs_sync_position) - return; cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); if (!cursor_sprite) - goto unset_cursor; + return; - if (!priv->has_hw_cursor) - goto unset_cursor; - - cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer, - cursor_sprite); - clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout); - view_rect = GRAPHENE_RECT_INIT (view_layout.x, view_layout.y, - view_layout.width, view_layout.height); - if (!graphene_rect_intersection (&cursor_rect, &view_rect, NULL)) - goto unset_cursor; - - set_crtc_cursor (cursor_renderer_native, frame, view, crtc, cursor_sprite); - - meta_cursor_renderer_emit_painted (cursor_renderer, - cursor_sprite, - CLUTTER_STAGE_VIEW (view)); - - crtc_cursor_data->needs_sync_position = FALSE; - crtc_cursor_data->hw_state_invalidated = FALSE; - return; - -unset_cursor: - unset_crtc_cursor (cursor_renderer_native, frame, crtc); - - crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc)); - crtc_cursor_data->hw_state_invalidated = FALSE; -} - -static gboolean -has_valid_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (!cursor_priv) - return FALSE; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (!cursor_gpu_state) - return FALSE; - - switch (cursor_gpu_state->pending_buffer_state) + cursor_stage_view = get_cursor_stage_view (META_STAGE_VIEW (view)); + if (cursor_stage_view && + cursor_stage_view->needs_emit_painted) { - case META_CURSOR_BUFFER_STATE_NONE: - return get_active_cursor_sprite_buffer (cursor_gpu_state) != NULL; - case META_CURSOR_BUFFER_STATE_SET: - return TRUE; - case META_CURSOR_BUFFER_STATE_INVALIDATED: - return FALSE; + meta_cursor_renderer_emit_painted (cursor_renderer, + cursor_sprite, + CLUTTER_STAGE_VIEW (view)); + cursor_stage_view->needs_emit_painted = FALSE; } - - g_assert_not_reached (); - - return FALSE; -} - -static void -set_can_preprocess (MetaCursorSprite *cursor_sprite, - float scale, - MetaMonitorTransform transform) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - cursor_priv->preprocess_state.current_relative_scale = scale; - cursor_priv->preprocess_state.current_relative_transform = transform; - cursor_priv->preprocess_state.can_preprocess = TRUE; - - invalidate_cursor_gpu_state (cursor_sprite); -} - -static void -unset_can_preprocess (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - memset (&cursor_priv->preprocess_state, - 0, - sizeof (cursor_priv->preprocess_state)); - cursor_priv->preprocess_state.can_preprocess = FALSE; - - invalidate_cursor_gpu_state (cursor_sprite); -} - -static gboolean -get_can_preprocess (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.can_preprocess; -} - -static float -get_current_relative_scale (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.current_relative_scale; -} - -static MetaMonitorTransform -get_current_relative_transform (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.current_relative_transform; -} - -static void -crtc_supports_hw_cursor (MetaLogicalMonitor *logical_monitor, - MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, - gpointer user_data) -{ - gboolean *supports_hw_cursor = user_data; - MetaCrtcNative *crtc_native = META_CRTC_NATIVE (crtc); - - *supports_hw_cursor &= meta_crtc_native_is_hw_cursor_supported (crtc_native); -} - -static gboolean -crtcs_supports_hw_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *logical_monitors; - GList *l; - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaRectangle logical_monitor_layout; - graphene_rect_t logical_monitor_rect; - gboolean supports_hw_cursor; - - logical_monitor_layout = - meta_logical_monitor_get_layout (logical_monitor); - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor_layout); - - if (!graphene_rect_intersection (&cursor_rect, &logical_monitor_rect, - NULL)) - continue; - - supports_hw_cursor = TRUE; - meta_logical_monitor_foreach_crtc (logical_monitor, - crtc_supports_hw_cursor, - &supports_hw_cursor); - if (!supports_hw_cursor) - return FALSE; - } - - return TRUE; -} - -static gboolean -get_common_crtc_sprite_scale_for_logical_monitors (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - float *out_scale) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_rect_t cursor_rect; - float scale = 1.0; - gboolean has_visible_crtc_sprite = FALSE; - GList *logical_monitors; - GList *l; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - graphene_rect_t logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor->rect); - float tmp_scale; - - if (!graphene_rect_intersection (&cursor_rect, - &logical_monitor_rect, - NULL)) - continue; - - tmp_scale = - calculate_cursor_crtc_sprite_scale (backend, - cursor_sprite, - logical_monitor); - - if (has_visible_crtc_sprite && scale != tmp_scale) - return FALSE; - - has_visible_crtc_sprite = TRUE; - scale = tmp_scale; - } - - if (!has_visible_crtc_sprite) - return FALSE; - - *out_scale = scale; - return TRUE; -} - -static gboolean -get_common_crtc_sprite_transform_for_logical_monitors (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - MetaMonitorTransform *out_transform) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_rect_t cursor_rect; - MetaMonitorTransform transform = META_MONITOR_TRANSFORM_NORMAL; - gboolean has_visible_crtc_sprite = FALSE; - GList *logical_monitors; - GList *l; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - graphene_rect_t logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor->rect); - MetaMonitorTransform logical_transform, tmp_transform; - GList *monitors, *l_mon; - - if (!graphene_rect_intersection (&cursor_rect, - &logical_monitor_rect, - NULL)) - continue; - - logical_transform = meta_logical_monitor_get_transform (logical_monitor); - monitors = meta_logical_monitor_get_monitors (logical_monitor); - for (l_mon = monitors; l_mon; l_mon = l_mon->next) - { - MetaMonitor *monitor = l_mon->data; - - tmp_transform = meta_monitor_transform_transform ( - meta_monitor_transform_invert ( - meta_cursor_sprite_get_texture_transform (cursor_sprite)), - meta_monitor_logical_to_crtc_transform (monitor, logical_transform)); - - if (has_visible_crtc_sprite && transform != tmp_transform) - return FALSE; - - has_visible_crtc_sprite = TRUE; - transform = tmp_transform; - } - } - - if (!has_visible_crtc_sprite) - return FALSE; - - *out_transform = transform; - return TRUE; -} - -static gboolean -should_have_hw_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - CoglTexture *texture; - MetaMonitorTransform transform; - float scale; - GList *l; - - if (!gpus) - return FALSE; - - if (!cursor_sprite) - return FALSE; - - if (meta_backend_is_hw_cursors_inhibited (priv->backend)) - return FALSE; - - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data) - return FALSE; - - if (cursor_renderer_gpu_data->hw_cursor_broken) - return FALSE; - - if (!has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms)) - return FALSE; - } - - if (!crtcs_supports_hw_cursor (renderer, cursor_sprite)) - return FALSE; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - if (!texture) - return FALSE; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &scale)) - return FALSE; - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &transform)) - return FALSE; - - if (G_APPROX_VALUE (scale, 1.f, FLT_EPSILON) && - transform == META_MONITOR_TRANSFORM_NORMAL) - return TRUE; - else - return get_can_preprocess (cursor_sprite); } static gboolean @@ -941,17 +272,14 @@ meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native) static void maybe_schedule_cursor_sprite_animation_frame (MetaCursorRendererNative *native, - MetaCursorSprite *cursor_sprite) + MetaCursorSprite *cursor_sprite, + gboolean cursor_changed) { MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); - gboolean cursor_change; guint delay; - cursor_change = cursor_sprite != priv->last_cursor; - priv->last_cursor = cursor_sprite; - - if (!cursor_change && priv->animation_timeout_id) + if (!cursor_changed && priv->animation_timeout_id) return; g_clear_handle_id (&priv->animation_timeout_id, g_source_remove); @@ -972,273 +300,154 @@ maybe_schedule_cursor_sprite_animation_frame (MetaCursorRendererNative *native, } } -static GList * -calculate_cursor_sprite_gpus (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *gpus = NULL; - GList *logical_monitors; - GList *l; - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaRectangle logical_monitor_layout; - graphene_rect_t logical_monitor_rect; - GList *monitors, *l_mon; - - logical_monitor_layout = - meta_logical_monitor_get_layout (logical_monitor); - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor_layout); - - if (!graphene_rect_intersection (&cursor_rect, &logical_monitor_rect, - NULL)) - continue; - - monitors = meta_logical_monitor_get_monitors (logical_monitor); - for (l_mon = monitors; l_mon; l_mon = l_mon->next) - { - MetaMonitor *monitor = l_mon->data; - MetaOutput *output = meta_monitor_get_main_output (monitor); - MetaGpu *gpu; - - gpu = meta_output_get_gpu (output); - if (gpu && !g_list_find (gpus, gpu)) - gpus = g_list_prepend (gpus, gpu); - } - } - - return gpus; -} - static void -kms_update_feedback_result (const MetaKmsFeedback *kms_feedback, - gpointer user_data) +on_cursor_sprite_texture_changed (MetaCursorSprite *cursor_sprite, + MetaCursorRenderer *cursor_renderer) { - MetaCursorRendererNative *cursor_renderer_native = user_data; - MetaCursorRenderer *cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - gboolean has_hw_cursor_failure = FALSE; - GList *l; - - for (l = meta_kms_feedback_get_failed_planes (kms_feedback); l; l = l->next) - { - MetaKmsPlaneFeedback *plane_feedback = l->data; - - switch (meta_kms_plane_get_plane_type (plane_feedback->plane)) - { - case META_KMS_PLANE_TYPE_CURSOR: - break; - case META_KMS_PLANE_TYPE_PRIMARY: - case META_KMS_PLANE_TYPE_OVERLAY: - continue; - } - - disable_hw_cursor_for_crtc (plane_feedback->crtc, - plane_feedback->error); - has_hw_cursor_failure = TRUE; - } - - if (has_hw_cursor_failure) - { - priv->has_hw_cursor = FALSE; - meta_cursor_renderer_force_update (cursor_renderer); - } -} - -static void -schedule_sync_position (MetaCursorRendererNative *cursor_renderer_native) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - GList *l; - - for (l = meta_backend_get_gpus (priv->backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *l_crtc; - - for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data); - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_cursor_data->needs_sync_position = TRUE; - } - } + invalidate_cursor_gpu_state (cursor_renderer, cursor_sprite); } static gboolean -meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, +meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *cursor_renderer, MetaCursorSprite *cursor_sprite) { - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); + MetaCursorRendererNative *native = + META_CURSOR_RENDERER_NATIVE (cursor_renderer); MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend)); - g_autoptr (GList) gpus = NULL; - - if (cursor_sprite) - { - gboolean realized; - - ensure_cursor_priv (cursor_sprite); - realized = meta_cursor_sprite_realize_texture (cursor_sprite); - gpus = calculate_cursor_sprite_gpus (renderer, cursor_sprite); - - if (realized || - !is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) - realize_cursor_sprite (renderer, cursor_sprite, gpus); - } - - maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite); - - priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus); - - schedule_sync_position (native); - clutter_stage_schedule_update (stage); - - return !(priv->has_hw_cursor || - !cursor_sprite || - !meta_cursor_sprite_get_cogl_texture (cursor_sprite)); -} - -static void -unset_crtc_cursor_renderer_privates (MetaGpu *gpu, - MetaDrmBuffer *buffer) -{ + MetaBackend *backend = priv->backend; + MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend); + MetaRenderer *renderer = meta_backend_get_renderer (backend); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + MetaKmsCursorManager *kms_cursor_manager = meta_kms_get_cursor_manager (kms); + gboolean cursor_changed; + GList *views; GList *l; - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) + COGL_TRACE_BEGIN_SCOPED (MetaCursorRendererNative, + "CursorRendererNative (update cursor)"); + + cursor_changed = priv->current_cursor != cursor_sprite; + + views = meta_renderer_get_views (renderer); + for (l = views; l; l = l->next) { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data); - CrtcCursorData *crtc_cursor_data; + MetaStageView *view = l->data; + MetaRendererView *renderer_view = META_RENDERER_VIEW (view); + MetaCrtc *crtc = meta_renderer_view_get_crtc (renderer_view); + MetaCrtcNative *crtc_native = META_CRTC_NATIVE (crtc); + CursorStageView *cursor_stage_view = NULL; + gboolean has_hw_cursor = FALSE; - crtc_cursor_data = meta_crtc_kms_get_cursor_renderer_private (crtc_kms); - if (crtc_cursor_data && buffer == crtc_cursor_data->buffer) - crtc_cursor_data->buffer = NULL; + cursor_stage_view = ensure_cursor_stage_view (view); + + if (!META_IS_CRTC_KMS (crtc) || + !meta_crtc_native_is_hw_cursor_supported (crtc_native)) + { + if (cursor_stage_view->has_hw_cursor) + { + meta_stage_view_uninhibit_cursor_overlay (view); + cursor_stage_view->has_hw_cursor = FALSE; + } + continue; + } + + if (cursor_sprite) + { + meta_cursor_sprite_realize_texture (cursor_sprite); + + if (cursor_changed || + !cursor_stage_view->is_hw_cursor_valid) + { + has_hw_cursor = realize_cursor_sprite_for_crtc (cursor_renderer, + META_CRTC_KMS (crtc), + cursor_sprite); + + cursor_stage_view->is_hw_cursor_valid = TRUE; + } + else + { + has_hw_cursor = + cursor_stage_view->is_hw_cursor_valid && + cursor_stage_view->has_hw_cursor; + } + + if (has_hw_cursor) + cursor_stage_view->needs_emit_painted = TRUE; + } + else + { + cursor_stage_view->is_hw_cursor_valid = FALSE; + has_hw_cursor = FALSE; + } + + if (cursor_stage_view->has_hw_cursor != has_hw_cursor) + { + if (has_hw_cursor || !cursor_sprite) + meta_stage_view_inhibit_cursor_overlay (view); + else + meta_stage_view_uninhibit_cursor_overlay (view); + + cursor_stage_view->has_hw_cursor = has_hw_cursor; + + if (!has_hw_cursor) + { + MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); + MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + + meta_kms_cursor_manager_update_sprite (kms_cursor_manager, + kms_crtc, + NULL, NULL); + } + } } -} -static void -cursor_gpu_state_free (MetaCursorNativeGpuState *cursor_gpu_state) -{ - int i; - MetaDrmBuffer *active_buffer; - - active_buffer = get_active_cursor_sprite_buffer (cursor_gpu_state); - if (active_buffer) - unset_crtc_cursor_renderer_privates (cursor_gpu_state->gpu, - active_buffer); - - for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++) - g_clear_object (&cursor_gpu_state->buffers[i]); - g_free (cursor_gpu_state); -} - -static MetaCursorNativeGpuState * -get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms) -{ - return g_hash_table_lookup (cursor_priv->gpu_states, gpu_kms); -} - -static MetaCursorNativeGpuState * -ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (cursor_gpu_state) - return cursor_gpu_state; - - cursor_gpu_state = g_new0 (MetaCursorNativeGpuState, 1); - cursor_gpu_state->gpu = META_GPU (gpu_kms); - g_hash_table_insert (cursor_priv->gpu_states, gpu_kms, cursor_gpu_state); - - return cursor_gpu_state; -} - -static void -invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - GHashTableIter iter; - MetaCursorNativeGpuState *cursor_gpu_state; - - g_hash_table_iter_init (&iter, cursor_priv->gpu_states); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state)) + if (cursor_changed) { - unsigned int pending_buffer_idx; + if (priv->current_cursor) + { + g_clear_signal_handler (&priv->texture_changed_handler_id, + priv->current_cursor); + } - pending_buffer_idx = get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - g_clear_object (&cursor_gpu_state->buffers[pending_buffer_idx]); - cursor_gpu_state->pending_buffer_state = - META_CURSOR_BUFFER_STATE_INVALIDATED; + g_set_object (&priv->current_cursor, cursor_sprite); + + if (priv->current_cursor) + { + priv->texture_changed_handler_id = + g_signal_connect (cursor_sprite, "texture-changed", + G_CALLBACK (on_cursor_sprite_texture_changed), + cursor_renderer); + } } + + maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite, + cursor_changed); + + return cursor_sprite && meta_cursor_sprite_get_cogl_texture (cursor_sprite); } static void -on_cursor_sprite_texture_changed (MetaCursorSprite *cursor_sprite) +invalidate_cursor_gpu_state (MetaCursorRenderer *cursor_renderer, + MetaCursorSprite *cursor_sprite) { - invalidate_cursor_gpu_state (cursor_sprite); -} + MetaCursorRendererNative *native = + META_CURSOR_RENDERER_NATIVE (cursor_renderer); + MetaCursorRendererNativePrivate *priv = + meta_cursor_renderer_native_get_instance_private (native); + MetaRenderer *renderer = meta_backend_get_renderer (priv->backend); + GList *views; + GList *l; -static void -cursor_priv_free (MetaCursorNativePrivate *cursor_priv) -{ - g_hash_table_destroy (cursor_priv->gpu_states); - g_free (cursor_priv); -} + views = meta_renderer_get_views (renderer); + for (l = views; l; l = l->next) + { + MetaStageView *view = l->data; + CursorStageView *cursor_stage_view; -static MetaCursorNativePrivate * -get_cursor_priv (MetaCursorSprite *cursor_sprite) -{ - return g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); -} - -static MetaCursorNativePrivate * -ensure_cursor_priv (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (cursor_priv) - return cursor_priv; - - cursor_priv = g_new0 (MetaCursorNativePrivate, 1); - cursor_priv->gpu_states = - g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) cursor_gpu_state_free); - g_object_set_qdata_full (G_OBJECT (cursor_sprite), - quark_cursor_sprite, - cursor_priv, - (GDestroyNotify) cursor_priv_free); - - g_signal_connect (cursor_sprite, "texture-changed", - G_CALLBACK (on_cursor_sprite_texture_changed), NULL); - - unset_can_preprocess (cursor_sprite); - - return cursor_priv; + cursor_stage_view = get_cursor_stage_view (view); + cursor_stage_view->is_hw_cursor_valid = FALSE; + } } static MetaDrmBuffer * @@ -1366,31 +575,38 @@ create_cursor_drm_buffer (MetaGpuKms *gpu_kms, } } -static void -load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, - MetaGpuKms *gpu_kms, - MetaCursorSprite *cursor_sprite, - uint8_t *pixels, - uint width, - uint height, - int rowstride, - uint32_t gbm_format) +static gboolean +load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native, + MetaCrtcKms *crtc_kms, + MetaCursorSprite *cursor_sprite, + uint8_t *pixels, + uint width, + uint height, + int rowstride, + float scale, + uint32_t gbm_format) { MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + MetaKmsCursorManager *kms_cursor_manager = meta_kms_get_cursor_manager (kms); MetaDevicePool *device_pool = meta_backend_native_get_device_pool (backend_native); + MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); + MetaKmsCrtc *kms_crtc; uint64_t cursor_width, cursor_height; - MetaDrmBuffer *buffer; + g_autoptr (MetaDrmBuffer) buffer = NULL; MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; g_autoptr (MetaDeviceFile) device_file = NULL; g_autoptr (GError) error = NULL; + int hot_x, hot_y; cursor_renderer_gpu_data = meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); if (!cursor_renderer_gpu_data) - return; + return FALSE; cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width; cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height; @@ -1399,7 +615,7 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, { meta_warning ("Invalid theme cursor size (must be at most %ux%u)", (unsigned int)cursor_width, (unsigned int)cursor_height); - return; + return FALSE; } device_file = meta_device_pool_open (device_pool, @@ -1412,7 +628,7 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, meta_gpu_kms_get_file_path (gpu_kms), error->message); disable_hw_cursor_for_gpu (gpu_kms, error); - return; + return FALSE; } buffer = create_cursor_drm_buffer (gpu_kms, device_file, @@ -1426,59 +642,16 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, { g_warning ("Realizing HW cursor failed: %s", error->message); disable_hw_cursor_for_gpu (gpu_kms, error); - return; - } - - set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms, buffer); -} - -static gboolean -is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (!cursor_priv) - return FALSE; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (!cursor_gpu_state) - return FALSE; - - switch (cursor_gpu_state->pending_buffer_state) - { - case META_CURSOR_BUFFER_STATE_SET: - case META_CURSOR_BUFFER_STATE_NONE: - return TRUE; - case META_CURSOR_BUFFER_STATE_INVALIDATED: return FALSE; } - g_assert_not_reached (); - return FALSE; -} - -static gboolean -is_cursor_scale_and_transform_valid (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaMonitorTransform transform; - float scale; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &scale)) - return FALSE; - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &transform)) - return FALSE; - - return (scale == get_current_relative_scale (cursor_sprite) && - transform == get_current_relative_transform (cursor_sprite)); + meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y); + kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + meta_kms_cursor_manager_update_sprite (kms_cursor_manager, + kms_crtc, + buffer, + &GRAPHENE_POINT_INIT (hot_x, hot_y)); + return TRUE; } static cairo_surface_t * @@ -1569,9 +742,9 @@ gbm_format_to_cairo_format (uint32_t gbm_format) } } -static void +static gboolean load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native, - MetaGpuKms *gpu_kms, + MetaCrtcKms *crtc_kms, MetaCursorSprite *cursor_sprite, float relative_scale, MetaMonitorTransform relative_transform, @@ -1581,6 +754,8 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native, int rowstride, uint32_t gbm_format) { + gboolean retval = FALSE; + if (!G_APPROX_VALUE (relative_scale, 1.f, FLT_EPSILON) || relative_transform != META_MONITOR_TRANSFORM_NORMAL || gbm_format != GBM_FORMAT_ARGB8888) @@ -1597,40 +772,47 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native, relative_scale, relative_transform); - load_cursor_sprite_gbm_buffer_for_gpu (native, - gpu_kms, - cursor_sprite, - cairo_image_surface_get_data (surface), - cairo_image_surface_get_width (surface), - cairo_image_surface_get_width (surface), - cairo_image_surface_get_stride (surface), - GBM_FORMAT_ARGB8888); + retval = + load_cursor_sprite_gbm_buffer_for_crtc (native, + crtc_kms, + cursor_sprite, + cairo_image_surface_get_data (surface), + cairo_image_surface_get_width (surface), + cairo_image_surface_get_width (surface), + cairo_image_surface_get_stride (surface), + relative_scale, + GBM_FORMAT_ARGB8888); cairo_surface_destroy (surface); } else { - load_cursor_sprite_gbm_buffer_for_gpu (native, - gpu_kms, - cursor_sprite, - data, - width, - height, - rowstride, - gbm_format); + retval = load_cursor_sprite_gbm_buffer_for_crtc (native, + crtc_kms, + cursor_sprite, + data, + width, + height, + rowstride, + relative_scale, + gbm_format); } + + return retval; } #ifdef HAVE_WAYLAND -static void -realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSpriteWayland *sprite_wayland) +static gboolean +realize_cursor_sprite_from_wl_buffer_for_crtc (MetaCursorRenderer *renderer, + MetaCrtcKms *crtc_kms, + MetaCursorSpriteWayland *sprite_wayland) { MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_wayland); + 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; @@ -1642,21 +824,15 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, cursor_renderer_gpu_data = meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) - return; - - if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) && - is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) - return; + return FALSE; buffer = meta_cursor_sprite_wayland_get_buffer (sprite_wayland); if (!buffer) - return; + return FALSE; buffer_resource = meta_wayland_buffer_get_resource (buffer); if (!buffer_resource) - return; - - ensure_cursor_priv (cursor_sprite); + return FALSE; shm_buffer = wl_shm_buffer_get (buffer_resource); if (shm_buffer) @@ -1667,25 +843,24 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, MetaMonitorTransform relative_transform; uint32_t gbm_format; - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &relative_scale)) - { - unset_can_preprocess (cursor_sprite); - return; - } + MetaCrtc *crtc = META_CRTC (crtc_kms); + MetaLogicalMonitor *logical_monitor; + MetaMonitor *monitor; + MetaMonitorTransform logical_transform; + gboolean retval; - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &relative_transform)) - { - unset_can_preprocess (cursor_sprite); - return; - } + monitor = meta_output_get_monitor (meta_crtc_get_outputs (crtc)->data); + logical_monitor = meta_monitor_get_logical_monitor (monitor); - set_can_preprocess (cursor_sprite, - relative_scale, - relative_transform); + relative_scale = calculate_cursor_crtc_sprite_scale (priv->backend, + cursor_sprite, + logical_monitor); + + logical_transform = meta_logical_monitor_get_transform (logical_monitor); + relative_transform = meta_monitor_transform_transform ( + meta_monitor_transform_invert ( + meta_cursor_sprite_get_texture_transform (cursor_sprite)), + meta_monitor_logical_to_crtc_transform (monitor, logical_transform)); wl_shm_buffer_begin_access (shm_buffer); buffer_data = wl_shm_buffer_get_data (shm_buffer); @@ -1706,24 +881,30 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, gbm_format = GBM_FORMAT_ARGB8888; } - load_scaled_and_transformed_cursor_sprite (native, - gpu_kms, - cursor_sprite, - relative_scale, - relative_transform, - buffer_data, - width, - height, - rowstride, - gbm_format); + retval = load_scaled_and_transformed_cursor_sprite (native, + crtc_kms, + cursor_sprite, + relative_scale, + relative_transform, + buffer_data, + width, + height, + rowstride, + gbm_format); wl_shm_buffer_end_access (shm_buffer); + + return retval; } else { MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend); MetaDevicePool *device_pool = meta_backend_native_get_device_pool (backend_native); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + MetaKmsCursorManager *kms_cursor_manager = meta_kms_get_cursor_manager (kms); + MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + int hot_x, hot_y; g_autoptr (MetaDeviceFile) device_file = NULL; struct gbm_device *gbm_device; struct gbm_bo *bo; @@ -1740,7 +921,7 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, g_warning ("Failed to open '%s' for updating the cursor: %s", meta_gpu_kms_get_file_path (gpu_kms), error->message); - return; + return FALSE; } /* HW cursors have a predefined size (at least 64x64), which usually is @@ -1759,12 +940,12 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, if (width != cursor_width || height != cursor_height) { meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors"); - return; + return FALSE; } gbm_device = meta_gbm_device_from_gpu (gpu_kms); if (!gbm_device) - return; + return FALSE; bo = gbm_bo_import (gbm_device, GBM_BO_IMPORT_WL_BUFFER, @@ -1773,11 +954,9 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, if (!bo) { meta_warning ("Importing HW cursor from wl_buffer failed"); - return; + return FALSE; } - unset_can_preprocess (cursor_sprite); - flags = META_DRM_BUFFER_FLAG_DISABLE_MODIFIERS; buffer_gbm = meta_drm_buffer_gbm_new_take (device_file, bo, flags, &error); @@ -1786,85 +965,88 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, meta_warning ("Failed to create DRM buffer wrapper: %s", error->message); gbm_bo_destroy (bo); - return; + return FALSE; } - set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms, - META_DRM_BUFFER (buffer_gbm)); + meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y); + kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + meta_kms_cursor_manager_update_sprite (kms_cursor_manager, + kms_crtc, + META_DRM_BUFFER (buffer_gbm), + &GRAPHENE_POINT_INIT (hot_x, hot_y)); + + return TRUE; } } -#endif +#endif /* HAVE_WAYLAND */ -static void -realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSpriteXcursor *sprite_xcursor) +static gboolean +realize_cursor_sprite_from_xcursor_for_crtc (MetaCursorRenderer *renderer, + MetaCrtcKms *crtc_kms, + MetaCursorSpriteXcursor *sprite_xcursor) { MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; + MetaCursorRendererNativePrivate *priv = + meta_cursor_renderer_native_get_instance_private (native); MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor); + MetaCrtc *crtc = META_CRTC (crtc_kms); + MetaLogicalMonitor *logical_monitor; + MetaMonitor *monitor; + MetaMonitorTransform logical_transform; XcursorImage *xc_image; float relative_scale; MetaMonitorTransform relative_transform; - ensure_cursor_priv (cursor_sprite); + monitor = meta_output_get_monitor (meta_crtc_get_outputs (crtc)->data); + logical_monitor = meta_monitor_get_logical_monitor (monitor); - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) - return; + relative_scale = calculate_cursor_crtc_sprite_scale (priv->backend, + cursor_sprite, + logical_monitor); - if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) && - is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) - return; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &relative_scale)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &relative_transform)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - set_can_preprocess (cursor_sprite, - relative_scale, - relative_transform); + logical_transform = meta_logical_monitor_get_transform (logical_monitor); + relative_transform = meta_monitor_transform_transform ( + meta_monitor_transform_invert ( + meta_cursor_sprite_get_texture_transform (cursor_sprite)), + meta_monitor_logical_to_crtc_transform (monitor, logical_transform)); xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor); - load_scaled_and_transformed_cursor_sprite (native, - gpu_kms, - cursor_sprite, - relative_scale, - relative_transform, - (uint8_t *) xc_image->pixels, - xc_image->width, - xc_image->height, - xc_image->width * 4, - GBM_FORMAT_ARGB8888); + return load_scaled_and_transformed_cursor_sprite (native, + crtc_kms, + cursor_sprite, + relative_scale, + relative_transform, + (uint8_t *) xc_image->pixels, + xc_image->width, + xc_image->height, + xc_image->width * 4, + GBM_FORMAT_ARGB8888); } -static void -realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSprite *cursor_sprite) +static gboolean +realize_cursor_sprite_for_crtc (MetaCursorRenderer *renderer, + MetaCrtcKms *crtc_kms, + MetaCursorSprite *cursor_sprite) { + MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); + + meta_topic (META_DEBUG_KMS, + "Realizing HW cursor for cursor sprite for CRTC %u (%s)", + meta_kms_crtc_get_id (kms_crtc), + meta_kms_device_get_path (kms_device)); + + COGL_TRACE_BEGIN_SCOPED (CursorRendererNAtiveRealize, + "Cursor Renderer Native (realize for crtc)"); if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite)) { MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (cursor_sprite); - realize_cursor_sprite_from_xcursor_for_gpu (renderer, - gpu_kms, - sprite_xcursor); + return realize_cursor_sprite_from_xcursor_for_crtc (renderer, + crtc_kms, + sprite_xcursor); } #ifdef HAVE_WAYLAND else if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite)) @@ -1872,25 +1054,14 @@ realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer, MetaCursorSpriteWayland *sprite_wayland = META_CURSOR_SPRITE_WAYLAND (cursor_sprite); - realize_cursor_sprite_from_wl_buffer_for_gpu (renderer, - gpu_kms, - sprite_wayland); + return realize_cursor_sprite_from_wl_buffer_for_crtc (renderer, + crtc_kms, + sprite_wayland); } #endif -} - -static void -realize_cursor_sprite (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus) -{ - GList *l; - - for (l = gpus; l; l = l->next) + else { - MetaGpuKms *gpu_kms = l->data; - - realize_cursor_sprite_for_gpu (renderer, gpu_kms, cursor_sprite); + return FALSE; } } @@ -1906,39 +1077,17 @@ meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass) quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native"); quark_cursor_renderer_native_gpu_data = g_quark_from_static_string ("-meta-cursor-renderer-native-gpu-data"); -} - -static void -force_update_hw_cursor (MetaCursorRendererNative *native) -{ - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - GList *l; - - for (l = meta_backend_get_gpus (priv->backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *l_crtc; - - for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data); - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_cursor_data->hw_state_invalidated = TRUE; - } - } - - meta_cursor_renderer_force_update (renderer); + quark_cursor_stage_view = + g_quark_from_static_string ("-meta-cursor-stage-view-native"); } static void on_monitors_changed (MetaMonitorManager *monitors, MetaCursorRendererNative *native) { - force_update_hw_cursor (native); + MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); + + meta_cursor_renderer_force_update (renderer); } static void @@ -1968,11 +1117,105 @@ on_gpu_added_for_cursor (MetaBackend *backend, init_hw_cursor_support_for_gpu (gpu_kms); } +typedef struct _CursorKmsImplState +{ + graphene_point_t sprite_hotspot; + graphene_rect_t sprite_rect; +} CursorKmsImplState; + +static void +on_pointer_position_changed_in_input_impl (MetaSeatImpl *seat_impl, + const graphene_point_t *position, + MetaBackend *backend) +{ + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + MetaKmsCursorManager *kms_cursor_manager = meta_kms_get_cursor_manager (kms); + + meta_kms_cursor_manager_position_changed_in_input_impl (kms_cursor_manager, + position); +} + +static gboolean +connect_seat_signals_in_input_impl (gpointer user_data) +{ + GTask *task = G_TASK (user_data); + MetaCursorRendererNative *cursor_renderer_native = + META_CURSOR_RENDERER_NATIVE (g_task_get_task_data (task)); + MetaCursorRendererNativePrivate *priv = + meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); + MetaBackend *backend = priv->backend; + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaSeatImpl *seat_impl = g_task_get_source_object (task); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + MetaKmsCursorManager *kms_cursor_manager = meta_kms_get_cursor_manager (kms); + ClutterInputDevice *device; + graphene_point_t position; + + priv->pointer_position_changed_in_impl_handler_id = + g_signal_connect (seat_impl, "pointer-position-changed-in-impl", + G_CALLBACK (on_pointer_position_changed_in_input_impl), + backend); + + + device = meta_seat_impl_get_pointer (seat_impl); + meta_seat_impl_query_state (seat_impl, device, NULL, &position, NULL); + meta_kms_cursor_manager_position_changed_in_input_impl (kms_cursor_manager, + &position); + + g_task_return_boolean (task, TRUE); + + return G_SOURCE_REMOVE; +} + +static gboolean +disconnect_seat_signals_in_input_impl (gpointer user_data) +{ + GTask *task = G_TASK (user_data); + MetaCursorRendererNative *cursor_renderer_native = + META_CURSOR_RENDERER_NATIVE (g_task_get_task_data (task)); + MetaCursorRendererNativePrivate *priv = + meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); + MetaSeatImpl *seat_impl = g_task_get_source_object (task); + + g_clear_signal_handler (&priv->pointer_position_changed_in_impl_handler_id, + seat_impl); + g_task_return_boolean (task, TRUE); + + g_mutex_lock (&priv->input_mutex); + priv->input_disconnected = TRUE; + g_cond_signal (&priv->input_cond); + g_mutex_unlock (&priv->input_mutex); + + return G_SOURCE_REMOVE; +} + +static void +query_cursor_position_in_kms_impl (float *x, + float *y, + gpointer user_data) +{ + ClutterSeat *seat = user_data; + ClutterInputDevice *device; + graphene_point_t position; + + device = clutter_seat_get_pointer (seat); + clutter_seat_query_state (seat, device, NULL, &position, NULL); + *x = position.x; + *y = position.y; +} + static void init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native) { MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); + MetaBackend *backend = priv->backend; + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + MetaKmsCursorManager *kms_cursor_manager = meta_kms_get_cursor_manager (kms); + ClutterSeat *seat; + MetaSeatNative *seat_native; GList *gpus; GList *l; @@ -1983,6 +1226,54 @@ init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native) init_hw_cursor_support_for_gpu (gpu_kms); } + + seat = meta_backend_get_default_seat (priv->backend); + seat_native = META_SEAT_NATIVE (seat); + meta_seat_native_run_impl_task (seat_native, + connect_seat_signals_in_input_impl, + cursor_renderer_native, NULL); + + meta_kms_cursor_manager_set_query_func (kms_cursor_manager, + query_cursor_position_in_kms_impl, + seat); +} + +static void +on_started (MetaContext *context, + MetaCursorRendererNative *cursor_renderer_native) +{ + if (g_strcmp0 (getenv ("MUTTER_DEBUG_DISABLE_HW_CURSORS"), "1")) + init_hw_cursor_support (cursor_renderer_native); + else + g_message ("Disabling hardware cursors because MUTTER_DEBUG_DISABLE_HW_CURSORS is set"); +} + +static void +on_prepare_shutdown (MetaContext *context, + MetaCursorRendererNative *cursor_renderer_native) +{ + MetaCursorRendererNativePrivate *priv = + meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); + ClutterSeat *seat; + MetaSeatNative *seat_native; + + g_mutex_init (&priv->input_mutex); + g_cond_init (&priv->input_cond); + priv->input_disconnected = FALSE; + + seat = meta_backend_get_default_seat (priv->backend); + seat_native = META_SEAT_NATIVE (seat); + meta_seat_native_run_impl_task (seat_native, + disconnect_seat_signals_in_input_impl, + cursor_renderer_native, NULL); + + g_mutex_lock (&priv->input_mutex); + while (!priv->input_disconnected) + g_cond_wait (&priv->input_cond, &priv->input_mutex); + g_mutex_unlock (&priv->input_mutex); + + g_mutex_clear (&priv->input_mutex); + g_cond_clear (&priv->input_cond); } MetaCursorRendererNative * @@ -1993,6 +1284,10 @@ meta_cursor_renderer_native_new (MetaBackend *backend, meta_backend_get_monitor_manager (backend); MetaCursorRendererNative *cursor_renderer_native; MetaCursorRendererNativePrivate *priv; + MetaSeatNative *seat = + META_SEAT_NATIVE (meta_backend_get_default_seat (backend)); + + g_assert (seat); cursor_renderer_native = g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, "backend", backend, @@ -2006,14 +1301,17 @@ meta_cursor_renderer_native_new (MetaBackend *backend, cursor_renderer_native, 0); g_signal_connect (backend, "gpu-added", G_CALLBACK (on_gpu_added_for_cursor), NULL); + g_signal_connect (meta_backend_get_context (backend), + "started", + G_CALLBACK (on_started), + cursor_renderer_native); + g_signal_connect (meta_backend_get_context (backend), + "prepare-shutdown", + G_CALLBACK (on_prepare_shutdown), + cursor_renderer_native); priv->backend = backend; - if (g_strcmp0 (getenv ("MUTTER_DEBUG_DISABLE_HW_CURSORS"), "1")) - init_hw_cursor_support (cursor_renderer_native); - else - g_message ("Disabling hardware cursors because MUTTER_DEBUG_DISABLE_HW_CURSORS is set"); - return cursor_renderer_native; } @@ -2021,17 +1319,3 @@ static void meta_cursor_renderer_native_init (MetaCursorRendererNative *native) { } - -void -meta_cursor_renderer_native_invalidate_gpu_state (MetaCursorRendererNative *native, - MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativePrivate *cursor_priv; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (!cursor_priv) - return; - - g_hash_table_remove (cursor_priv->gpu_states, gpu_kms); -} diff --git a/src/backends/native/meta-cursor-renderer-native.h b/src/backends/native/meta-cursor-renderer-native.h index d3858e5e5..fae221a5d 100644 --- a/src/backends/native/meta-cursor-renderer-native.h +++ b/src/backends/native/meta-cursor-renderer-native.h @@ -41,8 +41,4 @@ void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend, ClutterInputDevice *device); -void meta_cursor_renderer_native_invalidate_gpu_state (MetaCursorRendererNative *native, - MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms); - #endif /* META_CURSOR_RENDERER_NATIVE_H */ diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index ef7369075..2c3db57e3 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -55,6 +55,7 @@ #include "backends/native/meta-crtc-kms.h" #include "backends/native/meta-crtc-virtual.h" #include "backends/native/meta-device-pool.h" +#include "backends/native/meta-kms-cursor-manager.h" #include "backends/native/meta-kms-device.h" #include "backends/native/meta-kms.h" #include "backends/native/meta-onscreen-native.h" @@ -134,11 +135,7 @@ meta_get_renderer_native_parent_vtable (void) static void meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data) { - MetaRenderer *renderer = META_RENDERER (renderer_gpu_data->renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaCursorRenderer *cursor_renderer; MetaGpuKms *gpu_kms = renderer_gpu_data->gpu_kms; - GList *l; if (renderer_gpu_data->secondary.egl_context != EGL_NO_CONTEXT) { @@ -154,26 +151,6 @@ meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data NULL); } - cursor_renderer = meta_backend_get_cursor_renderer (backend); - if (cursor_renderer && gpu_kms) - { - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (cursor_renderer); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - GList *cursor_sprites = - meta_cursor_tracker_peek_cursor_sprites (cursor_tracker); - - for (l = cursor_sprites; l; l = l->next) - { - MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (l->data); - - meta_cursor_renderer_native_invalidate_gpu_state (cursor_renderer_native, - cursor_sprite, - gpu_kms); - } - } - if (renderer_gpu_data->crtc_needs_flush_handler_id) { g_clear_signal_handler (&renderer_gpu_data->crtc_needs_flush_handler_id, @@ -1107,7 +1084,13 @@ static void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) { MetaRenderer *renderer = META_RENDERER (renderer_native); + MetaBackend *backend = meta_renderer_get_backend (renderer); + MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend)); + MetaKmsCursorManager *kms_cursor_manager = meta_kms_get_cursor_manager (kms); GList *l; + g_autoptr (GArray) crtc_layouts = NULL; + + crtc_layouts = g_array_new (FALSE, TRUE, sizeof (MetaKmsCrtcLayout)); g_clear_list (&renderer_native->pending_mode_set_views, NULL); for (l = meta_renderer_get_views (renderer); l; l = l->next) @@ -1118,13 +1101,39 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) if (COGL_IS_ONSCREEN (framebuffer)) { + MetaOnscreenNative *onscreen_native = + META_ONSCREEN_NATIVE (framebuffer); + MetaCrtc *crtc; + MetaKmsCrtc *kms_crtc; + MetaRectangle view_layout; + float view_scale; + MetaKmsCrtcLayout crtc_layout; + renderer_native->pending_mode_set_views = g_list_prepend (renderer_native->pending_mode_set_views, stage_view); + meta_onscreen_native_invalidate (onscreen_native); + crtc = meta_onscreen_native_get_crtc (onscreen_native); + kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); + + clutter_stage_view_get_layout (stage_view, &view_layout); + view_scale = clutter_stage_view_get_scale (stage_view); + + crtc_layout = (MetaKmsCrtcLayout) { + .crtc = kms_crtc, + .layout = GRAPHENE_RECT_INIT (view_layout.x, + view_layout.y, + view_layout.width, + view_layout.height), + .scale = view_scale, + }; + g_array_append_val (crtc_layouts, crtc_layout); } } renderer_native->pending_mode_set = TRUE; + meta_kms_cursor_manager_update_crtc_layout (kms_cursor_manager, crtc_layouts); + meta_topic (META_DEBUG_KMS, "Queue mode set"); }