summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2012-02-13 14:37:27 +0000
committerRobert Bragg <robert@linux.intel.com>2012-03-09 17:35:31 +0000
commit9e692a8a1b6e61822eadeaa3458b04f69bff9779 (patch)
treeaf9ae84de2c10cfaf53afbe6626c7687aabd11db
parent9c59291b9463a6d705eb96ab6df61133fa324400 (diff)
downloadcogl-wip/wayland.tar.gz
onscreen: Adds buffer age apiwip/wayland
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.
-rw-r--r--cogl/cogl-framebuffer-private.h5
-rw-r--r--cogl/cogl-framebuffer.c2
-rw-r--r--cogl/cogl-onscreen.c11
-rw-r--r--cogl/cogl-onscreen.h40
-rw-r--r--cogl/winsys/cogl-winsys-egl-feature-functions.h7
-rw-r--r--cogl/winsys/cogl-winsys-egl-private.h3
-rw-r--r--cogl/winsys/cogl-winsys-egl.c22
7 files changed, 89 insertions, 1 deletions
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index 0081a2f9..f2cedf9a 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -129,6 +129,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 f18abf1d..da764eb9 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -194,6 +194,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 7bbe5291..39a2ad04 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -142,6 +142,7 @@ cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
COGL_BUFFER_BIT_COLOR |
COGL_BUFFER_BIT_DEPTH |
COGL_BUFFER_BIT_STENCIL);
+ framebuffer->back_buffer_age = 0;
}
void
@@ -167,6 +168,7 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
COGL_BUFFER_BIT_COLOR |
COGL_BUFFER_BIT_DEPTH |
COGL_BUFFER_BIT_STENCIL);
+ framebuffer->back_buffer_age = 0;
}
void
@@ -196,6 +198,7 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
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 554f379e..959dbd26 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -461,6 +461,46 @@ cogl_is_onscreen (void *object);
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 ecd87bef..4807e18e 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 9f501ee8..5e091bc2 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 0dc8dc31..21f807e7 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -582,6 +582,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
@@ -605,6 +608,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