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