From 2e2c54e356331cbbbc4bcad33ab124c6805fe02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 10 Jun 2024 14:59:46 +0200 Subject: [PATCH] onscreen/native: Track next and presenting buffers via ClutterFrame Let the ClutterFrame (or rather MetaFrameNative) own both the scanout object and the framebuffer object, and let the frame itself live for as long as it's needed. This allows to place fields that is related to a single frame together, aiming to help reasoning about the lifetime of the fields that were previously directly stored in MetaOnscreenNative. Also take the opportunity to rename "current" to "presenting", to make it clearer that frame's buffer is what is currently presenting to the user. Part-of: --- src/backends/native/meta-frame-native.c | 32 ++++++++ src/backends/native/meta-frame-native.h | 11 +++ src/backends/native/meta-onscreen-native.c | 93 +++++++++++----------- 3 files changed, 89 insertions(+), 47 deletions(-) diff --git a/src/backends/native/meta-frame-native.c b/src/backends/native/meta-frame-native.c index 146144db0..70461be32 100644 --- a/src/backends/native/meta-frame-native.c +++ b/src/backends/native/meta-frame-native.c @@ -27,6 +27,9 @@ struct _MetaFrameNative { ClutterFrame base; + MetaDrmBuffer *buffer; + CoglScanout *scanout; + MetaKmsUpdate *kms_update; }; @@ -35,6 +38,9 @@ meta_frame_native_release (ClutterFrame *frame) { MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); + g_clear_object (&frame_native->buffer); + g_clear_object (&frame_native->scanout); + g_return_if_fail (!frame_native->kms_update); } @@ -76,3 +82,29 @@ meta_frame_native_has_kms_update (MetaFrameNative *frame_native) { return !!frame_native->kms_update; } + +void +meta_frame_native_set_buffer (MetaFrameNative *frame_native, + MetaDrmBuffer *buffer) +{ + g_set_object (&frame_native->buffer, buffer); +} + +MetaDrmBuffer * +meta_frame_native_get_buffer (MetaFrameNative *frame_native) +{ + return frame_native->buffer; +} + +void +meta_frame_native_set_scanout (MetaFrameNative *frame_native, + CoglScanout *scanout) +{ + g_set_object (&frame_native->scanout, scanout); +} + +CoglScanout * +meta_frame_native_get_scanout (MetaFrameNative *frame_native) +{ + return frame_native->scanout; +} diff --git a/src/backends/native/meta-frame-native.h b/src/backends/native/meta-frame-native.h index f86d3b0b0..3df4eff78 100644 --- a/src/backends/native/meta-frame-native.h +++ b/src/backends/native/meta-frame-native.h @@ -17,6 +17,7 @@ #pragma once +#include "backends/native/meta-backend-native-types.h" #include "backends/native/meta-kms-types.h" #include "clutter/clutter.h" #include "core/util-private.h" @@ -36,3 +37,13 @@ MetaKmsUpdate * meta_frame_native_steal_kms_update (MetaFrameNative *frame_nativ META_EXPORT_TEST gboolean meta_frame_native_has_kms_update (MetaFrameNative *frame_native); + +void meta_frame_native_set_buffer (MetaFrameNative *frame_native, + MetaDrmBuffer *buffer); + +MetaDrmBuffer * meta_frame_native_get_buffer (MetaFrameNative *frame_native); + +void meta_frame_native_set_scanout (MetaFrameNative *frame_native, + CoglScanout *scanout); + +CoglScanout * meta_frame_native_get_scanout (MetaFrameNative *frame_native); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 1a31f04a1..02659a751 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -95,12 +95,11 @@ struct _MetaOnscreenNative MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; + ClutterFrame *presented_frame; + ClutterFrame *next_frame; + struct { struct gbm_surface *surface; - MetaDrmBuffer *current_fb; - MetaDrmBuffer *next_fb; - CoglScanout *current_scanout; - CoglScanout *next_scanout; } gbm; #ifdef HAVE_EGL_DEVICE @@ -137,30 +136,17 @@ init_secondary_gpu_state (MetaRendererNative *renderer_native, CoglOnscreen *onscreen, GError **error); -static void -free_current_bo (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - g_clear_object (&onscreen_native->gbm.current_fb); - g_clear_object (&onscreen_native->gbm.current_scanout); -} - static void meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - if (!onscreen_native->gbm.next_fb) + if (!onscreen_native->next_frame) return; - free_current_bo (onscreen); - - g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb); - g_clear_object (&onscreen_native->gbm.next_fb); - g_set_object (&onscreen_native->gbm.current_scanout, - onscreen_native->gbm.next_scanout); - g_clear_object (&onscreen_native->gbm.next_scanout); + g_clear_pointer (&onscreen_native->presented_frame, clutter_frame_unref); + onscreen_native->presented_frame = + g_steal_pointer (&onscreen_native->next_frame); } static void @@ -168,8 +154,7 @@ meta_onscreen_native_clear_next_fb (CoglOnscreen *onscreen) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - g_clear_object (&onscreen_native->gbm.next_fb); - g_clear_object (&onscreen_native->gbm.next_scanout); + g_clear_pointer (&onscreen_native->next_frame, clutter_frame_unref); } static void @@ -298,7 +283,7 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, frame_info = cogl_onscreen_peek_head_frame_info (onscreen); frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - g_warn_if_fail (!onscreen_native->gbm.next_fb); + g_warn_if_fail (!onscreen_native->next_frame); meta_onscreen_native_notify_frame_complete (onscreen); } @@ -495,16 +480,19 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaKmsUpdate *kms_update, MetaKmsAssignPlaneFlag flags, const int *rectangles, - int n_rectangles) + int n_rectangles, + ClutterFrame *frame) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaRendererNative *renderer_native = onscreen_native->renderer_native; + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaGpuKms *render_gpu = onscreen_native->render_gpu; MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); MetaRendererNativeGpuData *renderer_gpu_data; MetaGpuKms *gpu_kms; MetaDrmBuffer *buffer; + CoglScanout *scanout; MetaKmsPlaneAssignment *plane_assignment; graphene_rect_t src_rect; MtkRectangle dst_rect; @@ -521,14 +509,13 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: - buffer = onscreen_native->gbm.next_fb; + buffer = meta_frame_native_get_buffer (frame_native); + scanout = meta_frame_native_get_scanout (frame_native); - if (onscreen_native->gbm.next_scanout) + if (scanout) { - cogl_scanout_get_src_rect (onscreen_native->gbm.next_scanout, - &src_rect); - cogl_scanout_get_dst_rect (onscreen_native->gbm.next_scanout, - &dst_rect); + cogl_scanout_get_src_rect (scanout, &src_rect); + cogl_scanout_get_dst_rect (scanout, &dst_rect); } else { @@ -1299,6 +1286,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, MetaDrmBufferGbm *buffer_gbm; g_autoptr (MetaDrmBuffer) primary_gpu_fb = NULL; g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL; + MetaDrmBuffer *buffer; MetaKmsCrtc *kms_crtc; MetaKmsDevice *kms_device; @@ -1376,16 +1364,20 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, primary_gpu_fb, &secondary_gpu_fb); + g_warn_if_fail (!onscreen_native->next_frame); + onscreen_native->next_frame = clutter_frame_ref (frame); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: - g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); if (onscreen_native->secondary_gpu_state) - g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb); + buffer = secondary_gpu_fb; else - g_set_object (&onscreen_native->gbm.next_fb, primary_gpu_fb); + buffer = primary_gpu_fb; - if (!meta_drm_buffer_ensure_fb_id (onscreen_native->gbm.next_fb, &error)) + meta_frame_native_set_buffer (frame_native, buffer); + + if (!meta_drm_buffer_ensure_fb_id (buffer, &error)) { g_warning ("Failed to ensure KMS FB ID on %s: %s", meta_device_file_get_path (render_device_file), @@ -1434,7 +1426,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update, META_KMS_ASSIGN_PLANE_FLAG_NONE, rectangles, - n_rectangles); + n_rectangles, + frame); } else { @@ -1577,11 +1570,15 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, G_IO_ERROR_PERMISSION_DENIED)) { ClutterStageView *view = CLUTTER_STAGE_VIEW (onscreen_native->view); + ClutterFrame *next_frame = onscreen_native->next_frame; + MetaFrameNative *next_frame_native = + meta_frame_native_from_frame (next_frame); + CoglScanout *scanout = + meta_frame_native_get_scanout (next_frame_native); g_warning ("Direct scanout page flip failed: %s", error->message); - cogl_scanout_notify_failed (onscreen_native->gbm.next_scanout, - onscreen); + cogl_scanout_notify_failed (scanout, onscreen); clutter_stage_view_add_redraw_clip (view, NULL); clutter_stage_view_schedule_update_now (view); } @@ -1646,12 +1643,13 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, render_gpu); g_warn_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM); - g_warn_if_fail (!onscreen_native->gbm.next_fb); - g_warn_if_fail (!onscreen_native->gbm.next_scanout); - g_set_object (&onscreen_native->gbm.next_scanout, scanout); - g_set_object (&onscreen_native->gbm.next_fb, - META_DRM_BUFFER (cogl_scanout_get_buffer (scanout))); + g_warn_if_fail (!onscreen_native->next_frame); + onscreen_native->next_frame = clutter_frame_ref (frame); + + meta_frame_native_set_scanout (frame_native, scanout); + meta_frame_native_set_buffer (frame_native, + META_DRM_BUFFER (cogl_scanout_get_buffer (scanout))); frame_info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); @@ -1674,7 +1672,8 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, kms_update, META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT, NULL, - 0); + 0, + frame); meta_topic (META_DEBUG_KMS, "Posting direct scanout update for CRTC %u (%s)", @@ -2823,15 +2822,15 @@ meta_onscreen_native_dispose (GObject *object) meta_onscreen_native_detach (onscreen_native); + g_clear_pointer (&onscreen_native->next_frame, clutter_frame_unref); + g_clear_pointer (&onscreen_native->presented_frame, clutter_frame_unref); + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, onscreen_native->render_gpu); switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: - g_clear_object (&onscreen_native->gbm.next_fb); - g_clear_object (&onscreen_native->gbm.next_scanout); - free_current_bo (onscreen); break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached ();