[cogl] cogl-onscreen: Add buffer_age support



commit 427b1038051e9b53a071d8c229b363b075bb1dc0
Author: Adel Gadllah <adel gadllah gmail com>
Date:   Fri Dec 14 23:26:30 2012 +0100

    cogl-onscreen: Add buffer_age support
    
    Add a new BUFFER_AGE winsys feature and a get_buffer_age method to
    cogl-onscreen that allows to query the value.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=669122
    
    Reviewed-by: Neil Roberts <neil linux intel com>
    Reviewed-by: Robert Bragg <robert linux intel com>
    
    Note: When landing the patch I made some gtk-doc updates and changed
    _get_buffer_age to return an age of 0 always if the age feature isn't
    support instead of using _COGL_RETURN_VAL_IF_FAIL. -- Robert Bragg

 cogl/cogl-glx-renderer-private.h                |    4 ++
 cogl/cogl-onscreen.c                            |   16 ++++++++
 cogl/cogl-onscreen.h                            |   48 +++++++++++++++++++++++
 cogl/cogl-types.h                               |    3 +
 cogl/winsys/cogl-winsys-glx-feature-functions.h |    8 ++++
 cogl/winsys/cogl-winsys-glx.c                   |   29 +++++++++++++-
 cogl/winsys/cogl-winsys-private.h               |    3 +
 7 files changed, 110 insertions(+), 1 deletions(-)
---
diff --git a/cogl/cogl-glx-renderer-private.h b/cogl/cogl-glx-renderer-private.h
index 1be4d98..20ca543 100644
--- a/cogl/cogl-glx-renderer-private.h
+++ b/cogl/cogl-glx-renderer-private.h
@@ -67,6 +67,10 @@ typedef struct _CoglGLXRenderer
   void *
   (* glXGetProcAddress) (const GLubyte *procName);
 
+  int
+  (* glXQueryDrawable) (Display *dpy, GLXDrawable drawable,
+                        int attribute, unsigned int *value);
+
   /* Function pointers for GLX specific extensions */
 #define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
 
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index 9ae985c..147ac67 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -155,6 +155,22 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
                                     COGL_BUFFER_BIT_STENCIL);
 }
 
+int
+cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen)
+{
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  const CoglWinsysVtable *winsys;
+
+  _COGL_RETURN_VAL_IF_FAIL  (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN, 0);
+
+  winsys = _cogl_framebuffer_get_winsys (framebuffer);
+
+  if (!winsys->onscreen_get_buffer_age)
+    return 0;
+
+  return winsys->onscreen_get_buffer_age (onscreen);
+}
+
 #ifdef COGL_HAS_X11_SUPPORT
 void
 cogl_x11_onscreen_set_foreign_window_xid (CoglOnscreen *onscreen,
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index 3a93068..e7d7e97 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -330,6 +330,54 @@ cogl_onscreen_hide (CoglOnscreen *onscreen);
 void
 cogl_onscreen_swap_buffers (CoglOnscreen *onscreen);
 
+
+/**
+ * cogl_onscreen_get_buffer_age:
+ * @onscreen: A #CoglOnscreen framebuffer
+ *
+ * Gets the current age of the buffer contents.
+ *
+ * This function allows applications to query the age of the current
+ * back buffer contents for a #CoglOnscreen as the number of frames
+ * elapsed since the contents were most recently defined.
+ *
+ * These age values exposes enough information to applications about
+ * how Cogl internally manages back buffers to allow applications to
+ * re-use the contents of old frames and minimize how much must be
+ * redrawn for the next frame.
+ *
+ * The back buffer contents can either be reported as invalid (has an
+ * age of 0) or it may be reported to be the same contents as from n
+ * frames prior to the current frame.
+ *
+ * The queried value remains valid until the next buffer swap.
+ *
+ * <note>One caveat is that under X11 the buffer age does not reflect
+ * changes to buffer contents caused by the window systems. X11
+ * applications must track Expose events to determine what buffer
+ * regions need to additionally be repaired each frame.</note>
+ *
+ * The recommended way to take advantage of this buffer age api is to
+ * build up a circular buffer of length 3 for tracking damage regions
+ * over the last 3 frames and when starting a new frame look at the
+ * age of the buffer and combine the damage regions for the current
+ * frame with the damage regions of previous @age frames so you know
+ * everything that must be redrawn to update the old contents for the
+ * new frame.
+ *
+ * <note>If the system doesn't not support being able to track the age
+ * of back buffers then this function will always return 0 which
+ * implies that the contents are undefined.</note>
+ *
+ * Return value: The age of the buffer contents or 0 when the buffer
+ *               contents are undefined.
+ *
+ * Since: 1.14
+ * Stability: stable
+ */
+int
+cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen);
+
 /**
  * cogl_onscreen_swap_region:
  * @onscreen: A #CoglOnscreen framebuffer
diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h
index 7cc26fa..01ad4c9 100644
--- a/cogl/cogl-types.h
+++ b/cogl/cogl-types.h
@@ -655,6 +655,9 @@ typedef enum _CoglWinsysFeature
    * only needs to be throttled to the framerate */
   COGL_WINSYS_FEATURE_SWAP_REGION_SYNCHRONIZED,
 
