[mutter] clutter/stage-view: Defer and accumulate redraw-clip on scanout
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] clutter/stage-view: Defer and accumulate redraw-clip on scanout
- Date: Tue, 2 Aug 2022 12:19:00 +0000 (UTC)
commit 550f09a5e7c24731eee6f232f84ec32af64dd5ca
Author: Robert Mader <robert mader posteo de>
Date: Sat Jun 25 22:14:41 2022 +0200
clutter/stage-view: Defer and accumulate redraw-clip on scanout
When taking the scanout path we still want to clear the
redraw-clip from the stage-view in order to ensure we skip
frames in `handle_frame_clock_frame()` if no new redraw-clip
was recorded.
This was not done previously as the accumulated redraw-clip was
needed for the next repaint, likely under the assumption that
scheduling a scanout repeatedly would be computationally cost-free.
This assumption does not hold in a VRR world.
In order to archive both, an accumulated redraw-clip for the next
paint and frame-skipping during scanout, introduce new API to defer
and accumulate redraw-clips until the next repaint.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2480>
clutter/clutter/clutter-stage-view-private.h | 6 +++
clutter/clutter/clutter-stage-view.c | 71 ++++++++++++++++++++++++----
src/backends/meta-stage-impl.c | 7 ++-
3 files changed, 73 insertions(+), 11 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
index 39d8601ea5..309dde4960 100644
--- a/clutter/clutter/clutter-stage-view-private.h
+++ b/clutter/clutter/clutter-stage-view-private.h
@@ -59,6 +59,12 @@ const cairo_region_t * clutter_stage_view_peek_redraw_clip (ClutterStageView *vi
CLUTTER_EXPORT
cairo_region_t * clutter_stage_view_take_redraw_clip (ClutterStageView *view);
+CLUTTER_EXPORT
+cairo_region_t * clutter_stage_view_take_accumulated_redraw_clip (ClutterStageView *view);
+
+CLUTTER_EXPORT
+void clutter_stage_view_accumulate_redraw_clip (ClutterStageView *view);
+
CLUTTER_EXPORT
CoglScanout * clutter_stage_view_take_scanout (ClutterStageView *view);
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index 2e47237f0a..22c7647996 100644
--- a/clutter/clutter/clutter-stage-view.c
+++ b/clutter/clutter/clutter-stage-view.c
@@ -78,6 +78,8 @@ typedef struct _ClutterStageViewPrivate
gboolean has_redraw_clip;
cairo_region_t *redraw_clip;
+ gboolean has_accumulated_redraw_clip;
+ cairo_region_t *accumulated_redraw_clip;
float refresh_rate;
int64_t vblank_duration_us;
@@ -920,6 +922,23 @@ clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
view_class->get_offscreen_transformation_matrix (view, matrix);
}
+static void
+maybe_mark_full_redraw (ClutterStageView *view,
+ cairo_region_t **region)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ if (cairo_region_num_rectangles (*region) == 1)
+ {
+ cairo_rectangle_int_t region_extents;
+
+ cairo_region_get_extents (*region, ®ion_extents);
+ if (clutter_util_rectangle_equal (&priv->layout, ®ion_extents))
+ g_clear_pointer (region, cairo_region_destroy);
+ }
+}
+
void
clutter_stage_view_add_redraw_clip (ClutterStageView *view,
const cairo_rectangle_int_t *clip)
@@ -948,15 +967,7 @@ clutter_stage_view_add_redraw_clip (ClutterStageView *view,
else
{
cairo_region_union_rectangle (priv->redraw_clip, clip);
-
- if (cairo_region_num_rectangles (priv->redraw_clip) == 1)
- {
- cairo_rectangle_int_t redraw_clip_extents;
-
- cairo_region_get_extents (priv->redraw_clip, &redraw_clip_extents);
- if (clutter_util_rectangle_equal (&priv->layout, &redraw_clip_extents))
- g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
- }
+ maybe_mark_full_redraw (view, &priv->redraw_clip);
}
priv->has_redraw_clip = TRUE;
@@ -1000,6 +1011,47 @@ clutter_stage_view_take_redraw_clip (ClutterStageView *view)
return g_steal_pointer (&priv->redraw_clip);
}
+cairo_region_t *
+clutter_stage_view_take_accumulated_redraw_clip (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ g_return_val_if_fail (priv->has_redraw_clip, NULL);
+
+ clutter_stage_view_accumulate_redraw_clip (view);
+
+ priv->has_accumulated_redraw_clip = FALSE;
+ return g_steal_pointer (&priv->accumulated_redraw_clip);
+}
+
+void
+clutter_stage_view_accumulate_redraw_clip (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ g_return_if_fail (priv->has_redraw_clip);
+
+ if (priv->redraw_clip && priv->accumulated_redraw_clip)
+ {
+ cairo_region_union (priv->accumulated_redraw_clip, priv->redraw_clip);
+ maybe_mark_full_redraw (view, &priv->accumulated_redraw_clip);
+ }
+ else if (priv->redraw_clip && !priv->has_accumulated_redraw_clip)
+ {
+ priv->accumulated_redraw_clip = g_steal_pointer (&priv->redraw_clip);
+ }
+ else
+ {
+ g_clear_pointer (&priv->accumulated_redraw_clip, cairo_region_destroy);
+ }
+
+ g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
+ priv->has_accumulated_redraw_clip = TRUE;
+ priv->has_redraw_clip = FALSE;
+}
+
static void
clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *view,
graphene_matrix_t *matrix)
@@ -1400,6 +1452,7 @@ clutter_stage_view_dispose (GObject *object)
g_clear_object (&priv->offscreen);
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
+ g_clear_pointer (&priv->accumulated_redraw_clip, cairo_region_destroy);
g_clear_pointer (&priv->frame_clock, clutter_frame_clock_destroy);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c
index c45aaf852e..d562603c33 100644
--- a/src/backends/meta-stage-impl.c
+++ b/src/backends/meta-stage-impl.c
@@ -473,7 +473,7 @@ meta_stage_impl_redraw_view_primary (MetaStageImpl *stage_impl,
COGL_IS_ONSCREEN (onscreen) &&
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
- redraw_clip = clutter_stage_view_take_redraw_clip (stage_view);
+ redraw_clip = clutter_stage_view_take_accumulated_redraw_clip (stage_view);
/* NB: a NULL redraw clip == full stage redraw */
if (!redraw_clip)
@@ -725,7 +725,10 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window,
scanout,
frame,
&error))
- return;
+ {
+ clutter_stage_view_accumulate_redraw_clip (stage_view);
+ return;
+ }
if (!g_error_matches (error,
COGL_SCANOUT_ERROR,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]