diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index 9baccbd0e..b68266200 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -649,10 +649,11 @@ clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl, cairo_region_destroy (swap_region); } -static void -clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl, - ClutterStageView *view, - CoglScanout *scanout) +static gboolean +clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl, + ClutterStageView *view, + CoglScanout *scanout, + GError **error) { ClutterStageCoglPrivate *priv = _clutter_stage_cogl_get_instance_private (stage_cogl); @@ -660,14 +661,21 @@ clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl, CoglOnscreen *onscreen; CoglFrameInfo *frame_info; - g_return_if_fail (cogl_is_onscreen (framebuffer)); + g_assert (cogl_is_onscreen (framebuffer)); onscreen = COGL_ONSCREEN (framebuffer); frame_info = cogl_frame_info_new (priv->global_frame_counter); + + if (!cogl_onscreen_direct_scanout (onscreen, scanout, frame_info, error)) + { + cogl_object_unref (frame_info); + return FALSE; + } + priv->global_frame_counter++; - cogl_onscreen_direct_scanout (onscreen, scanout, frame_info); + return TRUE; } static void @@ -679,9 +687,16 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, scanout = clutter_stage_view_take_scanout (view); if (scanout) - clutter_stage_cogl_scanout_view (stage_cogl, view, scanout); - else - clutter_stage_cogl_redraw_view_primary (stage_cogl, view); + { + g_autoptr (GError) error = NULL; + + if (clutter_stage_cogl_scanout_view (stage_cogl, view, scanout, &error)) + return; + + g_warning ("Failed to scan out client buffer: %s", error->message); + } + + clutter_stage_cogl_redraw_view_primary (stage_cogl, view); } static void diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c index a3c1514a5..4f3f48fbe 100644 --- a/cogl/cogl/cogl-onscreen.c +++ b/cogl/cogl/cogl-onscreen.c @@ -406,24 +406,30 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen) return winsys->onscreen_get_buffer_age (onscreen); } -void -cogl_onscreen_direct_scanout (CoglOnscreen *onscreen, - CoglScanout *scanout, - CoglFrameInfo *info) +gboolean +cogl_onscreen_direct_scanout (CoglOnscreen *onscreen, + CoglScanout *scanout, + CoglFrameInfo *info, + GError **error) { CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); const CoglWinsysVtable *winsys; - g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN); - g_return_if_fail (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)); + g_warn_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN); + g_warn_if_fail (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)); info->frame_counter = onscreen->frame_counter; g_queue_push_tail (&onscreen->pending_frame_infos, info); winsys = _cogl_framebuffer_get_winsys (framebuffer); - winsys->onscreen_direct_scanout (onscreen, scanout, info); + if (!winsys->onscreen_direct_scanout (onscreen, scanout, info, error)) + { + g_queue_pop_tail (&onscreen->pending_frame_infos); + return FALSE; + } onscreen->frame_counter++; + return TRUE; } #ifdef COGL_HAS_X11_SUPPORT diff --git a/cogl/cogl/cogl-onscreen.h b/cogl/cogl/cogl-onscreen.h index b0cd99fce..824672f5e 100644 --- a/cogl/cogl/cogl-onscreen.h +++ b/cogl/cogl/cogl-onscreen.h @@ -291,10 +291,11 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, /** * cogl_onscreen_direct_scanout: (skip) */ -COGL_EXPORT void -cogl_onscreen_direct_scanout (CoglOnscreen *onscreen, - CoglScanout *scanout, - CoglFrameInfo *info); +COGL_EXPORT gboolean +cogl_onscreen_direct_scanout (CoglOnscreen *onscreen, + CoglScanout *scanout, + CoglFrameInfo *info, + GError **error); /** * cogl_onscreen_swap_region: diff --git a/cogl/cogl/winsys/cogl-winsys-private.h b/cogl/cogl/winsys/cogl-winsys-private.h index b9dbff524..2cf88f39b 100644 --- a/cogl/cogl/winsys/cogl-winsys-private.h +++ b/cogl/cogl/winsys/cogl-winsys-private.h @@ -119,10 +119,11 @@ typedef struct _CoglWinsysVtable int n_rectangles, CoglFrameInfo *info); - void - (*onscreen_direct_scanout) (CoglOnscreen *onscreen, - CoglScanout *scanout, - CoglFrameInfo *info); + gboolean + (*onscreen_direct_scanout) (CoglOnscreen *onscreen, + CoglScanout *scanout, + CoglFrameInfo *info, + GError **error); void (*onscreen_set_visibility) (CoglOnscreen *onscreen, diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c index 9501fc839..385e828cc 100644 --- a/src/backends/native/meta-crtc-kms.c +++ b/src/backends/native/meta-crtc-kms.c @@ -206,12 +206,14 @@ meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms, void meta_crtc_kms_page_flip (MetaCrtcKms *crtc_kms, const MetaKmsPageFlipFeedback *page_flip_feedback, + MetaKmsPageFlipFlag flags, gpointer user_data, MetaKmsUpdate *kms_update) { meta_kms_update_page_flip (kms_update, meta_crtc_kms_get_kms_crtc (crtc_kms), page_flip_feedback, + flags, user_data); } diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h index 9ca80c438..3e3e1a6e8 100644 --- a/src/backends/native/meta-crtc-kms.h +++ b/src/backends/native/meta-crtc-kms.h @@ -30,6 +30,7 @@ #include "backends/meta-crtc.h" #include "backends/native/meta-gpu-kms.h" #include "backends/native/meta-kms-crtc.h" +#include "backends/native/meta-kms-update.h" #define META_TYPE_CRTC_KMS (meta_crtc_kms_get_type ()) G_DECLARE_FINAL_TYPE (MetaCrtcKms, meta_crtc_kms, @@ -56,6 +57,7 @@ void meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms, void meta_crtc_kms_page_flip (MetaCrtcKms *crtc_kms, const MetaKmsPageFlipFeedback *page_flip_feedback, + MetaKmsPageFlipFlag flags, gpointer user_data, MetaKmsUpdate *kms_update); diff --git a/src/backends/native/meta-kms-impl-simple.c b/src/backends/native/meta-kms-impl-simple.c index 5aa7adc08..1afc89f74 100644 --- a/src/backends/native/meta-kms-impl-simple.c +++ b/src/backends/native/meta-kms-impl-simple.c @@ -988,6 +988,9 @@ err_planes_assigned: { MetaKmsPageFlip *page_flip = l->data; + if (page_flip->flags & META_KMS_PAGE_FLIP_FLAG_NO_DISCARD_FEEDBACK) + continue; + discard_page_flip (impl, update, page_flip); } diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index 4d4d4a276..df886b8dd 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -87,6 +87,7 @@ typedef struct _MetaKmsPageFlip { MetaKmsCrtc *crtc; const MetaKmsPageFlipFeedback *feedback; + MetaKmsPageFlipFlag flags; gpointer user_data; MetaKmsCustomPageFlipFunc custom_page_flip_func; gpointer custom_page_flip_user_data; diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c index d1092b43f..94dd23e2c 100644 --- a/src/backends/native/meta-kms-update.c +++ b/src/backends/native/meta-kms-update.c @@ -285,6 +285,7 @@ void meta_kms_update_page_flip (MetaKmsUpdate *update, MetaKmsCrtc *crtc, const MetaKmsPageFlipFeedback *feedback, + MetaKmsPageFlipFlag flags, gpointer user_data) { MetaKmsPageFlip *page_flip; @@ -295,6 +296,7 @@ meta_kms_update_page_flip (MetaKmsUpdate *update, *page_flip = (MetaKmsPageFlip) { .crtc = crtc, .feedback = feedback, + .flags = flags, .user_data = user_data, }; diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h index 1727c1974..0684ad181 100644 --- a/src/backends/native/meta-kms-update.h +++ b/src/backends/native/meta-kms-update.h @@ -41,6 +41,12 @@ typedef enum _MetaKmsAssignPlaneFlag META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED = 1 << 0, } MetaKmsAssignPlaneFlag; +typedef enum _MetaKmsPageFlipFlag +{ + META_KMS_PAGE_FLIP_FLAG_NONE = 0, + META_KMS_PAGE_FLIP_FLAG_NO_DISCARD_FEEDBACK = 1 << 0, +} MetaKmsPageFlipFlag; + struct _MetaKmsPageFlipFeedback { void (* flipped) (MetaKmsCrtc *crtc, @@ -99,6 +105,7 @@ MetaKmsPlaneAssignment * meta_kms_update_unassign_plane (MetaKmsUpdate *update, void meta_kms_update_page_flip (MetaKmsUpdate *update, MetaKmsCrtc *crtc, const MetaKmsPageFlipFeedback *feedback, + MetaKmsPageFlipFlag flags, gpointer user_data); void meta_kms_update_custom_page_flip (MetaKmsUpdate *update, diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index cf29fc9b5..b183cbf0e 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -1251,10 +1251,11 @@ queue_dummy_power_save_page_flip (CoglOnscreen *onscreen) } static void -meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, - MetaRendererView *view, - MetaCrtc *crtc, - MetaKmsUpdate *kms_update) +meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, + MetaRendererView *view, + MetaCrtc *crtc, + MetaKmsPageFlipFlag flags, + MetaKmsUpdate *kms_update) { CoglOnscreenEGL *onscreen_egl = onscreen->winsys; MetaOnscreenNative *onscreen_native = onscreen_egl->platform; @@ -1288,6 +1289,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, meta_crtc_kms_assign_primary_plane (crtc_kms, fb_id, kms_update); meta_crtc_kms_page_flip (crtc_kms, &page_flip_feedback, + flags, g_object_ref (view), kms_update); @@ -1340,8 +1342,9 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, } static void -meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen, - MetaKmsUpdate *kms_update) +meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen, + MetaKmsPageFlipFlag flags, + MetaKmsUpdate *kms_update) { CoglOnscreenEGL *onscreen_egl = onscreen->winsys; MetaOnscreenNative *onscreen_native = onscreen_egl->platform; @@ -1359,6 +1362,7 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen, if (power_save_mode == META_POWER_SAVE_ON) { meta_onscreen_native_flip_crtc (onscreen, view, onscreen_native->crtc, + flags, kms_update); } else @@ -1925,7 +1929,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed); ensure_crtc_modes (onscreen, kms_update); - meta_onscreen_native_flip_crtcs (onscreen, kms_update); + meta_onscreen_native_flip_crtcs (onscreen, + META_KMS_PAGE_FLIP_FLAG_NONE, + kms_update); /* * If we changed EGL context, cogl will have the wrong idea about what is @@ -2072,10 +2078,11 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, return TRUE; } -static void -meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, - CoglScanout *scanout, - CoglFrameInfo *frame_info) +static gboolean +meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, + CoglScanout *scanout, + CoglFrameInfo *frame_info, + GError **error) { CoglOnscreenEGL *onscreen_egl = onscreen->winsys; MetaOnscreenNative *onscreen_native = onscreen_egl->platform; @@ -2090,21 +2097,38 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaKms *kms = meta_backend_native_get_kms (backend_native); MetaKmsUpdate *kms_update; + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; kms_update = meta_kms_ensure_pending_update (kms); renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, render_gpu); - g_return_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM); - + g_warn_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM); g_warn_if_fail (!onscreen_native->gbm.next_fb); + g_set_object (&onscreen_native->gbm.next_fb, META_DRM_BUFFER (scanout)); ensure_crtc_modes (onscreen, kms_update); - meta_onscreen_native_flip_crtcs (onscreen, kms_update); + meta_onscreen_native_flip_crtcs (onscreen, + META_KMS_PAGE_FLIP_FLAG_NO_DISCARD_FEEDBACK, + kms_update); - meta_kms_post_pending_update_sync (kms); + kms_feedback = meta_kms_post_pending_update_sync (kms); + if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) + { + const GError *feedback_error = meta_kms_feedback_get_error (kms_feedback); + + if (g_error_matches (feedback_error, + G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) + return TRUE; + + g_clear_object (&onscreen_native->gbm.next_fb); + g_propagate_error (error, g_error_copy (feedback_error)); + return FALSE; + } + + return TRUE; } static gboolean