From 52c4b8516136b28c17ffec8b1082729a7920b598 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Sat, 26 Aug 2023 12:39:58 +0200 Subject: [PATCH] cogl: Turn CoglScanout into an object We need an object to hold additional scanout related information, such as scaling and positioning data. Turn CoglScanout into such an object, moving the interface into CoglScanoutBuffer. Part-of: --- cogl/cogl/cogl-scanout.c | 77 +++++++++++++++++----- cogl/cogl/cogl-scanout.h | 17 ++++- cogl/cogl/cogl-types.h | 1 + src/backends/native/meta-drm-buffer-gbm.c | 11 ++-- src/backends/native/meta-onscreen-native.c | 23 +++++-- src/backends/native/meta-onscreen-native.h | 4 +- src/tests/native-kms-render.c | 6 +- src/wayland/meta-wayland-buffer.c | 7 +- src/wayland/meta-wayland-dma-buf.c | 7 +- 9 files changed, 113 insertions(+), 40 deletions(-) diff --git a/cogl/cogl/cogl-scanout.c b/cogl/cogl/cogl-scanout.c index 8999108c0..3efb914a0 100644 --- a/cogl/cogl/cogl-scanout.c +++ b/cogl/cogl/cogl-scanout.c @@ -38,18 +38,20 @@ enum static guint signals[N_SIGNALS]; -G_DEFINE_INTERFACE (CoglScanout, cogl_scanout, G_TYPE_OBJECT) +G_DEFINE_INTERFACE (CoglScanoutBuffer, cogl_scanout_buffer, G_TYPE_OBJECT) + +struct _CoglScanout +{ + GObject parent; + + CoglScanoutBuffer *scanout_buffer; +}; + +G_DEFINE_FINAL_TYPE (CoglScanout, cogl_scanout, G_TYPE_OBJECT); static void -cogl_scanout_default_init (CoglScanoutInterface *iface) +cogl_scanout_buffer_default_init (CoglScanoutBufferInterface *iface) { - signals[SCANOUT_FAILED] = - g_signal_new ("scanout-failed", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, - COGL_TYPE_ONSCREEN); } gboolean @@ -59,16 +61,16 @@ cogl_scanout_blit_to_framebuffer (CoglScanout *scanout, int y, GError **error) { - CoglScanoutInterface *iface; + CoglScanoutBufferInterface *iface = + COGL_SCANOUT_BUFFER_GET_IFACE (scanout->scanout_buffer); - g_return_val_if_fail (COGL_IS_SCANOUT (scanout), FALSE); + return iface->blit_to_framebuffer (scanout, framebuffer, x, y, error); +} - iface = COGL_SCANOUT_GET_IFACE (scanout); - - if (iface->blit_to_framebuffer) - return iface->blit_to_framebuffer (scanout, framebuffer, x, y, error); - else - return FALSE; +CoglScanoutBuffer * +cogl_scanout_get_buffer (CoglScanout *scanout) +{ + return scanout->scanout_buffer; } void @@ -77,3 +79,44 @@ cogl_scanout_notify_failed (CoglScanout *scanout, { g_signal_emit (scanout, signals[SCANOUT_FAILED], 0, onscreen); } + +CoglScanout * +cogl_scanout_new (CoglScanoutBuffer *scanout_buffer) +{ + CoglScanout *scanout = g_object_new (COGL_TYPE_SCANOUT, NULL); + + scanout->scanout_buffer = scanout_buffer; + + return scanout; +} + +static void +cogl_scanout_finalize (GObject *object) +{ + CoglScanout *scanout = COGL_SCANOUT (object); + + g_clear_object (&scanout->scanout_buffer); + + G_OBJECT_CLASS (cogl_scanout_parent_class)->finalize (object); +} + +static void +cogl_scanout_class_init (CoglScanoutClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = cogl_scanout_finalize; + + signals[SCANOUT_FAILED] = + g_signal_new ("scanout-failed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, + COGL_TYPE_ONSCREEN); +} + +static void +cogl_scanout_init (CoglScanout *scanout) +{ +} diff --git a/cogl/cogl/cogl-scanout.h b/cogl/cogl/cogl-scanout.h index f6c2c7c48..c8007e60e 100644 --- a/cogl/cogl/cogl-scanout.h +++ b/cogl/cogl/cogl-scanout.h @@ -35,10 +35,15 @@ #define COGL_TYPE_SCANOUT (cogl_scanout_get_type ()) COGL_EXPORT -G_DECLARE_INTERFACE (CoglScanout, cogl_scanout, - COGL, SCANOUT, GObject) +G_DECLARE_FINAL_TYPE (CoglScanout, cogl_scanout, + COGL, SCANOUT, GObject) -struct _CoglScanoutInterface +#define COGL_TYPE_SCANOUT_BUFFER (cogl_scanout_buffer_get_type ()) +COGL_EXPORT +G_DECLARE_INTERFACE (CoglScanoutBuffer, cogl_scanout_buffer, + COGL, SCANOUT_BUFFER, GObject) + +struct _CoglScanoutBufferInterface { GTypeInterface parent_iface; @@ -56,6 +61,12 @@ gboolean cogl_scanout_blit_to_framebuffer (CoglScanout *scanout, int y, GError **error); +COGL_EXPORT +CoglScanoutBuffer * cogl_scanout_get_buffer (CoglScanout *scanout); + COGL_EXPORT void cogl_scanout_notify_failed (CoglScanout *scanout, CoglOnscreen *onscreen); + +COGL_EXPORT +CoglScanout * cogl_scanout_new (CoglScanoutBuffer *scanout_buffer); diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h index 30749da1c..177406ded 100644 --- a/cogl/cogl/cogl-types.h +++ b/cogl/cogl/cogl-types.h @@ -426,6 +426,7 @@ typedef enum } CoglStereoMode; typedef struct _CoglScanout CoglScanout; +typedef struct _CoglScanoutBuffer CoglScanoutBuffer; #define COGL_SCANOUT_ERROR (cogl_scanout_error_quark ()) diff --git a/src/backends/native/meta-drm-buffer-gbm.c b/src/backends/native/meta-drm-buffer-gbm.c index 5c7e5f79e..c2ed99e38 100644 --- a/src/backends/native/meta-drm-buffer-gbm.c +++ b/src/backends/native/meta-drm-buffer-gbm.c @@ -44,11 +44,11 @@ struct _MetaDrmBufferGbm }; static void -cogl_scanout_iface_init (CoglScanoutInterface *iface); +cogl_scanout_buffer_iface_init (CoglScanoutBufferInterface *iface); G_DEFINE_TYPE_WITH_CODE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER, - G_IMPLEMENT_INTERFACE (COGL_TYPE_SCANOUT, - cogl_scanout_iface_init)) + G_IMPLEMENT_INTERFACE (COGL_TYPE_SCANOUT_BUFFER, + cogl_scanout_buffer_iface_init)) struct gbm_bo * meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm) @@ -236,7 +236,8 @@ meta_drm_buffer_gbm_blit_to_framebuffer (CoglScanout *scanout, int y, GError **error) { - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (scanout); + CoglScanoutBuffer *scanout_buffer = cogl_scanout_get_buffer (scanout); + MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (scanout_buffer); MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_gbm); MetaDeviceFile *device_file = meta_drm_buffer_get_device_file (buffer); MetaDevicePool *device_pool = meta_device_file_get_pool (device_file); @@ -357,7 +358,7 @@ out: } static void -cogl_scanout_iface_init (CoglScanoutInterface *iface) +cogl_scanout_buffer_iface_init (CoglScanoutBufferInterface *iface) { iface->blit_to_framebuffer = meta_drm_buffer_gbm_blit_to_framebuffer; } diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index be597ec45..81c6857e7 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -98,6 +98,8 @@ struct _MetaOnscreenNative struct gbm_surface *surface; MetaDrmBuffer *current_fb; MetaDrmBuffer *next_fb; + CoglScanout *current_scanout; + CoglScanout *next_scanout; } gbm; #ifdef HAVE_EGL_DEVICE @@ -137,6 +139,7 @@ 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 @@ -151,6 +154,9 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *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); } static void @@ -159,6 +165,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); } static void @@ -1425,8 +1432,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, } gboolean -meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, - MetaDrmBuffer *fb) +meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, + CoglScanout *scanout) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaCrtc *crtc = onscreen_native->crtc; @@ -1435,6 +1442,7 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, MetaKmsDevice *kms_device; MetaKmsCrtc *kms_crtc; MetaKmsUpdate *test_update; + MetaDrmBuffer *buffer; g_autoptr (MetaKmsFeedback) kms_feedback = NULL; MetaKmsFeedbackResult result; @@ -1443,7 +1451,8 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); test_update = meta_kms_update_new (kms_device); - assign_primary_plane (crtc_kms, fb, test_update, + buffer = META_DRM_BUFFER (cogl_scanout_get_buffer (scanout)); + assign_primary_plane (crtc_kms, buffer, test_update, META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT); meta_topic (META_DEBUG_KMS, @@ -1480,7 +1489,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Direct scanout page flip failed: %s", error->message); - cogl_scanout_notify_failed (COGL_SCANOUT (onscreen_native->gbm.next_fb), + cogl_scanout_notify_failed (onscreen_native->gbm.next_scanout, onscreen); clutter_stage_view_add_redraw_clip (view, NULL); clutter_stage_view_schedule_update_now (view); @@ -1547,8 +1556,11 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, 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_fb, META_DRM_BUFFER (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))); frame_info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); @@ -2666,6 +2678,7 @@ meta_onscreen_native_dispose (GObject *object) { 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: diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h index 91eb7b533..c1373aeae 100644 --- a/src/backends/native/meta-onscreen-native.h +++ b/src/backends/native/meta-onscreen-native.h @@ -45,8 +45,8 @@ void meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen); -gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, - MetaDrmBuffer *fb); +gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, + CoglScanout *scanout); void meta_onscreen_native_set_view (CoglOnscreen *onscreen, MetaRendererView *view); diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c index 2948aa52f..f5ebc23fe 100644 --- a/src/tests/native-kms-render.c +++ b/src/tests/native-kms-render.c @@ -133,14 +133,16 @@ on_scanout_before_paint (ClutterStage *stage, KmsRenderingTest *test) { CoglScanout *scanout; + CoglScanoutBuffer *scanout_buffer; MetaDrmBuffer *buffer; scanout = clutter_stage_view_peek_scanout (stage_view); if (!scanout) return; - g_assert_true (META_IS_DRM_BUFFER (scanout)); - buffer = META_DRM_BUFFER (scanout); + scanout_buffer = cogl_scanout_get_buffer (scanout); + g_assert_true (META_IS_DRM_BUFFER (scanout_buffer)); + buffer = META_DRM_BUFFER (scanout_buffer); test->scanout.fb_id = meta_drm_buffer_get_fb_id (buffer); g_assert_cmpuint (test->scanout.fb_id, >, 0); } diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c index be7039c2e..f02abc898 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -863,6 +863,7 @@ try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer, struct gbm_bo *gbm_bo; MetaDrmBufferFlags flags; g_autoptr (MetaDrmBufferGbm) fb = NULL; + g_autoptr (CoglScanout) scanout = NULL; g_autoptr (GError) error = NULL; gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native); @@ -887,11 +888,11 @@ try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer, return NULL; } - if (!meta_onscreen_native_is_buffer_scanout_compatible (onscreen, - META_DRM_BUFFER (fb))) + scanout = cogl_scanout_new (COGL_SCANOUT_BUFFER (g_steal_pointer (&fb))); + if (!meta_onscreen_native_is_buffer_scanout_compatible (onscreen, scanout)) return NULL; - return COGL_SCANOUT (g_steal_pointer (&fb)); + return g_steal_pointer (&scanout); #else return NULL; #endif diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c index ef8c540be..3f0447dd7 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c @@ -618,6 +618,7 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandBuffer *buffer, MetaGpuKms *gpu_kms; struct gbm_bo *gbm_bo; g_autoptr (MetaDrmBufferGbm) fb = NULL; + g_autoptr (CoglScanout) scanout = NULL; g_autoptr (GError) error = NULL; MetaDrmBufferFlags flags; gboolean use_modifier; @@ -662,15 +663,15 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandBuffer *buffer, return NULL; } - if (!meta_onscreen_native_is_buffer_scanout_compatible (onscreen, - META_DRM_BUFFER (fb))) + scanout = cogl_scanout_new (COGL_SCANOUT_BUFFER (g_steal_pointer (&fb))); + if (!meta_onscreen_native_is_buffer_scanout_compatible (onscreen, scanout)) { meta_topic (META_DEBUG_RENDER, "Buffer not scanout compatible (see also KMS debug topic)"); return NULL; } - return COGL_SCANOUT (g_steal_pointer (&fb)); + return g_steal_pointer (&scanout); #else return NULL; #endif