[clutter/wip/clip-with-swap-buffers: 4/4] experimental clipped redraws without extension



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]