[cogl/wip/wayland: 8/9] onscreen: Adds cogl_onscreen_start_frame() api



commit d874707dfbfabb78433bf84747bda0a0ec22a737
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-context.h                             |    7 +++
 cogl/cogl-onscreen.c                            |   17 ++++++
 cogl/cogl-onscreen.h                            |   24 ++++++++
 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-context.h b/cogl/cogl-context.h
index 86c746b..19d472b 100644
--- a/cogl/cogl-context.h
+++ b/cogl/cogl-context.h
@@ -205,6 +205,12 @@ cogl_is_context (void *object);
  * @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
@@ -232,6 +238,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/cogl-onscreen.c b/cogl/cogl-onscreen.c
index c846855..75ec85c 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 273b05a..798239a 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -423,6 +423,30 @@ void
 cogl_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
                                             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/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 f46cda4..0dc8dc3 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -416,6 +416,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;
@@ -551,6 +556,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)
@@ -578,9 +635,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,
@@ -604,9 +659,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)
@@ -673,6 +726,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 90a63f8..b866ec7 100644
--- a/cogl/winsys/cogl-winsys-private.h
+++ b/cogl/winsys/cogl-winsys-private.h
@@ -97,6 +97,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]