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>
This commit is contained in:
parent
34475e7e98
commit
550f09a5e7
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user