From 5f181f7265fe043025583e3a7747e9ce55bd65ba Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 23 Nov 2010 16:05:44 +0000 Subject: [PATCH] stage-window: tweak has_redraw_clips semantics This tweaks the semantics of the has_redraw_clips vfunc so we can assume that at the start of a new frame there is an implied, initial, redraw_clip that clips everything (i.e. nothing would be redrawn) so in that case we would expect the has_redraw_clips vfunc to return True at the start of a new frame for backends that support clipping. Previously there was an ambiguity when this function returned False since it could either mean a full screen redraw had been queued or it could mean that the clip state wasn't yet initialized for that frame. This would result in _clutter_stage_has_full_redraw_queued() returning True at the start of a new frame even before any actors have been updated, which in turn meant we would incorrectly ignore queue_redraw requests for actors, believing them to be redundant. --- clutter/clutter-stage-window.c | 16 ++++++++++++++++ clutter/egl/clutter-stage-egl.c | 19 +++++++++++++------ clutter/glx/clutter-stage-glx.c | 21 ++++++++++++++------- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/clutter/clutter-stage-window.c b/clutter/clutter-stage-window.c index c704854ea..ce88a5d34 100644 --- a/clutter/clutter-stage-window.c +++ b/clutter/clutter-stage-window.c @@ -124,6 +124,14 @@ _clutter_stage_window_add_redraw_clip (ClutterStageWindow *window, iface->add_redraw_clip (window, stage_clip); } +/* Determines if the backend will clip the rendering of the next + * frame. + * + * Note: at the start of each new frame there is an implied clip that + * clips everything (i.e. nothing would be drawn) so this function + * will return True at the start of a new frame if the backend + * supports clipped redraws. + */ gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window) { @@ -138,6 +146,14 @@ _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window) return FALSE; } +/* Determines if the backend will discard any additional redraw clips + * and instead promote them to a full stage redraw. + * + * The ideas is that backend may have some heuristics that cause it to + * give up tracking redraw clips so this can be used to avoid the cost + * of calculating a redraw clip when we know it's going to be ignored + * anyway. + */ gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window) { diff --git a/clutter/egl/clutter-stage-egl.c b/clutter/egl/clutter-stage-egl.c index 16c561d98..859a87740 100644 --- a/clutter/egl/clutter-stage-egl.c +++ b/clutter/egl/clutter-stage-egl.c @@ -278,9 +278,16 @@ clutter_stage_egl_has_redraw_clips (ClutterStageWindow *stage_window) { ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window); - /* NB: a degenerate clip means a full stage redraw is required */ - if (stage_egl->initialized_redraw_clip && - stage_egl->bounding_redraw_clip.width != 0) + /* NB: at the start of each new frame there is an implied clip that + * clips everything (i.e. nothing would be drawn) so we need to make + * sure we return True in the un-initialized case here. + * + * NB: a clip width of 0 means a full stage redraw has been queued + * so we effectively don't have any redraw clips in that case. + */ + if (!stage_egl->initialized_redraw_clip || + (stage_egl->initialized_redraw_clip && + stage_egl->bounding_redraw_clip.width != 0)) return TRUE; else return FALSE; @@ -291,7 +298,7 @@ clutter_stage_egl_ignoring_redraw_clips (ClutterStageWindow *stage_window) { ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window); - /* NB: a degenerate clip means a full stage redraw is required */ + /* NB: a clip width of 0 means a full stage redraw is required */ if (stage_egl->initialized_redraw_clip && stage_egl->bounding_redraw_clip.width == 0) return TRUE; @@ -324,7 +331,7 @@ clutter_stage_egl_add_redraw_clip (ClutterStageWindow *stage_window, return; /* A NULL stage clip means a full stage redraw has been queued and - * we keep track of this by setting a degenerate + * we keep track of this by setting a zero width * stage_egl->bounding_redraw_clip */ if (stage_clip == NULL) { @@ -444,7 +451,7 @@ _clutter_stage_egl_redraw (ClutterStageEGL *stage_egl, #endif if (G_LIKELY (backend_egl->can_blit_sub_buffer) && - /* NB: a degenerate redraw clip width == full stage redraw */ + /* NB: a zero width clip == full stage redraw */ stage_egl->bounding_redraw_clip.width != 0 && /* some drivers struggle to get going and produce some junk * frames when starting up... */ diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index 42b29fe81..ae3c8cda1 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -291,9 +291,16 @@ clutter_stage_glx_has_redraw_clips (ClutterStageWindow *stage_window) { ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); - /* NB: a degenerate clip means a full stage redraw is required */ - if (stage_glx->initialized_redraw_clip && - stage_glx->bounding_redraw_clip.width != 0) + /* NB: at the start of each new frame there is an implied clip that + * clips everything (i.e. nothing would be drawn) so we need to make + * sure we return True in the un-initialized case here. + * + * NB: a clip width of 0 means a full stage redraw has been queued + * so we effectively don't have any redraw clips in that case. + */ + if (!stage_glx->initialized_redraw_clip || + (stage_glx->initialized_redraw_clip && + stage_glx->bounding_redraw_clip.width != 0)) return TRUE; else return FALSE; @@ -304,7 +311,7 @@ clutter_stage_glx_ignoring_redraw_clips (ClutterStageWindow *stage_window) { ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); - /* NB: a degenerate clip means a full stage redraw is required */ + /* NB: a clip width of 0 means a full stage redraw is required */ if (stage_glx->initialized_redraw_clip && stage_glx->bounding_redraw_clip.width == 0) return TRUE; @@ -369,7 +376,7 @@ clutter_stage_glx_add_redraw_clip (ClutterStageWindow *stage_window, return; /* A NULL stage clip means a full stage redraw has been queued and - * we keep track of this by setting a degenerate + * we keep track of this by setting a zero width * stage_glx->bounding_redraw_clip */ if (stage_clip == NULL) { @@ -408,7 +415,7 @@ clutter_stage_glx_add_redraw_clip (ClutterStageWindow *stage_window, if (redraw_area > (stage_area * 0.7f)) { g_print ("DEBUG: clipped redraw too big, forcing full redraw\n"); - /* Set a degenerate clip to force a full redraw */ + /* Set a zero width clip to force a full redraw */ stage_glx->bounding_redraw_clip.width = 0; } #endif @@ -519,7 +526,7 @@ _clutter_stage_glx_redraw (ClutterStageGLX *stage_glx, CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer); if (G_LIKELY (backend_glx->can_blit_sub_buffer) && - /* NB: a degenerate redraw clip width == full stage redraw */ + /* NB: a zero width redraw clip == full stage redraw */ stage_glx->bounding_redraw_clip.width != 0 && /* some drivers struggle to get going and produce some junk * frames when starting up... */