diff options
-rw-r--r-- | clutter/glx/clutter-stage-glx.c | 87 | ||||
-rw-r--r-- | clutter/glx/clutter-stage-glx.h | 6 |
2 files changed, 75 insertions, 18 deletions
diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index a2ae2dabe..66e78707f 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -47,6 +47,7 @@ #include <sys/ioctl.h> #include <fcntl.h> #include <errno.h> +#include <stdlib.h> #ifdef HAVE_DRM #include <drm.h> @@ -108,6 +109,11 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window) if (!_clutter_stage_x11_create_window (stage_x11)) return FALSE; + if (getenv ("CLUTTER_SWAP_CHAIN_LENGTH")) + stage_glx->max_old_redraw_clips = + strtoul (getenv ("CLUTTER_SWAP_CHAIN_LENGTH"), NULL, 10) - 1; + stage_glx->n_old_redraw_clips = 0; + backend_x11 = stage_x11->backend; backend_glx = CLUTTER_BACKEND_GLX (backend_x11); @@ -371,7 +377,10 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window) GLXDrawable drawable; unsigned int video_sync_count; gboolean may_use_clipped_redraw; + gboolean have_final_clip; gboolean use_clipped_redraw; + ClutterGeometry final_clip; + int i; CLUTTER_STATIC_TIMER (painting_timer, "Redrawing", /* parent */ @@ -400,7 +409,8 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window) CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer); - if (G_LIKELY (backend_glx->can_blit_sub_buffer) && + if ((G_LIKELY (backend_glx->can_blit_sub_buffer) || + stage_glx->max_old_redraw_clips) && /* 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 @@ -414,9 +424,49 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window) may_use_clipped_redraw = TRUE; } else - may_use_clipped_redraw = FALSE; + { + stage_glx->n_old_redraw_clips = 0; + may_use_clipped_redraw = FALSE; + } + + if (may_use_clipped_redraw) + { + if (stage_glx->max_old_redraw_clips) + { + /* shift old redraw clips along and record the latest... */ + for (i = 0; i < stage_glx->max_old_redraw_clips - 1; i++) + stage_glx->old_redraw_clips[i] = stage_glx->old_redraw_clips[i + 1]; + stage_glx->old_redraw_clips[stage_glx->max_old_redraw_clips - 1] = + stage_glx->bounding_redraw_clip; + + /* Only if the history of old redraw clips is full then we + * can perform a clipped redraw... */ + if (stage_glx->n_old_redraw_clips == stage_glx->max_old_redraw_clips) + { + final_clip = stage_glx->old_redraw_clips[0]; + for (i = 1; i < stage_glx->max_old_redraw_clips; i++) + clutter_geometry_union (&stage_glx->old_redraw_clips[i], + &final_clip, + &final_clip); + + have_final_clip = TRUE; + } + else + { + stage_glx->n_old_redraw_clips++; + have_final_clip = FALSE; + } + } + else + { + final_clip = stage_glx->bounding_redraw_clip; + have_final_clip = TRUE; + } + } + else + have_final_clip = FALSE; - if (may_use_clipped_redraw && + if (have_final_clip && G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS))) use_clipped_redraw = TRUE; @@ -425,31 +475,31 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window) if (use_clipped_redraw) { - CLUTTER_NOTE (CLIPPING, + CLUTTER_NOTE (BACKEND, "Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n", - stage_glx->bounding_redraw_clip.x, - stage_glx->bounding_redraw_clip.y, - stage_glx->bounding_redraw_clip.width, - stage_glx->bounding_redraw_clip.height); - cogl_clip_push_window_rectangle (stage_glx->bounding_redraw_clip.x, - stage_glx->bounding_redraw_clip.y, - stage_glx->bounding_redraw_clip.width, - stage_glx->bounding_redraw_clip.height); - _clutter_stage_do_paint (stage_x11->wrapper, - &stage_glx->bounding_redraw_clip); + final_clip.x, + final_clip.y, + final_clip.width, + final_clip.height); + + cogl_clip_push_window_rectangle (final_clip.x, + final_clip.y, + final_clip.width, + final_clip.height); + _clutter_stage_do_paint (stage_x11->wrapper, &final_clip); cogl_clip_pop (); } else { - CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n"); + CLUTTER_NOTE (BACKEND, "Unclipped stage paint\n"); _clutter_stage_do_paint (stage_x11->wrapper, NULL); } - if (may_use_clipped_redraw && + if (have_final_clip && G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS))) { static CoglMaterial *outline = NULL; - ClutterGeometry *clip = &stage_glx->bounding_redraw_clip; + ClutterGeometry *clip = &final_clip; ClutterActor *actor = CLUTTER_ACTOR (stage_x11->wrapper); CoglHandle vbo; float x_1 = clip->x; @@ -510,7 +560,8 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window) backend_glx->get_video_sync (&video_sync_count); /* push on the screen */ - if (use_clipped_redraw) + if (use_clipped_redraw && + stage_glx->max_old_redraw_clips == 0) { ClutterGeometry *clip = &stage_glx->bounding_redraw_clip; ClutterGeometry copy_area; diff --git a/clutter/glx/clutter-stage-glx.h b/clutter/glx/clutter-stage-glx.h index 9baa0f3d4..37f219ec8 100644 --- a/clutter/glx/clutter-stage-glx.h +++ b/clutter/glx/clutter-stage-glx.h @@ -44,6 +44,8 @@ G_BEGIN_DECLS typedef struct _ClutterStageGLX ClutterStageGLX; typedef struct _ClutterStageGLXClass ClutterStageGLXClass; +#define CLUTTER_STAGE_GLX_MAX_SWAP_CHAIN_LENGTH 3 + struct _ClutterStageGLX { ClutterStageX11 parent_instance; @@ -61,6 +63,10 @@ struct _ClutterStageGLX ClutterGeometry bounding_redraw_clip; + ClutterGeometry old_redraw_clips[CLUTTER_STAGE_GLX_MAX_SWAP_CHAIN_LENGTH - 1]; + int n_old_redraw_clips; + int max_old_redraw_clips; + guint initialized_redraw_clip : 1; }; |