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; }