[cogl/wip/wayland: 8/8] onscreen: Adds buffer age api



commit fa36307cce3304e081139544ab0e5a8a411bc1f2
Author: Robert Bragg <robert linux intel com>
Date:   Mon Feb 13 14:37:27 2012 +0000

    onscreen: Adds buffer age api
    
    This adds a cogl_oncsreen_get_back_buffer_age() function that allows
    applications to query how old the back buffer contents are at the start
    of a new frame.
    
    The intention of this api is to help optimize applications that
    frequently only update small regions of the screen.  Applications can
    maintain a running record of the regions changed over the last three or
    so frames and at the start of each frame they can check the age of the
    back buffer contents and if its between 1 and 3 then they can use their
    history of the last three frames to calculate how to repair the contents
    of the re-used buffer instead of having to redraw everything.
    
    A nice advantage this approach has is that it doesn't require a blit to
    present the incremental updates to the front buffer, a flip can be used
    which is more efficient.

 cogl/cogl-framebuffer-private.h                 |    5 +++
 cogl/cogl-framebuffer.c                         |    2 +
 cogl/cogl-onscreen.c                            |   11 ++++++
 cogl/cogl-onscreen.h                            |   40 +++++++++++++++++++++++
 cogl/winsys/cogl-winsys-egl-feature-functions.h |    7 ++++
 cogl/winsys/cogl-winsys-egl-private.h           |    3 +-
 cogl/winsys/cogl-winsys-egl.c                   |   22 ++++++++++++
 7 files changed, 89 insertions(+), 1 deletions(-)
---
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index 137ba87..014bfc2 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -128,6 +128,11 @@ struct _CoglFramebuffer
 
   int                 samples_per_pixel;
 
+  /* How old the contents of the current back buffer are.
+   *  0 = Uninitialized / Unknown buffer contents
+   */
+  int                 back_buffer_age;
+
   /* We journal the textured rectangles we want to submit to OpenGL so
    * we have an oppertunity to batch them together into less draw
    * calls. */
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index ccefc49..b4b47e5 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -184,6 +184,8 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer,
    */
   framebuffer->clear_clip_dirty = TRUE;
 
+  framebuffer->back_buffer_age = 0;
+
   /* XXX: We have to maintain a central list of all framebuffers
    * because at times we need to be able to flush all known journals.
    *
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index f4f4c3f..a7eab40 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -140,6 +140,7 @@ cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer)
                                     COGL_BUFFER_BIT_COLOR |
                                     COGL_BUFFER_BIT_DEPTH |
                                     COGL_BUFFER_BIT_STENCIL);
+  framebuffer->back_buffer_age = 0;
 }
 
 void
@@ -166,6 +167,7 @@ cogl_framebuffer_swap_buffers_with_damage (CoglFramebuffer *framebuffer,
                                     COGL_BUFFER_BIT_COLOR |
                                     COGL_BUFFER_BIT_DEPTH |
                                     COGL_BUFFER_BIT_STENCIL);
+  framebuffer->back_buffer_age = 0;
 }
 
 void
@@ -194,6 +196,7 @@ cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
                                     COGL_BUFFER_BIT_COLOR |
                                     COGL_BUFFER_BIT_DEPTH |
                                     COGL_BUFFER_BIT_STENCIL);
+  framebuffer->back_buffer_age = 0;
 }
 
 #ifdef COGL_HAS_X11_SUPPORT
@@ -406,3 +409,11 @@ cogl_onscreen_start_frame (CoglOnscreen *onscreen)
   if (winsys->onscreen_start_frame)
     winsys->onscreen_start_frame (onscreen);
 }
+
+int
+cogl_onscreen_get_back_buffer_age (CoglOnscreen *onscreen)
+{
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+
+  return framebuffer->back_buffer_age;
+}
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index 7be963c..fdd7553 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -440,6 +440,46 @@ cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
 void
 cogl_onscreen_start_frame (CoglOnscreen *onscreen);
 
+/**
+ * cogl_onscreen_get_back_buffer_age:
+ * @onscreen: A #CoglOnscreen framebuffer
+ *
+ * Queries how old the contents of the current back buffer are. If the back
+ * buffer has been newly allocated or otherwise has undefined contents then the
+ * age returned will be 0.
+ *
+ * For example if the @onscreen framebuffer is double buffered then you will
+ * typically see a buffer age of 2. If @onscreen is single buffered then you
+ * will typically see an age of 1. Since there can be system events such as
+ * power management events or the driver might have more complex ways of
+ * managing buffers than a simple ring you can't assume anything about the age
+ * based on previous values.
+ *
+ * The intention of providing this information is to help optimize applications
+ * that often update small regions of the screen. These applications can keep a
+ * running list of the regions they modify for the last 3 frames and at the
+ * start of each frame they can query the age of the back buffer and so long as
+ * the age is between 1 and 3 they can use the history of modified regions to
+ * determine how to repair the re-used back buffer instead of having to redraw
+ * everything.
+ *
+ * This mechanism can really help to improve application efficiency first by
+ * helping minimize redundant re-drawing of unchanging parts of a scene but
+ * also the final result can be presented by flipping the back and front buffer
+ * instead of having to copy the modified region.
+ *
+ * <note>Applications using this api should typically use
+ * cogl_onscreen_start_frame() to explicitly start a new frame without
+ * rendering before querying the age. The back buffer age is undefined after
+ * calling cogl_swap_buffers() (or similar apis) until a new frame has been
+ * started.</note>
+ *
+ * Since: 1.10
+ * Stability: unstable
+ */
+int
+cogl_onscreen_get_back_buffer_age (CoglOnscreen *onscreen);
+
 G_END_DECLS
 
 #endif /* __COGL_ONSCREEN_H */
