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

(cherry picked from commit 427b1038051e9b53a071d8c229b363b075bb1dc0)
This commit is contained in:
Adel Gadllah 2012-12-14 23:26:30 +01:00 committed by Robert Bragg
parent 9fb0cbd45d
commit 860fb00fdc
7 changed files with 110 additions and 1 deletions

View File

@ -69,6 +69,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, g)

View File

@ -188,6 +188,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,

View File

@ -307,6 +307,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

View File

@ -829,6 +829,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;

View File

@ -170,3 +170,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 ()

View File

@ -280,7 +280,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,
@ -1189,6 +1191,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,
@ -2165,6 +2191,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 =

View File

@ -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);