[cogl/wip/wayland: 7/8] onscreen: Adds cogl_onscreen_start_frame() api
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/wayland: 7/8] onscreen: Adds cogl_onscreen_start_frame() api
- Date: Fri, 17 Feb 2012 15:10:32 +0000 (UTC)
commit 043e40919477aef123eec9422a7c7da0124dc3e2
Author: Robert Bragg <robert linux intel com>
Date: Sun Feb 12 22:38:53 2012 +0000
onscreen: Adds cogl_onscreen_start_frame() api
This adds cogl_onscreen_start_frame() api to allow applications to
explicitly start a frame without rendering anything. This will ensure
that all ancillary buffers associated with the onscreen framebuffer have
been allocated and the framebuffer is prepared for rendering. This also
gives applications an opportunity to query properties of the framebuffer
that may be affected by starting a new frame that might also be
useful to know before anything is actually drawn; such as the width
and height of the framebuffer.
The plan is to follow up with another patch that lets applications query
the age of the back buffer contents which will allow applications to
efficiently perform incremental updates of reused buffers, and this
relies on us being able to start the next frame without rendering
anything.
cogl/cogl-onscreen.c | 17 ++++++
cogl/cogl-onscreen.h | 24 ++++++++
cogl/cogl.h | 7 +++
cogl/winsys/cogl-winsys-egl-feature-functions.h | 11 ++++-
cogl/winsys/cogl-winsys-egl.c | 67 +++++++++++++++++++++--
cogl/winsys/cogl-winsys-private.h | 3 +
6 files changed, 122 insertions(+), 7 deletions(-)
---
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index 49dcd80..f4f4c3f 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -389,3 +389,20 @@ _cogl_framebuffer_winsys_update_size (CoglFramebuffer *framebuffer,
framebuffer->context->current_draw_buffer_changes |=
COGL_FRAMEBUFFER_STATE_VIEWPORT;
}
+
+void
+cogl_onscreen_start_frame (CoglOnscreen *onscreen)
+{
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+ const CoglWinsysVtable *winsys;
+
+ if (!framebuffer->allocated)
+ {
+ if (!cogl_framebuffer_allocate (framebuffer, NULL))
+ return;
+ }
+
+ winsys = _cogl_framebuffer_get_winsys (framebuffer);
+ if (winsys->onscreen_start_frame)
+ winsys->onscreen_start_frame (onscreen);
+}
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index 528b92d..7be963c 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -416,6 +416,30 @@ void
cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
unsigned int id);
+/**
+ * cogl_onscreen_start_frame:
+ * @onscreen: A #CoglOnscreen framebuffer
+ *
+ * Explicitly starts the next frame without rendering anything. This will
+ * ensure that all ancillary buffers associated with the given @onscreen
+ * framebuffer are allocated ready for rendering.
+ *
+ * It can be useful to explicitly start a frame without rendering anything if
+ * you want to check the geometry of the buffers before you start drawing or
+ * check other properties of the framebuffer that might be affected by starting
+ * a new frame.
+ *
+ * You should check for the %COGL_FEATURE_ID_START_FRAME feature before using
+ * this api. If the feature is not currently available this function simply
+ * does nothing, but it won't cause warnings or abort so you may find it
+ * convenient sometimes to use this api without checking for the feature.
+ *
+ * Since: 1.10
+ * Stability: unstable
+ */
+void
+cogl_onscreen_start_frame (CoglOnscreen *onscreen);
+
G_END_DECLS
#endif /* __COGL_ONSCREEN_H */
diff --git a/cogl/cogl.h b/cogl/cogl.h
index 37853c9..f1f80e1 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -211,6 +211,12 @@ cogl_features_available (CoglFeatureFlags features);
* @COGL_FEATURE_ID_SWAP_BUFFERS_EVENT:
* Available if the window system supports reporting an event
* for swap buffer completions.
+ * @COGL_FEATURE_ID_START_FRAME: Whether cogl_onscreen_start_frame()
+ * can be used to explicitly start a frame without drawing
+ * anything. For example this allows applications to check the
+ * geometry of the buffers before starting to render and also
+ * check the age of the buffer contents so the contents can be
+ * updated incrementally.
*
* All the capabilities that can vary between different GPUs supported
* by Cogl. Applications that depend on any of these features should explicitly
@@ -238,6 +244,7 @@ typedef enum _CoglFeatureID
COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE,
COGL_FEATURE_ID_MIRRORED_REPEAT,
COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
+ COGL_FEATURE_ID_START_FRAME,
/*< private > */
_COGL_N_FEATURE_IDS
diff --git a/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/winsys/cogl-winsys-egl-feature-functions.h
index 84110b8..ecd87be 100644
--- a/cogl/winsys/cogl-winsys-egl-feature-functions.h
+++ b/cogl/winsys/cogl-winsys-egl-feature-functions.h
@@ -115,4 +115,13 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersWithDamage,
EGLint n_rects))
COGL_WINSYS_FEATURE_END ()
#endif
-
+#ifdef EGL_EXT_start_frame
+COGL_WINSYS_FEATURE_BEGIN (start_frame,
+ "EXT\0",
+ "start_frame\0",
+ 0)
+COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglStartFrame,
+ (EGLDisplay dpy,
+ EGLSurface surface))
+COGL_WINSYS_FEATURE_END ()
+#endif
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index bb4eadc..99d0307 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -418,6 +418,11 @@ _cogl_winsys_context_init (CoglContext *context, GError **error)
COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
}
+#ifdef EGL_EXT_start_frame
+ if (egl_renderer->pf_eglStartFrame)
+ COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_START_FRAME, TRUE);
+#endif
+
if (egl_renderer->platform_vtable->context_init &&
!egl_renderer->platform_vtable->context_init (context, error))
return FALSE;
@@ -553,6 +558,58 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
}
static void
+transient_onscreen_bind (CoglOnscreen *onscreen)
+{
+ CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
+ CoglContext *context = fb->context;
+ CoglContextEGL *egl_context = context->winsys;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+
+ if (egl_context->current_surface != egl_onscreen->egl_surface)
+ {
+ _cogl_winsys_onscreen_bind (onscreen);
+
+ /* Make sure that next time _cogl_framebuffer_flush_state() is
+ * called then we will re-bind the previous framebufer. */
+ context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
+ }
+}
+
+static void
+_cogl_winsys_onscreen_start_frame (CoglOnscreen *onscreen)
+{
+ CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
+ CoglContext *context = fb->context;
+ CoglRenderer *renderer = context->display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+ int width, height;
+
+ /* 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
+ * crash/abort in this case. */
+ if (!egl_renderer->pf_eglStartFrame)
+ return;
+
+ transient_onscreen_bind (onscreen);
+
+ if (egl_renderer->pf_eglStartFrame (egl_renderer->edpy,
+ egl_onscreen->egl_surface) == EGL_FALSE)
+ g_warning ("Error reported by eglStartFrameEXT");
+
+ if (eglQuerySurface (egl_renderer->edpy, egl_onscreen->egl_surface,
+ EGL_WIDTH, &width) == EGL_TRUE &&
+ eglQuerySurface (egl_renderer->edpy, egl_onscreen->egl_surface,
+ EGL_HEIGHT, &height) == EGL_TRUE)
+ {
+ if (fb->width != width || fb->height != height)
+ _cogl_framebuffer_winsys_update_size (fb, width, height);
+ }
+ else
+ g_warning ("Error reported by eglQuerySurface");
+}
+
+static void
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
const int *user_rectangles,
int n_rectangles)
@@ -580,9 +637,7 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
swap must be bound to the current context. It looks like Mesa
also validates that this is the case for eglSwapBuffersRegion so
we must bind here too */
- _cogl_framebuffer_flush_state (COGL_FRAMEBUFFER (onscreen),
- COGL_FRAMEBUFFER (onscreen),
- COGL_FRAMEBUFFER_STATE_BIND);
+ transient_onscreen_bind (onscreen);
if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy,
egl_onscreen->egl_surface,
@@ -606,9 +661,7 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
although it may change in future. Mesa explicitly checks for this
and just returns an error if this is not the case so we can't
just pretend this isn't in the spec. */
- _cogl_framebuffer_flush_state (COGL_FRAMEBUFFER (onscreen),
- COGL_FRAMEBUFFER (onscreen),
- COGL_FRAMEBUFFER_STATE_BIND);
+ transient_onscreen_bind (onscreen);
#ifdef EGL_EXT_swap_buffers_with_damage
if (egl_renderer->pf_eglSwapBuffersWithDamage)
@@ -675,6 +728,8 @@ static CoglWinsysVtable _cogl_winsys_vtable =
.onscreen_init = _cogl_winsys_onscreen_init,
.onscreen_deinit = _cogl_winsys_onscreen_deinit,
.onscreen_bind = _cogl_winsys_onscreen_bind,
+ .onscreen_start_frame =
+ _cogl_winsys_onscreen_start_frame,
.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
.onscreen_swap_buffers_with_damage =
_cogl_winsys_onscreen_swap_buffers_with_damage,
diff --git a/cogl/winsys/cogl-winsys-private.h b/cogl/winsys/cogl-winsys-private.h
index 0bbcc0a..9912db6 100644
--- a/cogl/winsys/cogl-winsys-private.h
+++ b/cogl/winsys/cogl-winsys-private.h
@@ -95,6 +95,9 @@ typedef struct _CoglWinsysVtable
(*onscreen_bind) (CoglOnscreen *onscreen);
void
+ (*onscreen_start_frame) (CoglOnscreen *onscreen);
+
+ void
(*onscreen_swap_buffers) (CoglOnscreen *onscreen);
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]