[clutter/wip/clip-with-swap-buffers: 4/4] experimental clipped redraws without extension
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/wip/clip-with-swap-buffers: 4/4] experimental clipped redraws without extension
- Date: Fri, 1 Apr 2011 16:58:18 +0000 (UTC)
commit a9c667a34dfee4a4aeceda3357334a394a16023d
Author: Robert Bragg <robert linux intel com>
Date: Tue Mar 22 00:26:34 2011 +0000
experimental clipped redraws without extension
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.
clutter/glx/clutter-stage-glx.c | 87 +++++++++++++++++++++++++++++++--------
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 a2ae2da..66e7870 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 9baa0f3..37f219e 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;
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]