From 9d3e4fd40224b946ddb9f40a6a250231e52b297f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 5 May 2020 19:05:36 +0200 Subject: [PATCH] clutter/stage-cogl: Use buffer age when view monitor is rotated We failed to use the buffer age when monitors were rotated, as when they are, we first composite to an offscreen framebuffer, then later again to the onscreen. The buffer age checking happened on the offscreen, and an offscreen being single buffered, they can't possible support buffer ages. Instead, move the buffer age check to check the actual onscreen framebuffer. The offscreen to onscreen painting is still always full frame, but that will be fixed in a later commit. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237 --- clutter/clutter/clutter-stage-view-private.h | 6 +++ clutter/clutter/clutter-stage-view.c | 29 ++++++------ clutter/clutter/clutter-stage-view.h | 11 ++--- clutter/clutter/cogl/clutter-stage-cogl.c | 46 ++++++-------------- src/backends/meta-renderer-view.c | 22 ++++++++++ 5 files changed, 64 insertions(+), 50 deletions(-) diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h index 2855211eb..b5b65a4df 100644 --- a/clutter/clutter/clutter-stage-view-private.h +++ b/clutter/clutter/clutter-stage-view-private.h @@ -52,4 +52,10 @@ cairo_region_t * clutter_stage_view_take_redraw_clip (ClutterStageView *view); CoglScanout * clutter_stage_view_take_scanout (ClutterStageView *view); +void clutter_stage_view_transform_rect_to_onscreen (ClutterStageView *view, + const cairo_rectangle_int_t *src_rect, + int dst_width, + int dst_height, + cairo_rectangle_int_t *dst_rect); + #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index b7a3d6716..97aadcc9c 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -166,6 +166,22 @@ clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view) g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref); } +void +clutter_stage_view_transform_rect_to_onscreen (ClutterStageView *view, + const cairo_rectangle_int_t *src_rect, + int dst_width, + int dst_height, + cairo_rectangle_int_t *dst_rect) +{ + ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view); + + return view_class->transform_rect_to_onscreen (view, + src_rect, + dst_width, + dst_height, + dst_rect); +} + static void paint_transformed_framebuffer (ClutterStageView *view, CoglPipeline *pipeline, @@ -471,19 +487,6 @@ clutter_stage_view_take_redraw_clip (ClutterStageView *view) return g_steal_pointer (&priv->redraw_clip); } -void -clutter_stage_view_transform_to_onscreen (ClutterStageView *view, - gfloat *x, - gfloat *y) -{ - gfloat z = 0, w = 1; - CoglMatrix matrix; - - clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); - cogl_matrix_get_inverse (&matrix, &matrix); - cogl_matrix_transform_point (&matrix, x, y, &z, &w); -} - static void clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *view, CoglMatrix *matrix) diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h index 26bf10e79..eb0184e9a 100644 --- a/clutter/clutter/clutter-stage-view.h +++ b/clutter/clutter/clutter-stage-view.h @@ -43,6 +43,12 @@ struct _ClutterStageViewClass void (* get_offscreen_transformation_matrix) (ClutterStageView *view, CoglMatrix *matrix); + + void (* transform_rect_to_onscreen) (ClutterStageView *view, + const cairo_rectangle_int_t *src_rect, + int dst_width, + int dst_height, + cairo_rectangle_int_t *dst_rect); }; CLUTTER_EXPORT @@ -56,11 +62,6 @@ CoglFramebuffer *clutter_stage_view_get_onscreen (ClutterStageView *view); CLUTTER_EXPORT void clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view); -CLUTTER_EXPORT -void clutter_stage_view_transform_to_onscreen (ClutterStageView *view, - gfloat *x, - gfloat *y); - CLUTTER_EXPORT float clutter_stage_view_get_scale (ClutterStageView *view); diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index 4a7eee735..fa9d655d3 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -536,44 +536,25 @@ static cairo_region_t * transform_swap_region_to_onscreen (ClutterStageView *view, cairo_region_t *swap_region) { - CoglFramebuffer *framebuffer; - cairo_rectangle_int_t layout; - gint width, height; + CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view); int n_rects, i; cairo_rectangle_int_t *rects; cairo_region_t *transformed_region; + int width, height; - framebuffer = clutter_stage_view_get_onscreen (view); - clutter_stage_view_get_layout (view, &layout); - - width = cogl_framebuffer_get_width (framebuffer); - height = cogl_framebuffer_get_height (framebuffer); + width = cogl_framebuffer_get_width (onscreen); + height = cogl_framebuffer_get_height (onscreen); n_rects = cairo_region_num_rectangles (swap_region); rects = g_newa (cairo_rectangle_int_t, n_rects); for (i = 0; i < n_rects; i++) { - gfloat x1, y1, x2, y2; - cairo_region_get_rectangle (swap_region, i, &rects[i]); - - x1 = (float) rects[i].x / layout.width; - y1 = (float) rects[i].y / layout.height; - x2 = (float) (rects[i].x + rects[i].width) / layout.width; - y2 = (float) (rects[i].y + rects[i].height) / layout.height; - - clutter_stage_view_transform_to_onscreen (view, &x1, &y1); - clutter_stage_view_transform_to_onscreen (view, &x2, &y2); - - x1 = floor (x1 * width); - y1 = floor (height - (y1 * height)); - x2 = ceil (x2 * width); - y2 = ceil (height - (y2 * height)); - - rects[i].x = x1; - rects[i].y = y1; - rects[i].width = x2 - x1; - rects[i].height = y2 - y1; + clutter_stage_view_transform_rect_to_onscreen (view, + &rects[i], + width, + height, + &rects[i]); } transformed_region = cairo_region_create_rectangles (rects, n_rects); @@ -598,6 +579,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, ClutterStageViewCoglPrivate *view_priv = clutter_stage_view_cogl_get_instance_private (view_cogl); CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view); + CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view); cairo_rectangle_int_t view_rect; gboolean is_full_redraw; gboolean use_clipped_redraw; @@ -619,10 +601,10 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, fb_height = cogl_framebuffer_get_height (fb); can_blit_sub_buffer = - cogl_is_onscreen (fb) && + cogl_is_onscreen (onscreen) && cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION); - has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled (); + has_buffer_age = cogl_is_onscreen (onscreen) && is_buffer_age_enabled (); redraw_clip = clutter_stage_view_take_redraw_clip (view); if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)) @@ -636,7 +618,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, if (has_buffer_age) { - buffer_age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb)); + buffer_age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (onscreen)); if (!valid_buffer_age (view_cogl, buffer_age)) { CLUTTER_NOTE (CLIPPING, @@ -654,7 +636,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, !is_full_redraw && /* some drivers struggle to get going and produce some junk * frames when starting up... */ - cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3; + cogl_onscreen_get_frame_counter (COGL_ONSCREEN (onscreen)) > 3; if (use_clipped_redraw) { diff --git a/src/backends/meta-renderer-view.c b/src/backends/meta-renderer-view.c index ae771f2de..785b29cd7 100644 --- a/src/backends/meta-renderer-view.c +++ b/src/backends/meta-renderer-view.c @@ -34,6 +34,7 @@ #include "backends/meta-renderer.h" #include "clutter/clutter-mutter.h" +#include "compositor/region-utils.h" enum { @@ -117,6 +118,25 @@ meta_renderer_view_setup_offscreen_blit_pipeline (ClutterStageView *view, cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); } +static void +meta_renderer_view_transform_rect_to_onscreen (ClutterStageView *view, + const cairo_rectangle_int_t *src_rect, + int dst_width, + int dst_height, + cairo_rectangle_int_t *dst_rect) +{ + MetaRendererView *renderer_view = META_RENDERER_VIEW (view); + MetaMonitorTransform inverted_transform; + + inverted_transform = + meta_monitor_transform_invert (renderer_view->transform); + return meta_rectangle_transform (src_rect, + inverted_transform, + dst_width, + dst_height, + dst_rect); +} + static void meta_renderer_view_set_transform (MetaRendererView *view, MetaMonitorTransform transform) @@ -181,6 +201,8 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass) meta_renderer_view_setup_offscreen_blit_pipeline; view_class->get_offscreen_transformation_matrix = meta_renderer_view_get_offscreen_transformation_matrix; + view_class->transform_rect_to_onscreen = + meta_renderer_view_transform_rect_to_onscreen; object_class->get_property = meta_renderer_view_get_property; object_class->set_property = meta_renderer_view_set_property;