diff --git a/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/winsys/cogl-winsys-egl-feature-functions.h
index ecd87be..4807e18 100644
--- a/cogl/winsys/cogl-winsys-egl-feature-functions.h
+++ b/cogl/winsys/cogl-winsys-egl-feature-functions.h
@@ -125,3 +125,10 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglStartFrame,
                                EGLSurface surface))
 COGL_WINSYS_FEATURE_END ()
 #endif
+#ifdef EGL_EXT_buffer_age
+COGL_WINSYS_FEATURE_BEGIN (buffer_age,
+                           "EXT\0",
+                           "buffer_age\0",
+                           COGL_EGL_WINSYS_FEATURE_BUFFER_AGE)
+COGL_WINSYS_FEATURE_END ()
+#endif
diff --git a/cogl/winsys/cogl-winsys-egl-private.h b/cogl/winsys/cogl-winsys-egl-private.h
index 9f501ee..5e091bc 100644
--- a/cogl/winsys/cogl-winsys-egl-private.h
+++ b/cogl/winsys/cogl-winsys-egl-private.h
@@ -71,7 +71,8 @@ typedef enum _CoglEGLWinsysFeature
   COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_WAYLAND_BUFFER =1L<<2,
   COGL_EGL_WINSYS_FEATURE_SURFACELESS_OPENGL            =1L<<3,
   COGL_EGL_WINSYS_FEATURE_SURFACELESS_GLES1             =1L<<4,
-  COGL_EGL_WINSYS_FEATURE_SURFACELESS_GLES2             =1L<<5
+  COGL_EGL_WINSYS_FEATURE_SURFACELESS_GLES2             =1L<<5,
+  COGL_EGL_WINSYS_FEATURE_BUFFER_AGE                    =1L<<6
 } CoglEGLWinsysFeature;
 
 typedef struct _CoglRendererEGL
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index 99d0307..e5f2742 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -584,6 +584,9 @@ _cogl_winsys_onscreen_start_frame (CoglOnscreen *onscreen)
   CoglRendererEGL *egl_renderer = renderer->winsys;
   CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
   int width, height;
+#ifdef EGL_EXT_buffer_age
+  int age;
+#endif
 
   /* NB: cogl_onscreen_start_frame() is documented to be a NOP if
    * the COGL_FEATURE_ID_START_FRAME isn't available so we can't
@@ -607,6 +610,25 @@ _cogl_winsys_onscreen_start_frame (CoglOnscreen *onscreen)
     }
   else
     g_warning ("Error reported by eglQuerySurface");
+
+#ifdef EGL_EXT_buffer_age
+  if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_BUFFER_AGE)
+    {
+      if (eglQuerySurface (egl_renderer->edpy, egl_onscreen->egl_surface,
+                           EGL_BUFFER_AGE_EXT, &age) == EGL_TRUE)
+        {
+          fb->back_buffer_age = age;
+        }
+      else
+        {
+          g_warning ("Error reported by eglQuerySurface "
+                     "when querying EGL_BUFFER_AGE_EXT");
+          fb->back_buffer_age = 0;
+        }
+    }
+  else
+#endif
+    fb->back_buffer_age = 0;
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]