From c98575344295b715a0301c7319195b2724dc2bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sat, 10 Oct 2020 01:02:28 +0200 Subject: [PATCH] cursor-renderer/native: Update HW state during frames Before each frame is maybe redrawn, push any new cursor KMS state to the pending update. It'll then either be posted during the next page flip, or when the same frame finishes, in case nothing was redrawn. Part-of: --- clutter/clutter/clutter-stage-view.c | 2 + clutter/clutter/clutter-stage-window.c | 11 + clutter/clutter/clutter-stage-window.h | 7 + clutter/clutter/cogl/clutter-stage-cogl.c | 15 + clutter/clutter/cogl/clutter-stage-cogl.h | 4 + src/backends/meta-monitor.c | 22 + src/backends/meta-monitor.h | 4 + .../native/meta-cursor-renderer-native.c | 441 ++++++++---------- .../native/meta-cursor-renderer-native.h | 3 + src/backends/native/meta-renderer-native.c | 77 ++- src/backends/native/meta-renderer-native.h | 6 +- src/backends/native/meta-stage-native.c | 24 +- 12 files changed, 359 insertions(+), 257 deletions(-) diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index 66d052ebe..436ce40b2 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -1099,6 +1099,8 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock, frame = CLUTTER_FRAME_INIT; + _clutter_stage_window_prepare_frame (stage_window, view, &frame); + if (clutter_stage_view_has_redraw_clip (view)) { clutter_stage_emit_before_paint (stage, view); diff --git a/clutter/clutter/clutter-stage-window.c b/clutter/clutter/clutter-stage-window.c index 5f7c48967..9052a8c4b 100644 --- a/clutter/clutter/clutter-stage-window.c +++ b/clutter/clutter/clutter-stage-window.c @@ -135,6 +135,17 @@ _clutter_stage_window_get_views (ClutterStageWindow *window) return iface->get_views (window); } +void +_clutter_stage_window_prepare_frame (ClutterStageWindow *window, + ClutterStageView *view, + ClutterFrame *frame) +{ + ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + if (iface->prepare_frame) + iface->prepare_frame (window, view, frame); +} + void _clutter_stage_window_finish_frame (ClutterStageWindow *window, ClutterStageView *view, diff --git a/clutter/clutter/clutter-stage-window.h b/clutter/clutter/clutter-stage-window.h index b1ebd2bad..5f0ae7ab1 100644 --- a/clutter/clutter/clutter-stage-window.h +++ b/clutter/clutter/clutter-stage-window.h @@ -52,6 +52,9 @@ struct _ClutterStageWindowInterface GList *(* get_views) (ClutterStageWindow *stage_window); int64_t (* get_frame_counter) (ClutterStageWindow *stage_window); + void (* prepare_frame) (ClutterStageWindow *stage_window, + ClutterStageView *view, + ClutterFrame *frame); void (* finish_frame) (ClutterStageWindow *stage_window, ClutterStageView *view, ClutterFrame *frame); @@ -89,6 +92,10 @@ gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWin GList * _clutter_stage_window_get_views (ClutterStageWindow *window); +void _clutter_stage_window_prepare_frame (ClutterStageWindow *window, + ClutterStageView *view, + ClutterFrame *frame); + void _clutter_stage_window_finish_frame (ClutterStageWindow *window, ClutterStageView *view, ClutterFrame *frame); diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index 90f428ec8..2e14ec9eb 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -731,6 +731,21 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, clutter_stage_cogl_redraw_view_primary (stage_cogl, view, frame); } +void +clutter_stage_cogl_add_onscreen_frame_info (ClutterStageCogl *stage_cogl, + ClutterStageView *view) +{ + ClutterStageCoglPrivate *priv = + _clutter_stage_cogl_get_instance_private (stage_cogl); + CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view); + CoglFrameInfo *frame_info; + + frame_info = cogl_frame_info_new (priv->global_frame_counter); + priv->global_frame_counter++; + + cogl_onscreen_add_frame_info (COGL_ONSCREEN (framebuffer), frame_info); +} + static void clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) { diff --git a/clutter/clutter/cogl/clutter-stage-cogl.h b/clutter/clutter/cogl/clutter-stage-cogl.h index a67ba9615..11aeaefe1 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.h +++ b/clutter/clutter/cogl/clutter-stage-cogl.h @@ -56,6 +56,10 @@ void _clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl, CoglFrameEvent frame_event, ClutterFrameInfo *frame_info); +CLUTTER_EXPORT +void clutter_stage_cogl_add_onscreen_frame_info (ClutterStageCogl *stage_cogl, + ClutterStageView *view); + G_END_DECLS #endif /* __CLUTTER_STAGE_COGL_H__ */ diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index 07c574de2..0be7994ad 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -1948,6 +1948,28 @@ meta_monitor_mode_foreach_output (MetaMonitor *monitor, return TRUE; } +MetaMonitorCrtcMode * +meta_monitor_get_crtc_mode_for_output (MetaMonitor *monitor, + MetaMonitorMode *mode, + MetaOutput *output) +{ + MetaMonitorPrivate *monitor_priv = + meta_monitor_get_instance_private (monitor); + GList *l; + int i; + + for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++) + { + MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i]; + + if (monitor_crtc_mode->output == output) + return monitor_crtc_mode; + } + + g_warn_if_reached (); + return NULL; +} + const char * meta_monitor_get_display_name (MetaMonitor *monitor) { diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h index eb6b99fea..96f280a89 100644 --- a/src/backends/meta-monitor.h +++ b/src/backends/meta-monitor.h @@ -264,6 +264,10 @@ gboolean meta_monitor_mode_foreach_output (MetaMonitor *monitor, gpointer user_data, GError **error); +MetaMonitorCrtcMode * meta_monitor_get_crtc_mode_for_output (MetaMonitor *monitor, + MetaMonitorMode *mode, + MetaOutput *output); + META_EXPORT_TEST gboolean meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode); diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index ff175e8e2..3899bd205 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -80,6 +80,8 @@ static GQuark quark_cursor_sprite = 0; typedef struct _CrtcCursorData { MetaDrmBuffer *buffer; + gboolean needs_sync_position; + gboolean hw_state_invalidated; } CrtcCursorData; struct _MetaCursorRendererNative @@ -91,7 +93,6 @@ struct _MetaCursorRendererNativePrivate { MetaBackend *backend; - gboolean hw_state_invalidated; gboolean has_hw_cursor; MetaCursorSprite *last_cursor; @@ -137,6 +138,10 @@ static GQuark quark_cursor_renderer_native_gpu_data = 0; G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); +static void +on_kms_update_result (const MetaKmsFeedback *kms_feedback, + gpointer user_data); + static void realize_cursor_sprite (MetaCursorRenderer *renderer, MetaCursorSprite *cursor_sprite, @@ -266,6 +271,7 @@ ensure_crtc_cursor_data (MetaCrtcKms *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); @@ -275,15 +281,12 @@ ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms) } static void -set_crtc_cursor (MetaCursorRendererNative *native, - MetaKmsUpdate *kms_update, - MetaCrtcKms *crtc_kms, - int x, - int y, - MetaCursorSprite *cursor_sprite) +assign_cursor_plane (MetaCursorRendererNative *native, + MetaCrtcKms *crtc_kms, + int x, + int y, + MetaCursorSprite *cursor_sprite) { - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); 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)); @@ -303,6 +306,7 @@ set_crtc_cursor (MetaCursorRendererNative *native, 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) @@ -333,9 +337,12 @@ set_crtc_cursor (MetaCursorRendererNative *native, flags = META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL; crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); crtc_buffer = crtc_cursor_data->buffer; - if (!priv->hw_state_invalidated && buffer == crtc_buffer) + if (!crtc_cursor_data->hw_state_invalidated && buffer == crtc_buffer) flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED; + kms_update = + meta_kms_ensure_pending_update (meta_kms_device_get_kms (kms_device), + meta_kms_crtc_get_device (kms_crtc)); plane_assignment = meta_kms_update_assign_plane (kms_update, kms_crtc, cursor_plane, @@ -351,6 +358,10 @@ set_crtc_cursor (MetaCursorRendererNative *native, cursor_hotspot_x, cursor_hotspot_y); + meta_kms_update_add_result_listener (kms_update, + on_kms_update_result, + native); + crtc_cursor_data->buffer = buffer; if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) @@ -361,35 +372,6 @@ set_crtc_cursor (MetaCursorRendererNative *native, } } -static void -unset_crtc_cursor (MetaCursorRendererNative *native, - MetaKmsUpdate *kms_update, - MetaCrtcKms *crtc_kms) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *cursor_plane; - MetaDrmBuffer *crtc_buffer; - CrtcCursorData *crtc_cursor_data; - - crtc_buffer = meta_crtc_kms_get_cursor_renderer_private (crtc_kms); - if (!priv->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) - meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane); - - crtc_cursor_data = meta_crtc_kms_get_cursor_renderer_private (crtc_kms); - if (crtc_cursor_data) - crtc_cursor_data->buffer = NULL; -} - static float calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite, MetaLogicalMonitor *logical_monitor) @@ -405,139 +387,121 @@ calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite, } } -typedef struct +static void +set_crtc_cursor (MetaCursorRendererNative *cursor_renderer_native, + MetaRendererView *view, + MetaCrtc *crtc, + MetaCursorSprite *cursor_sprite) { - MetaCursorRendererNative *in_cursor_renderer_native; - MetaLogicalMonitor *in_logical_monitor; - graphene_rect_t in_local_cursor_rect; - MetaCursorSprite *in_cursor_sprite; - - gboolean out_painted; -} UpdateCrtcCursorData; - -static gboolean -update_monitor_crtc_cursor (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - MetaMonitorCrtcMode *monitor_crtc_mode, - gpointer user_data, - GError **error) -{ - UpdateCrtcCursorData *data = user_data; - MetaCursorRendererNative *cursor_renderer_native = - data->in_cursor_renderer_native; - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaCrtc *crtc; - MetaGpuKms *gpu_kms; - MetaKmsDevice *kms_device; - MetaKms *kms; - MetaKmsUpdate *kms_update; + 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; + MetaMonitorTransform inverted_transform; + MetaMonitorMode *monitor_mode; + MetaMonitorCrtcMode *monitor_crtc_mode; const MetaCrtcModeInfo *crtc_mode_info; - graphene_rect_t scaled_crtc_rect; - float scale; - int crtc_x, crtc_y; - int crtc_width, crtc_height; - if (meta_is_stage_views_scaled ()) - scale = meta_logical_monitor_get_scale (data->in_logical_monitor); - else - scale = 1.0; + view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view)); - transform = meta_logical_monitor_get_transform (data->in_logical_monitor); - transform = meta_monitor_logical_to_crtc_transform (monitor, transform); + 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); - meta_monitor_calculate_crtc_pos (monitor, monitor_mode, - monitor_crtc_mode->output, - transform, - &crtc_x, &crtc_y); + local_crtc_rect = crtc_config->layout; + graphene_rect_offset (&local_crtc_rect, + -logical_monitor->rect.x, + -logical_monitor->rect.y); - crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode); + 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; - if (meta_monitor_transform_is_rotated (transform)) - { - crtc_width = crtc_mode_info->height; - crtc_height = crtc_mode_info->width; - } - else - { - crtc_width = crtc_mode_info->width; - crtc_height = crtc_mode_info->height; - } + texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); + tex_width = cogl_texture_get_width (texture); + tex_height = cogl_texture_get_height (texture); - scaled_crtc_rect = (graphene_rect_t) { - .origin = { - .x = crtc_x / scale, - .y = crtc_y / scale - }, - .size = { - .width = crtc_width / scale, - .height = crtc_height / scale - }, + cursor_crtc_scale = + calculate_cursor_crtc_sprite_scale (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) }; - crtc = meta_output_get_assigned_crtc (monitor_crtc_mode->output); - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - kms = meta_kms_device_get_kms (kms_device); - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + transform = meta_logical_monitor_get_transform (logical_monitor); + transform = meta_monitor_logical_to_crtc_transform (monitor, transform); - if (priv->has_hw_cursor && - graphene_rect_intersection (&scaled_crtc_rect, - &data->in_local_cursor_rect, - NULL)) - { - MetaMonitorTransform inverted_transform; - MetaRectangle cursor_rect; - CoglTexture *texture; - float crtc_cursor_x, crtc_cursor_y; - float cursor_crtc_scale; - int tex_width, tex_height; + inverted_transform = meta_monitor_transform_invert (transform); - crtc_cursor_x = (data->in_local_cursor_rect.origin.x - - scaled_crtc_rect.origin.x) * scale; - crtc_cursor_y = (data->in_local_cursor_rect.origin.y - - scaled_crtc_rect.origin.y) * scale; + 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, + inverted_transform, + crtc_mode_info->width, + crtc_mode_info->height, + &cursor_rect); - texture = meta_cursor_sprite_get_cogl_texture (data->in_cursor_sprite); - tex_width = cogl_texture_get_width (texture); - tex_height = cogl_texture_get_height (texture); - - cursor_crtc_scale = - calculate_cursor_crtc_sprite_scale (data->in_cursor_sprite, - data->in_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) - }; - - inverted_transform = meta_monitor_transform_invert (transform); - meta_rectangle_transform (&cursor_rect, - inverted_transform, - crtc_mode_info->width, - crtc_mode_info->height, - &cursor_rect); - - set_crtc_cursor (data->in_cursor_renderer_native, - kms_update, + assign_cursor_plane (cursor_renderer_native, META_CRTC_KMS (crtc), cursor_rect.x, cursor_rect.y, - data->in_cursor_sprite); + cursor_sprite); +} - data->out_painted = data->out_painted || TRUE; - } - else +static void +unset_crtc_cursor (MetaCursorRendererNative *native, + MetaCrtc *crtc) +{ + MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); + 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) { - unset_crtc_cursor (data->in_cursor_renderer_native, - kms_update, - META_CRTC_KMS (crtc)); + MetaKms *kms = meta_kms_device_get_kms (kms_device); + MetaKmsUpdate *kms_update; + + kms_update = meta_kms_ensure_pending_update (kms, kms_device); + meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane); } - return TRUE; + crtc_cursor_data->buffer = NULL; } static void @@ -556,68 +520,61 @@ disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc, cursor_renderer_gpu_data->hw_cursor_broken = TRUE; } -static void -update_hw_cursor (MetaCursorRendererNative *native, - MetaCursorSprite *cursor_sprite) +void +meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, + MetaRendererView *view) { + MetaCursorRenderer *cursor_renderer = + META_CURSOR_RENDERER (cursor_renderer_native); MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); + 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 rect; - gboolean painted = FALSE; + MetaCrtc *crtc = meta_renderer_view_get_crtc (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 (cursor_sprite) - rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - else - rect = GRAPHENE_RECT_INIT_ZERO; + if (meta_monitor_manager_get_power_save_mode (monitor_manager) != + META_POWER_SAVE_ON) + return; - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - UpdateCrtcCursorData data; - GList *monitors; - GList *k; + 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; - data = (UpdateCrtcCursorData) { - .in_cursor_renderer_native = native, - .in_logical_monitor = logical_monitor, - .in_local_cursor_rect = (graphene_rect_t) { - .origin = { - .x = rect.origin.x - logical_monitor->rect.x, - .y = rect.origin.y - logical_monitor->rect.y - }, - .size = rect.size - }, - .in_cursor_sprite = cursor_sprite, - }; + cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); + if (!cursor_sprite) + goto unset_cursor; - monitors = meta_logical_monitor_get_monitors (logical_monitor); - for (k = monitors; k; k = k->next) - { - MetaMonitor *monitor = k->data; - MetaMonitorMode *monitor_mode; + if (!priv->has_hw_cursor) + goto unset_cursor; - monitor_mode = meta_monitor_get_current_mode (monitor); - meta_monitor_mode_foreach_crtc (monitor, monitor_mode, - update_monitor_crtc_cursor, - &data, - NULL); - } + 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; - painted = painted || data.out_painted; - } + set_crtc_cursor (cursor_renderer_native, view, crtc, cursor_sprite); - priv->hw_state_invalidated = FALSE; + meta_cursor_renderer_emit_painted (cursor_renderer, cursor_sprite); - if (painted) - meta_cursor_renderer_emit_painted (renderer, cursor_sprite); + crtc_cursor_data->needs_sync_position = FALSE; + crtc_cursor_data->hw_state_invalidated = FALSE; + return; + +unset_cursor: + unset_crtc_cursor (cursor_renderer_native, crtc); + + crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc)); + crtc_cursor_data->hw_state_invalidated = FALSE; } static gboolean @@ -1074,6 +1031,29 @@ on_kms_update_result (const MetaKmsFeedback *kms_feedback, } } +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; + } + } +} + static gboolean meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, MetaCursorSprite *cursor_sprite) @@ -1081,10 +1061,7 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); - MetaRendererNative *renderer_native = - META_RENDERER_NATIVE (meta_backend_get_renderer (priv->backend)); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); + ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend)); g_autoptr (GList) gpus = NULL; if (cursor_sprite) @@ -1097,43 +1074,9 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite); priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus); - update_hw_cursor (native, cursor_sprite); - if (!meta_renderer_native_is_mode_set_pending (renderer_native)) - { - GList *l; - - for (l = meta_kms_get_devices (kms); l; l = l->next) - { - MetaKmsDevice *kms_device = l->data; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - on_kms_update_result (kms_feedback, renderer); - } - } - else - { - GList *l; - - for (l = meta_kms_get_devices (kms); l; l = l->next) - { - MetaKmsDevice *kms_device = l->data; - MetaKmsUpdate *kms_update; - - kms_update = meta_kms_get_pending_update (kms, kms_device); - if (!kms_update) - continue; - - meta_kms_update_add_result_listener (kms_update, - on_kms_update_result, - renderer); - } - } + schedule_sync_position (native); + clutter_stage_schedule_update (stage); return (priv->has_hw_cursor || !cursor_sprite || @@ -1779,8 +1722,23 @@ 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; + } + } - priv->hw_state_invalidated = TRUE; meta_cursor_renderer_force_update (renderer); } @@ -1863,7 +1821,6 @@ meta_cursor_renderer_native_new (MetaBackend *backend, G_CALLBACK (on_gpu_added_for_cursor), NULL); priv->backend = backend; - priv->hw_state_invalidated = TRUE; init_hw_cursor_support (cursor_renderer_native); diff --git a/src/backends/native/meta-cursor-renderer-native.h b/src/backends/native/meta-cursor-renderer-native.h index 26c698cda..5113b96ce 100644 --- a/src/backends/native/meta-cursor-renderer-native.h +++ b/src/backends/native/meta-cursor-renderer-native.h @@ -33,6 +33,9 @@ G_DECLARE_FINAL_TYPE (MetaCursorRendererNative, meta_cursor_renderer_native, META, CURSOR_RENDERER_NATIVE, MetaCursorRenderer) +void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, + MetaRendererView *view); + MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend, ClutterInputDevice *device); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 9efee2c1f..f1b9c749b 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -2345,12 +2345,6 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer, return NULL; } -gboolean -meta_renderer_native_is_mode_set_pending (MetaRendererNative *renderer_native) -{ - return renderer_native->pending_mode_set; -} - gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, uint32_t drm_format, @@ -3286,9 +3280,76 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer)); } -void -meta_renderer_native_finish_frame (MetaRendererNative *renderer_native) +static void +add_onscreen_frame_info (MetaCrtc *crtc) { + MetaGpu *gpu = meta_crtc_get_gpu (crtc); + MetaBackend *backend = meta_gpu_get_backend (gpu); + ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); + MetaStageNative *stage_native = + meta_clutter_backend_native_get_stage_native (clutter_backend); + MetaRenderer *renderer = meta_backend_get_renderer (backend); + MetaRendererView *view = meta_renderer_get_view_for_crtc (renderer, crtc); + + clutter_stage_cogl_add_onscreen_frame_info (CLUTTER_STAGE_COGL (stage_native), + CLUTTER_STAGE_VIEW (view)); +} + +void +meta_renderer_native_finish_frame (MetaRendererNative *renderer_native, + MetaRendererView *view, + ClutterFrame *frame) +{ + MetaRenderer *renderer = META_RENDERER (renderer_native); + MetaBackend *backend = meta_renderer_get_backend (renderer); + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + + if (!clutter_frame_has_result (frame)) + { + MetaCrtc *crtc = meta_renderer_view_get_crtc (view); + MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);; + MetaKmsUpdateFlag flags; + MetaKmsUpdate *kms_update; + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; + const GError *error; + + kms_update = meta_kms_get_pending_update (kms, kms_device); + if (!kms_update) + { + clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); + return; + } + + meta_kms_update_add_page_flip_listener (kms_update, + kms_crtc, + &page_flip_listener_vtable, + g_object_ref (view)); + + flags = META_KMS_UPDATE_FLAG_NONE; + kms_feedback = meta_kms_post_pending_update_sync (kms, + kms_device, + flags); + switch (meta_kms_feedback_get_result (kms_feedback)) + { + case META_KMS_FEEDBACK_PASSED: + add_onscreen_frame_info (crtc); + clutter_frame_set_result (frame, + CLUTTER_FRAME_RESULT_PENDING_PRESENTED); + break; + case META_KMS_FEEDBACK_FAILED: + clutter_frame_set_result (frame, + CLUTTER_FRAME_RESULT_IDLE); + + error = meta_kms_feedback_get_error (kms_feedback); + if (!g_error_matches (error, + G_IO_ERROR, + G_IO_ERROR_PERMISSION_DENIED)) + g_warning ("Failed to post KMS update: %s", error->message); + break; + } + } } static gboolean diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h index e48712be8..786bd9d41 100644 --- a/src/backends/native/meta-renderer-native.h +++ b/src/backends/native/meta-renderer-native.h @@ -53,14 +53,14 @@ struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms); MetaGpuKms * meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native); -void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native); +void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native, + MetaRendererView *view, + ClutterFrame *frame); void meta_renderer_native_reset_modes (MetaRendererNative *renderer_native); gboolean meta_renderer_native_use_modifiers (MetaRendererNative *renderer_native); -gboolean meta_renderer_native_is_mode_set_pending (MetaRendererNative *renderer_native); - gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, uint32_t drm_format, uint64_t drm_modifier, diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c index 2a29f9312..3b27c9930 100644 --- a/src/backends/native/meta-stage-native.c +++ b/src/backends/native/meta-stage-native.c @@ -27,6 +27,7 @@ #include "backends/native/meta-stage-native.h" #include "backends/meta-backend-private.h" +#include "backends/native/meta-cursor-renderer-native.h" #include "backends/native/meta-renderer-native.h" #include "meta/meta-backend.h" #include "meta/meta-monitor-manager.h" @@ -105,6 +106,21 @@ meta_stage_native_get_views (ClutterStageWindow *stage_window) return meta_renderer_get_views (renderer); } +static void +meta_stage_native_prepare_frame (ClutterStageWindow *stage_window, + ClutterStageView *stage_view, + ClutterFrame *frame) +{ + MetaBackend *backend = meta_get_backend (); + MetaCursorRenderer *cursor_renderer = + meta_backend_get_cursor_renderer (backend); + MetaCursorRendererNative *cursor_renderer_native = + META_CURSOR_RENDERER_NATIVE (cursor_renderer); + + meta_cursor_renderer_native_prepare_frame (cursor_renderer_native, + META_RENDERER_VIEW (stage_view)); +} + static void meta_stage_native_finish_frame (ClutterStageWindow *stage_window, ClutterStageView *stage_view, @@ -113,10 +129,9 @@ meta_stage_native_finish_frame (ClutterStageWindow *stage_window, MetaBackend *backend = meta_get_backend (); MetaRenderer *renderer = meta_backend_get_renderer (backend); - meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer)); - - if (!clutter_frame_has_result (frame)) - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); + meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer), + META_RENDERER_VIEW (stage_view), + frame); } static void @@ -139,5 +154,6 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) iface->can_clip_redraws = meta_stage_native_can_clip_redraws; iface->get_geometry = meta_stage_native_get_geometry; iface->get_views = meta_stage_native_get_views; + iface->prepare_frame = meta_stage_native_prepare_frame; iface->finish_frame = meta_stage_native_finish_frame; }