[cogl] cogl-onscreen: Add buffer_age support
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl] cogl-onscreen: Add buffer_age support
- Date: Wed, 23 Jan 2013 17:57:27 +0000 (UTC)
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]