+  /* Avaiable if the age of the back buffer can be queried */
+  COGL_WINSYS_FEATURE_BUFFER_AGE,
+
   COGL_WINSYS_FEATURE_N_FEATURES
 } CoglWinsysFeature;
 
diff --git a/cogl/winsys/cogl-winsys-glx-feature-functions.h b/cogl/winsys/cogl-winsys-glx-feature-functions.h
index a265757..ce3bd06 100644
--- a/cogl/winsys/cogl-winsys-glx-feature-functions.h
+++ b/cogl/winsys/cogl-winsys-glx-feature-functions.h
@@ -162,3 +162,11 @@ COGL_WINSYS_FEATURE_FUNCTION (GLXContext, glXCreateContextAttribs,
                                Bool direct,
                                const int *attrib_list))
 COGL_WINSYS_FEATURE_END ()
+
+COGL_WINSYS_FEATURE_BEGIN (255, 255,
+                           buffer_age,
+                           "EXT\0",
+                           "buffer_age\0",
+                           0,
+                           COGL_WINSYS_FEATURE_BUFFER_AGE)
+COGL_WINSYS_FEATURE_END ()
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 3a0abba..cef6b39 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -277,7 +277,9 @@ resolve_core_glx_functions (CoglRenderer *renderer,
       (!g_module_symbol (glx_renderer->libgl_module, "glXGetProcAddress",
                          (void **) &glx_renderer->glXGetProcAddress) &&
        !g_module_symbol (glx_renderer->libgl_module, "glXGetProcAddressARB",
-                         (void **) &glx_renderer->glXGetProcAddress)))
+                         (void **) &glx_renderer->glXGetProcAddress)) ||
+       !g_module_symbol (glx_renderer->libgl_module, "glXQueryDrawable",
+                         (void **) &glx_renderer->glXQueryDrawable))
     {
       _cogl_set_error (error, COGL_WINSYS_ERROR,
                    COGL_WINSYS_ERROR_INIT,
@@ -1181,6 +1183,30 @@ _cogl_winsys_get_vsync_counter (CoglContext *ctx)
   return video_sync_count;
 }
 
+#ifndef GLX_BACK_BUFFER_AGE_EXT
+#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
+#endif
+
+static int
+_cogl_winsys_onscreen_get_buffer_age (CoglOnscreen *onscreen)
+{
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  CoglContext *context = framebuffer->context;
+  CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (context->display->renderer);
+  CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
+  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+  CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+  GLXDrawable drawable = glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
+  unsigned int age;
+
+  if (!_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE))
+    return 0;
+
+  glx_renderer->glXQueryDrawable (xlib_renderer->xdpy, drawable, GLX_BACK_BUFFER_AGE_EXT, &age);
+
+  return age;
+}
+
 static void
 _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
                                    const int *user_rectangles,
@@ -2156,6 +2182,7 @@ static CoglWinsysVtable _cogl_winsys_vtable =
     .onscreen_bind = _cogl_winsys_onscreen_bind,
     .onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
     .onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
+    .onscreen_get_buffer_age = _cogl_winsys_onscreen_get_buffer_age,
     .onscreen_update_swap_throttled =
       _cogl_winsys_onscreen_update_swap_throttled,
     .onscreen_x11_get_window_xid =
diff --git a/cogl/winsys/cogl-winsys-private.h b/cogl/winsys/cogl-winsys-private.h
index 2ccf20c..27cf886 100644
--- a/cogl/winsys/cogl-winsys-private.h
+++ b/cogl/winsys/cogl-winsys-private.h
@@ -127,6 +127,9 @@ typedef struct _CoglWinsysVtable
   void
   (*onscreen_set_resizable) (CoglOnscreen *onscreen, CoglBool resizable);
 
+  int
+  (*onscreen_get_buffer_age) (CoglOnscreen *onscreen);
+
 #ifdef COGL_HAS_EGL_SUPPORT
   EGLDisplay
   (*context_egl_get_egl_display) (CoglContext *context);



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