summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2011-03-22 00:26:34 +0000
committerRobert Bragg <robert@linux.intel.com>2011-04-01 17:26:29 +0100
commita9c667a34dfee4a4aeceda3357334a394a16023d (patch)
tree3fe6a525449caa363e3ea358b0293a950e35b7e4
parent5c548ad9bd95bcec0c43bfe6c313b8f391ab2abd (diff)
downloadclutter-a9c667a34dfee4a4aeceda3357334a394a16023d.tar.gz
experimental clipped redraws without extensionwip/clip-with-swap-buffers
This implements an experimental approach to supporting clipped redraws without the aid of an extension. Instead it depends on making an assumption about the number of back buffers provided by the driver. To tell Clutter about the number of back buffers set CLUTTER_SWAP_CHAIN_LENGTH=3 for example in your environment before running a Clutter app. Note: This is unlikely to be big win if your driver doesn't actually support flipping back buffers and instead uses a blit to present. Compared to the blit based clipped redraw path we have when using GLX one significant issue is that the whole window will effectively be damaged when using glXSwapBuffers which means the whole window could end up being blitted if the window isn't fullscreen. Even when compositing, because we don't have a way to report a limited damage region the compositor will be told that the whole window has been damage.
-rw-r--r--clutter/glx/clutter-stage-glx.c87
-rw-r--r--clutter/glx/clutter-stage-glx.h6
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;
};