From f27ca241f9a2c519eb6b43e17c791ba33efad095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 20 Oct 2022 21:57:25 +0200 Subject: [PATCH] renderer/native: Move per frame KMS update to MetaFrameNative In order to make things more and more asynchronus and to each time we paint be an isolated event, that can be potentially be applied individually or together with other updates, make it so that each time we draw, we use the transient MetaFrameNative (ClutterFrame) instance to carry a KMS update for us. For this to work, we also need to restructure how we apply mode sets. Previously we'd amend the same KMS update each frame during mode set, then after the last CRTC was composited, we'd apply the update that contained updates for all CRTC. Now each CRTC has its own KMS update, and instead we put them in a per device table, and whenever we finished painting, we'll merge the new update into any existing one, and then finally once all CRTCs have been composited, we'll apply an update that contains all the mode sets for all relevant CRTCs on a device. Part-of: --- .../native/meta-cursor-renderer-native.c | 23 ++-- .../native/meta-cursor-renderer-native.h | 3 +- src/backends/native/meta-frame-native.c | 49 +++++++ src/backends/native/meta-frame-native.h | 19 +++ src/backends/native/meta-kms-update-private.h | 7 - src/backends/native/meta-kms-update.h | 7 + src/backends/native/meta-kms.c | 87 ------------ src/backends/native/meta-kms.h | 13 -- src/backends/native/meta-onscreen-native.c | 83 +++++++----- .../native/meta-renderer-native-private.h | 4 + src/backends/native/meta-renderer-native.c | 125 ++++++++++++------ src/backends/native/meta-renderer-native.h | 1 + src/backends/native/meta-stage-native.c | 3 +- src/core/util-private.h | 3 + src/tests/native-kms-render.c | 14 +- 15 files changed, 248 insertions(+), 193 deletions(-) diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index 57774345c..f1b7459fe 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -43,6 +43,7 @@ #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-frame-native.h" #include "backends/native/meta-kms-device.h" #include "backends/native/meta-kms-plane.h" #include "backends/native/meta-kms-update.h" @@ -282,6 +283,7 @@ ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms) static void assign_cursor_plane (MetaCursorRendererNative *native, + ClutterFrame *frame, MetaCrtcKms *crtc_kms, int x, int y, @@ -294,6 +296,7 @@ assign_cursor_plane (MetaCursorRendererNative *native, 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; @@ -340,9 +343,8 @@ assign_cursor_plane (MetaCursorRendererNative *native, 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)); + 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, @@ -390,6 +392,7 @@ 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) @@ -467,6 +470,7 @@ set_crtc_cursor (MetaCursorRendererNative *cursor_renderer_native, &cursor_rect); assign_cursor_plane (cursor_renderer_native, + frame, META_CRTC_KMS (crtc), cursor_rect.x, cursor_rect.y, @@ -475,9 +479,11 @@ set_crtc_cursor (MetaCursorRendererNative *cursor_renderer_native, 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; @@ -495,10 +501,10 @@ unset_crtc_cursor (MetaCursorRendererNative *native, if (cursor_plane) { - MetaKms *kms = meta_kms_device_get_kms (kms_device); MetaKmsUpdate *kms_update; - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_frame_native_ensure_kms_update (frame_native, + kms_device); meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane); } @@ -531,7 +537,8 @@ disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc, void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, - MetaRendererView *view) + MetaRendererView *view, + ClutterFrame *frame) { MetaCursorRenderer *cursor_renderer = META_CURSOR_RENDERER (cursor_renderer_native); @@ -574,7 +581,7 @@ meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_rend if (!graphene_rect_intersection (&cursor_rect, &view_rect, NULL)) goto unset_cursor; - set_crtc_cursor (cursor_renderer_native, view, crtc, cursor_sprite); + set_crtc_cursor (cursor_renderer_native, frame, view, crtc, cursor_sprite); meta_cursor_renderer_emit_painted (cursor_renderer, cursor_sprite, @@ -585,7 +592,7 @@ meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_rend return; unset_cursor: - unset_crtc_cursor (cursor_renderer_native, crtc); + 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; diff --git a/src/backends/native/meta-cursor-renderer-native.h b/src/backends/native/meta-cursor-renderer-native.h index 72b7b3c35..d3858e5e5 100644 --- a/src/backends/native/meta-cursor-renderer-native.h +++ b/src/backends/native/meta-cursor-renderer-native.h @@ -35,7 +35,8 @@ G_DECLARE_FINAL_TYPE (MetaCursorRendererNative, meta_cursor_renderer_native, MetaCursorRenderer) void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, - MetaRendererView *view); + MetaRendererView *view, + ClutterFrame *frame); MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend, ClutterInputDevice *device); diff --git a/src/backends/native/meta-frame-native.c b/src/backends/native/meta-frame-native.c index 45351b70b..c39af96ae 100644 --- a/src/backends/native/meta-frame-native.c +++ b/src/backends/native/meta-frame-native.c @@ -21,16 +21,23 @@ #include "backends/native/meta-frame-native.h" +#include "backends/native/meta-kms-update.h" #include "clutter/clutter-mutter.h" +#include "core/util-private.h" struct _MetaFrameNative { ClutterFrame base; + + MetaKmsUpdate *kms_update; }; static void meta_frame_native_release (ClutterFrame *frame) { + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); + + g_return_if_fail (!frame_native->kms_update); } MetaFrameNative * @@ -38,3 +45,45 @@ meta_frame_native_new (void) { return clutter_frame_new (MetaFrameNative, meta_frame_native_release); } + +MetaFrameNative * +meta_frame_native_from_frame (ClutterFrame *frame) +{ + return META_CONTAINER_OF (frame, MetaFrameNative, base); +} + +void +meta_frame_native_set_kms_update (MetaFrameNative *frame_native, + MetaKmsUpdate *kms_update) +{ + g_return_if_fail (!frame_native->kms_update); + + frame_native->kms_update = kms_update; +} + +MetaKmsUpdate * +meta_frame_native_ensure_kms_update (MetaFrameNative *frame_native, + MetaKmsDevice *kms_device) +{ + if (frame_native->kms_update) + { + g_warn_if_fail (meta_kms_update_get_device (frame_native->kms_update) == + kms_device); + return frame_native->kms_update; + } + + frame_native->kms_update = meta_kms_update_new (kms_device); + return frame_native->kms_update; +} + +MetaKmsUpdate * +meta_frame_native_steal_kms_update (MetaFrameNative *frame_native) +{ + return g_steal_pointer (&frame_native->kms_update); +} + +gboolean +meta_frame_native_has_kms_update (MetaFrameNative *frame_native) +{ + return !!frame_native->kms_update; +} diff --git a/src/backends/native/meta-frame-native.h b/src/backends/native/meta-frame-native.h index f52921ce6..e7140929b 100644 --- a/src/backends/native/meta-frame-native.h +++ b/src/backends/native/meta-frame-native.h @@ -20,8 +20,27 @@ #ifndef META_FRAME_NATIVE_H #define META_FRAME_NATIVE_H +#include "backends/native/meta-kms-types.h" +#include "clutter/clutter.h" +#include "core/util-private.h" + typedef struct _MetaFrameNative MetaFrameNative; MetaFrameNative * meta_frame_native_new (void); +META_EXPORT_TEST +MetaFrameNative * meta_frame_native_from_frame (ClutterFrame *frame); + +void meta_frame_native_set_kms_update (MetaFrameNative *frame_native, + MetaKmsUpdate *kms_update); + +META_EXPORT_TEST +MetaKmsUpdate * meta_frame_native_ensure_kms_update (MetaFrameNative *frame_native, + MetaKmsDevice *kms_device); + +MetaKmsUpdate * meta_frame_native_steal_kms_update (MetaFrameNative *frame_native); + +META_EXPORT_TEST +gboolean meta_frame_native_has_kms_update (MetaFrameNative *frame_native); + #endif /* META_FRAME_NATIVE_H */ diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index f39b47b9f..0e91778e7 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -148,9 +148,6 @@ void meta_kms_update_seal (MetaKmsUpdate *update); META_EXPORT_TEST gboolean meta_kms_update_is_sealed (MetaKmsUpdate *update); -META_EXPORT_TEST -MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update); - void meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment, MetaKmsPlaneRotation rotation); @@ -184,10 +181,6 @@ void meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update, GList * meta_kms_update_take_result_listeners (MetaKmsUpdate *update); -META_EXPORT_TEST -void meta_kms_update_merge_from (MetaKmsUpdate *update, - MetaKmsUpdate *other_update); - void meta_kms_result_listener_set_feedback (MetaKmsResultListener *listener, MetaKmsFeedback *feedback); diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h index 6ce5a8159..885655c42 100644 --- a/src/backends/native/meta-kms-update.h +++ b/src/backends/native/meta-kms-update.h @@ -101,6 +101,9 @@ MetaKmsUpdate * meta_kms_update_new (MetaKmsDevice *device); META_EXPORT_TEST void meta_kms_update_free (MetaKmsUpdate *update); +META_EXPORT_TEST +MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update); + void meta_kms_update_set_underscanning (MetaKmsUpdate *update, MetaKmsConnector *connector, uint64_t hborder, @@ -170,6 +173,10 @@ void meta_kms_update_add_result_listener (MetaKmsUpdate *update, MetaKmsResultListenerFunc func, gpointer user_data); +META_EXPORT_TEST +void meta_kms_update_merge_from (MetaKmsUpdate *update, + MetaKmsUpdate *other_update); + static inline MetaFixed16 meta_fixed_16_from_int (int16_t d) { diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 0c5ca0726..d3a840b31 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -181,72 +181,6 @@ struct _MetaKms G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT) -void -meta_kms_discard_pending_updates (MetaKms *kms) -{ - g_clear_list (&kms->pending_updates, (GDestroyNotify) meta_kms_update_free); -} - -static void -meta_kms_add_pending_update (MetaKms *kms, - MetaKmsUpdate *update) -{ - kms->pending_updates = g_list_prepend (kms->pending_updates, update); -} - -MetaKmsUpdate * -meta_kms_ensure_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - MetaKmsUpdate *update; - - update = meta_kms_get_pending_update (kms, device); - if (update) - return update; - - update = meta_kms_update_new (device); - meta_kms_add_pending_update (kms, update); - - return update; -} - -MetaKmsUpdate * -meta_kms_get_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - GList *l; - - for (l = kms->pending_updates; l; l = l->next) - { - MetaKmsUpdate *update = l->data; - - if (meta_kms_update_get_device (update) == device) - return update; - } - - return NULL; -} - -static MetaKmsUpdate * -meta_kms_take_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - GList *l; - - for (l = kms->pending_updates; l; l = l->next) - { - MetaKmsUpdate *update = l->data; - - if (meta_kms_update_get_device (update) == device) - { - kms->pending_updates = g_list_delete_link (kms->pending_updates, l); - return update; - } - } - - return NULL; -} - static void invoke_result_listener (MetaKms *kms, gpointer user_data) @@ -266,27 +200,6 @@ meta_kms_queue_result_callback (MetaKms *kms, (GDestroyNotify) meta_kms_result_listener_free); } -void -meta_kms_post_pending_update_sync (MetaKms *kms, - MetaKmsDevice *device, - MetaKmsUpdateFlag flags) -{ - MetaKmsUpdate *update; - g_autoptr (MetaKmsFeedback) feedback = NULL; - GList *result_listeners; - - COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync, - "KMS (post update)"); - - update = meta_kms_take_pending_update (kms, device); - if (!update) - return; - - result_listeners = meta_kms_update_take_result_listeners (update); - feedback = meta_kms_device_process_update_sync (device, update, flags); - meta_kms_feedback_dispatch_result (feedback, kms, result_listeners); -} - static gpointer meta_kms_discard_pending_page_flips_in_impl (MetaKmsImpl *impl, gpointer user_data, diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h index 3d9aaed1c..fe4fef1a0 100644 --- a/src/backends/native/meta-kms.h +++ b/src/backends/native/meta-kms.h @@ -34,19 +34,6 @@ typedef enum _MetaKmsFlags #define META_TYPE_KMS (meta_kms_get_type ()) G_DECLARE_FINAL_TYPE (MetaKms, meta_kms, META, KMS, GObject) -void meta_kms_discard_pending_updates (MetaKms *kms); - -META_EXPORT_TEST -MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms, - MetaKmsDevice *device); - -MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms, - MetaKmsDevice *device); - -void meta_kms_post_pending_update_sync (MetaKms *kms, - MetaKmsDevice *device, - MetaKmsUpdateFlag flags); - void meta_kms_discard_pending_page_flips (MetaKms *kms); void meta_kms_notify_modes_set (MetaKms *kms); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 49385c901..5b9396aeb 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -39,6 +39,7 @@ #include "backends/native/meta-drm-buffer-gbm.h" #include "backends/native/meta-drm-buffer-import.h" #include "backends/native/meta-drm-buffer.h" +#include "backends/native/meta-frame-native.h" #include "backends/native/meta-kms-device.h" #include "backends/native/meta-kms-utils.h" #include "backends/native/meta-kms.h" @@ -412,6 +413,7 @@ static void meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaRendererView *view, MetaCrtc *crtc, + MetaKmsUpdate *kms_update, MetaKmsPageFlipListenerFlag flags, const int *rectangles, int n_rectangles) @@ -423,9 +425,6 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); MetaRendererNativeGpuData *renderer_gpu_data; MetaGpuKms *gpu_kms; - MetaKmsDevice *kms_device; - MetaKms *kms; - MetaKmsUpdate *kms_update; MetaDrmBuffer *buffer; MetaKmsPlaneAssignment *plane_assignment; @@ -433,9 +432,6 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, "Onscreen (flip CRTCs)"); 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); g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc)); @@ -478,20 +474,15 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, static void meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, + MetaKmsUpdate *kms_update, MetaRendererNativeGpuData *renderer_gpu_data) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdate *kms_update; COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes, "Onscreen (set CRTC modes)"); - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -1002,7 +993,8 @@ update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen, } static void -ensure_crtc_modes (CoglOnscreen *onscreen) +ensure_crtc_modes (CoglOnscreen *onscreen, + MetaKmsUpdate *kms_update) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); @@ -1014,7 +1006,7 @@ ensure_crtc_modes (CoglOnscreen *onscreen) if (meta_renderer_native_pop_pending_mode_set (renderer_native, onscreen_native->view)) - meta_onscreen_native_set_crtc_mode (onscreen, renderer_gpu_data); + meta_onscreen_native_set_crtc_mode (onscreen, kms_update, renderer_gpu_data); } static void @@ -1062,14 +1054,14 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; MetaRenderer *renderer = META_RENDERER (renderer_native); MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaGpuKms *render_gpu = onscreen_native->render_gpu; MetaDeviceFile *render_device_file; ClutterFrame *frame = user_data; + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); + MetaKmsUpdate *kms_update; CoglOnscreenClass *parent_class; gboolean egl_context_changed = FALSE; MetaPowerSave power_save_mode; @@ -1080,6 +1072,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL; MetaKmsCrtc *kms_crtc; MetaKmsDevice *kms_device; + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, "Onscreen (swap-buffers)"); @@ -1168,17 +1161,17 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); if (power_save_mode == META_POWER_SAVE_ON) { - MetaKmsUpdate *kms_update; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_frame_native_ensure_kms_update (frame_native, + kms_device); meta_kms_update_add_result_listener (kms_update, on_swap_buffer_update_result, onscreen_native); - ensure_crtc_modes (onscreen); + ensure_crtc_modes (onscreen, kms_update); meta_onscreen_native_flip_crtc (onscreen, onscreen_native->view, onscreen_native->crtc, + kms_update, META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE, rectangles, n_rectangles); @@ -1205,6 +1198,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_kms_crtc_get_id (kms_crtc), meta_kms_device_get_path (kms_device)); + kms_update = meta_frame_native_steal_kms_update (frame_native); + meta_renderer_native_queue_mode_set_update (renderer_native, + kms_update); clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); return; @@ -1214,7 +1210,11 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_topic (META_DEBUG_KMS, "Posting global mode set updates on %s", meta_kms_device_get_path (kms_device)); - meta_renderer_native_notify_mode_sets_reset (renderer_native); + kms_update = meta_frame_native_steal_kms_update (frame_native); + meta_renderer_native_queue_mode_set_update (renderer_native, + kms_update); + + meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_post_mode_set_updates (renderer_native); clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); @@ -1228,7 +1228,10 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, case META_RENDERER_NATIVE_MODE_EGL_DEVICE: if (meta_renderer_native_has_pending_mode_set (renderer_native)) { - meta_renderer_native_notify_mode_sets_reset (renderer_native); + kms_update = meta_frame_native_steal_kms_update (frame_native); + meta_renderer_native_queue_mode_set_update (renderer_native, + kms_update); + meta_renderer_native_post_mode_set_updates (renderer_native); clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); @@ -1243,7 +1246,10 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_kms_crtc_get_id (kms_crtc), meta_kms_device_get_path (kms_device)); - meta_kms_post_pending_update_sync (kms, kms_device, META_KMS_UPDATE_FLAG_NONE); + kms_update = meta_frame_native_steal_kms_update (frame_native); + kms_feedback = + meta_kms_device_process_update_sync (kms_device, kms_update, + META_KMS_UPDATE_FLAG_NONE); clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); } @@ -1332,17 +1338,17 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; 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); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); MetaPowerSave power_save_mode; ClutterFrame *frame = user_data; + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaDrmBuffer *scanout_buffer; GError *fill_timings_error = NULL; MetaKmsCrtc *kms_crtc; MetaKmsDevice *kms_device; MetaKmsUpdate *kms_update; + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); if (power_save_mode != META_POWER_SAVE_ON) @@ -1400,7 +1406,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); kms_device = meta_kms_crtc_get_device (kms_crtc); - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, on_scanout_update_result, @@ -1409,6 +1415,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, meta_onscreen_native_flip_crtc (onscreen, onscreen_native->view, onscreen_native->crtc, + kms_update, META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE, NULL, 0); @@ -1418,8 +1425,11 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, meta_kms_crtc_get_id (kms_crtc), meta_kms_device_get_path (kms_device)); + kms_update = meta_frame_native_steal_kms_update (frame_native); + kms_feedback = + meta_kms_device_process_update_sync (kms_device, kms_update, + META_KMS_UPDATE_FLAG_NONE); clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - meta_kms_post_pending_update_sync (kms, kms_device, META_KMS_UPDATE_FLAG_NONE); return TRUE; } @@ -1446,8 +1456,8 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen, MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); MetaOutputKms *output_kms = META_OUTPUT_KMS (onscreen_native->output); MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); - MetaKms *kms = meta_kms_device_get_kms (kms_device); + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);; + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); if (onscreen_native->is_gamma_lut_invalid) { @@ -1458,7 +1468,8 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen, { MetaKmsUpdate *kms_update; - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_frame_native_ensure_kms_update (frame_native, + kms_device); meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, gamma); @@ -1472,7 +1483,8 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen, MetaKmsUpdate *kms_update; gboolean enabled; - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_frame_native_ensure_kms_update (frame_native, + kms_device); enabled = meta_output_is_privacy_screen_enabled (onscreen_native->output); meta_kms_update_set_privacy_screen (kms_update, kms_connector, enabled); @@ -1487,10 +1499,11 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaCrtc *crtc = onscreen_native->crtc; MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); - MetaKms *kms = meta_kms_device_get_kms (kms_device); + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - kms_update = meta_kms_get_pending_update (kms, kms_device); + kms_update = meta_frame_native_steal_kms_update (frame_native); if (!kms_update) { clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); @@ -1510,7 +1523,9 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, meta_kms_crtc_get_id (kms_crtc), meta_kms_device_get_path (kms_device)); - meta_kms_post_pending_update_sync (kms, kms_device, META_KMS_UPDATE_FLAG_NONE); + kms_feedback = + meta_kms_device_process_update_sync (kms_device, kms_update, + META_KMS_UPDATE_FLAG_NONE); clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); } diff --git a/src/backends/native/meta-renderer-native-private.h b/src/backends/native/meta-renderer-native-private.h index e2e133bd9..5e741bff7 100644 --- a/src/backends/native/meta-renderer-native-private.h +++ b/src/backends/native/meta-renderer-native-private.h @@ -75,6 +75,7 @@ MetaGles3 * meta_renderer_native_get_gles3 (MetaRendererNative *renderer_native) MetaRendererNativeGpuData * meta_renderer_native_get_gpu_data (MetaRendererNative *renderer_native, MetaGpuKms *gpu_kms); +META_EXPORT_TEST gboolean meta_renderer_native_has_pending_mode_sets (MetaRendererNative *renderer_native); gboolean meta_renderer_native_has_pending_mode_set (MetaRendererNative *renderer_native); @@ -83,6 +84,9 @@ void meta_renderer_native_notify_mode_sets_reset (MetaRendererNative *renderer_n void meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native); +void meta_renderer_native_queue_mode_set_update (MetaRendererNative *renderer_native, + MetaKmsUpdate *new_kms_update); + void meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_native, CoglOnscreen *onscreen); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 1a3195166..4da361e2b 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -101,6 +101,8 @@ struct _MetaRendererNative GList *power_save_page_flip_onscreens; guint power_save_page_flip_source_id; + + GHashTable *mode_set_updates; }; static void @@ -298,6 +300,22 @@ meta_renderer_native_disconnect (CoglRenderer *cogl_renderer) g_free (cogl_renderer_egl); } +static MetaKmsUpdate * +ensure_mode_set_update (MetaRendererNative *renderer_native, + MetaKmsDevice *kms_device) +{ + MetaKmsUpdate *kms_update; + + kms_update = g_hash_table_lookup (renderer_native->mode_set_updates, + kms_device); + if (kms_update) + return kms_update; + + kms_update = meta_kms_update_new (kms_device); + + return kms_update; +} + static gboolean meta_renderer_native_connect (CoglRenderer *cogl_renderer, GError **error) @@ -664,9 +682,9 @@ meta_renderer_native_create_dma_buf_framebuffer (MetaRendererNative *renderer_n } static void -configure_disabled_crtcs (MetaKmsDevice *kms_device) +configure_disabled_crtcs (MetaKmsDevice *kms_device, + MetaRendererNative *renderer_native) { - MetaKms *kms = meta_kms_device_get_kms (kms_device); GList *l; for (l = meta_kms_device_get_crtcs (kms_device); l; l = l->next) @@ -681,7 +699,7 @@ configure_disabled_crtcs (MetaKmsDevice *kms_device) if (!meta_kms_crtc_is_active (kms_crtc)) continue; - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = ensure_mode_set_update (renderer_native, kms_device); meta_kms_update_mode_set (kms_update, kms_crtc, NULL, NULL); } } @@ -831,32 +849,44 @@ on_mode_sets_update_result (const MetaKmsFeedback *kms_feedback, g_warning ("Failed to post KMS update: %s", feedback_error->message); } +static void +post_mode_set_updates (MetaRendererNative *renderer_native) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, renderer_native->mode_set_updates); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + MetaKmsDevice *kms_device = META_KMS_DEVICE (key); + MetaKmsUpdate *kms_update = value; + g_autoptr (MetaKmsFeedback) feedback = NULL; + + g_hash_table_iter_steal (&iter); + + meta_kms_update_add_result_listener (kms_update, + on_mode_sets_update_result, + NULL); + + feedback = meta_kms_device_process_update_sync (kms_device, kms_update, + META_KMS_UPDATE_FLAG_NONE); + } +} + void meta_renderer_native_post_mode_set_updates (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)); - GList *l; - for (l = meta_kms_get_devices (kms); l; l = l->next) - { - MetaKmsDevice *kms_device = l->data; - MetaKmsUpdate *kms_update; + renderer_native->pending_mode_set = FALSE; - configure_disabled_crtcs (kms_device); + g_list_foreach (meta_kms_get_devices (kms), + (GFunc) configure_disabled_crtcs, + renderer_native); - kms_update = meta_kms_get_pending_update (kms, kms_device); - if (!kms_update) - continue; - - meta_kms_update_add_result_listener (kms_update, - on_mode_sets_update_result, - NULL); - - meta_kms_post_pending_update_sync (kms, kms_device, - META_KMS_UPDATE_FLAG_NONE); - } + post_mode_set_updates (renderer_native); clear_detached_onscreens (renderer_native); @@ -865,10 +895,31 @@ meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native) free_unused_gpu_datas (renderer_native); } -static void -unset_disabled_crtcs (MetaBackend *backend, - MetaKms *kms) +void +meta_renderer_native_queue_mode_set_update (MetaRendererNative *renderer_native, + MetaKmsUpdate *new_kms_update) { + MetaKmsDevice *kms_device = meta_kms_update_get_device (new_kms_update); + MetaKmsUpdate *kms_update; + + kms_update = g_hash_table_lookup (renderer_native->mode_set_updates, + kms_device); + if (!kms_update) + { + g_hash_table_insert (renderer_native->mode_set_updates, + kms_device, new_kms_update); + return; + } + + meta_kms_update_merge_from (kms_update, new_kms_update); + meta_kms_update_free (new_kms_update); +} + +static void +unset_disabled_crtcs (MetaRendererNative *renderer_native) +{ + MetaRenderer *renderer = META_RENDERER (renderer_native); + MetaBackend *backend = meta_renderer_get_backend (renderer); GList *l; meta_topic (META_DEBUG_KMS, "Disabling all disabled CRTCs"); @@ -889,19 +940,12 @@ unset_disabled_crtcs (MetaBackend *backend, if (meta_crtc_get_config (crtc)) continue; - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = ensure_mode_set_update (renderer_native, kms_device); meta_crtc_kms_set_mode (META_CRTC_KMS (crtc), kms_update); } - - if (!kms_update) - continue; - - meta_kms_update_add_result_listener (kms_update, - on_mode_sets_update_result, - NULL); - meta_kms_post_pending_update_sync (kms, kms_device, - META_KMS_UPDATE_FLAG_NONE); } + + post_mode_set_updates (renderer_native); } static CoglDmaBufHandle * @@ -1432,6 +1476,7 @@ detach_onscreens (MetaRenderer *renderer) static void meta_renderer_native_rebuild_views (MetaRenderer *renderer) { + MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); MetaBackend *backend = meta_renderer_get_backend (renderer); MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaKms *kms = meta_backend_native_get_kms (backend_native); @@ -1439,7 +1484,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) META_RENDERER_CLASS (meta_renderer_native_parent_class); meta_kms_discard_pending_page_flips (kms); - meta_kms_discard_pending_updates (kms); + g_hash_table_remove_all (renderer_native->mode_set_updates); detach_onscreens (renderer); @@ -1930,12 +1975,7 @@ on_power_save_mode_changed (MetaMonitorManager *monitor_manager, void meta_renderer_native_reset_modes (MetaRendererNative *renderer_native) { - 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); - - unset_disabled_crtcs (backend, kms); + unset_disabled_crtcs (renderer_native); } static MetaGpuKms * @@ -2133,6 +2173,7 @@ meta_renderer_native_finalize (GObject *object) g_source_remove); g_list_free (renderer_native->pending_mode_set_views); + g_hash_table_unref (renderer_native->mode_set_updates); g_clear_handle_id (&renderer_native->release_unused_gpus_idle_id, g_source_remove); @@ -2173,6 +2214,10 @@ meta_renderer_native_init (MetaRendererNative *renderer_native) g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) meta_renderer_native_gpu_data_free); + renderer_native->mode_set_updates = + g_hash_table_new_full (NULL, NULL, + NULL, + (GDestroyNotify) meta_kms_update_free); } static void diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h index b39e35f80..f34881889 100644 --- a/src/backends/native/meta-renderer-native.h +++ b/src/backends/native/meta-renderer-native.h @@ -34,6 +34,7 @@ #include "backends/native/meta-monitor-manager-native.h" #define META_TYPE_RENDERER_NATIVE (meta_renderer_native_get_type ()) +META_EXPORT_TEST G_DECLARE_FINAL_TYPE (MetaRendererNative, meta_renderer_native, META, RENDERER_NATIVE, MetaRenderer) diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c index 7aad9b643..8cdf6cb02 100644 --- a/src/backends/native/meta-stage-native.c +++ b/src/backends/native/meta-stage-native.c @@ -130,7 +130,8 @@ meta_stage_native_prepare_frame (ClutterStageWindow *stage_window, META_RENDERER_VIEW (stage_view), frame); meta_cursor_renderer_native_prepare_frame (cursor_renderer_native, - META_RENDERER_VIEW (stage_view)); + META_RENDERER_VIEW (stage_view), + frame); } static void diff --git a/src/core/util-private.h b/src/core/util-private.h index 806cdc652..d6af275b3 100644 --- a/src/core/util-private.h +++ b/src/core/util-private.h @@ -50,4 +50,7 @@ void meta_init_debug_utils (void); (ycoord) >= (rect).y && \ (ycoord) < ((rect).y + (rect).height)) +#define META_CONTAINER_OF(ptr, type, member) \ + (type *) ((uint8_t *) (ptr) - G_STRUCT_OFFSET (type, member)) + #endif diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c index 841d1064c..1557b764e 100644 --- a/src/tests/native-kms-render.c +++ b/src/tests/native-kms-render.c @@ -26,7 +26,9 @@ #include "backends/native/meta-crtc-kms.h" #include "backends/native/meta-device-pool.h" #include "backends/native/meta-drm-buffer.h" +#include "backends/native/meta-frame-native.h" #include "backends/native/meta-onscreen-native.h" +#include "backends/native/meta-renderer-native-private.h" #include "backends/native/meta-kms.h" #include "backends/native/meta-kms-device.h" #include "backends/native/meta-kms-device-private.h" @@ -77,6 +79,14 @@ on_after_update (ClutterStage *stage, ClutterFrame *frame, KmsRenderingTest *test) { + MetaBackend *backend = meta_context_get_backend (test_context); + MetaRenderer *renderer = meta_backend_get_renderer (backend); + MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); + + g_assert (meta_renderer_native_has_pending_mode_sets (renderer_native) || + !meta_frame_native_has_kms_update (frame_native)); + test->number_of_frames_left--; if (test->number_of_frames_left == 0) g_main_loop_quit (test->loop); @@ -342,7 +352,7 @@ on_scanout_fallback_before_paint (ClutterStage *stage, 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); - MetaKms *kms = meta_kms_device_get_kms (kms_device); + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); CoglScanout *scanout; MetaKmsUpdate *kms_update; @@ -364,7 +374,7 @@ on_scanout_fallback_before_paint (ClutterStage *stage, test->scanout_fallback.scanout_sabotaged = TRUE; - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, on_scanout_fallback_result, test);