[Cogl] [PATCH] dispatch _COMPLETE instead of _PRESENTED frame events

Robert Bragg robert at sixbynine.org
Thu Jan 24 12:25:52 PST 2013


From: Robert Bragg <robert at linux.intel.com>

As discussed, this removes the _PRESENTED event and adds a _COMPLETE event
instead that signifies the end of a frame.

regards,
- Robert

-- >8 --

Instead of dispatching a _PRESENTED frame event when we receive a SwapComplete
event we instead send a _COMPLETE event that signifies that a frame has
been completed and that it's a good opportunity for applications to
collect CoglFrameInfo statistics, including the _presentation_time().
---
 cogl/cogl-context.h               |  7 +++----
 cogl/cogl-onscreen-private.h      |  5 ++++-
 cogl/cogl-onscreen.c              | 31 ++++++++++++++++++++++++++-----
 cogl/cogl-onscreen.h              | 27 ++++++++++++++++-----------
 cogl/winsys/cogl-winsys-egl-kms.c | 11 +++++++++--
 cogl/winsys/cogl-winsys-glx.c     | 12 ++++++++++--
 6 files changed, 68 insertions(+), 25 deletions(-)

diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h
index 840d76a..ae306d6 100644
--- a/cogl/cogl-context.h
+++ b/cogl/cogl-context.h
@@ -210,9 +210,8 @@ cogl_is_context (void *object);
  *     the depth buffer to a texture.
  * @COGL_FEATURE_ID_FRAME_SYNC: Whether %COGL_FRAME_EVENT_SYNC events
  *    will be sent to registered #CoglFrameCallback functions.
- * @COGL_FEATURE_ID_PRESENTATION_EVENTS: Whether
- *    %COGL_FRAME_EVENT_PRESENTED events will be sent to registered
- *    #CoglFrameCallback functions.
+ * @COGL_FEATURE_ID_PRESENTATION_TIME: Whether frame presentation
+ *    time stamps will be recorded in #CoglFrameInfo objects.
  *
  * All the capabilities that can vary between different GPUs supported
  * by Cogl. Applications that depend on any of these features should explicitly
@@ -243,7 +242,7 @@ typedef enum _CoglFeatureID
   COGL_FEATURE_ID_GLES2_CONTEXT,
   COGL_FEATURE_ID_DEPTH_TEXTURE,
   COGL_FEATURE_ID_FRAME_SYNC,
-  COGL_FEATURE_ID_PRESENTATION_EVENTS,
+  COGL_FEATURE_ID_PRESENTATION_TIME,
 
   /*< private >*/
   _COGL_N_FEATURE_IDS   /*< skip >*/
diff --git a/cogl/cogl-onscreen-private.h b/cogl/cogl-onscreen-private.h
index fd516c1..c712e72 100644
--- a/cogl/cogl-onscreen-private.h
+++ b/cogl/cogl-onscreen-private.h
@@ -97,7 +97,10 @@ _cogl_framebuffer_winsys_update_size (CoglFramebuffer *framebuffer,
                                       int width, int height);
 
 void
-_cogl_onscreen_notify_swap_buffers (CoglOnscreen *onscreen);
+_cogl_onscreen_notify_frame_sync (CoglOnscreen *onscreen, CoglFrameInfo *info);
+
+void
+_cogl_onscreen_notify_complete (CoglOnscreen *onscreen, CoglFrameInfo *info);
 
 void
 _cogl_onscreen_notify_resize (CoglOnscreen *onscreen);
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index 88118d0..64f8a40 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -343,7 +343,16 @@ shim_swap_buffers_callback (CoglOnscreen *onscreen,
 {
   SwapBufferCallbackState *state = user_data;
 
-  if (event == COGL_FRAME_EVENT_PRESENTED)
+  /* XXX: Note that technically it is a change in semantics for this
+   * interface to forward _SYNC events here and also makes the api
+   * name somewhat missleading.
+   *
+   * In practice though this interface is currently used by
+   * applications for throttling, not because they are strictly
+   * interested in knowing when a frame has been presented and so
+   * forwarding _SYNC events should serve them better.
+   */
+  if (event == COGL_FRAME_EVENT_SYNC)
     state->callback (COGL_FRAMEBUFFER (onscreen), state->user_data);
 }
 
@@ -432,21 +441,33 @@ cogl_onscreen_hide (CoglOnscreen *onscreen)
 }
 
 void
-_cogl_onscreen_notify_swap_buffers (CoglOnscreen *onscreen)
+_cogl_onscreen_notify_frame_sync (CoglOnscreen *onscreen, CoglFrameInfo *info)
 {
   CoglFrameClosure *entry, *tmp;
-  CoglFrameInfo *info = g_queue_pop_tail (&onscreen->pending_frame_infos);
 
   COGL_TAILQ_FOREACH_SAFE (entry,
                            &onscreen->frame_closures,
                            list_node,
                            tmp)
     {
-      entry->callback (onscreen, COGL_FRAME_EVENT_PRESENTED, info,
+      entry->callback (onscreen, COGL_FRAME_EVENT_SYNC, info,
                        entry->user_data);
     }
+}
+
+void
+_cogl_onscreen_notify_complete (CoglOnscreen *onscreen, CoglFrameInfo *info)
+{
+  CoglFrameClosure *entry, *tmp;
 
-  cogl_object_unref (info);
+  COGL_TAILQ_FOREACH_SAFE (entry,
+                           &onscreen->frame_closures,
+                           list_node,
+                           tmp)
+    {
+      entry->callback (onscreen, COGL_FRAME_EVENT_COMPLETE, info,
+                       entry->user_data);
+    }
 }
 
 void
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index 5f664f4..9ce5cd2 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -341,11 +341,13 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
  *                         new frame to be created. Only delivered
  *                         if the %COGL_FEATURE_ID_FRAME_SYNC
  *                         feature is supported.
- * @COGL_FRAME_EVENT_PRESENTED: Notifies that a frame has become
- *                              visible to the user. Only delivered
- *                              if the
- *                              %COGL_FEATURE_ID_PRESENTATION_EVENTS
- *                              feature is supported.
+ * @COGL_FRAME_EVENT_COMPLETE: Notifies that a frame has ended. This
+ *                             is a good time for applications to
+ *                             collect statistics about the frame
+ *                             since the #CoglFrameInfo should hold
+ *                             the most data at this point. No other
+ *                             events should be expected after a
+ *                             @COGL_FRAME_EVENT_COMPLETE event.
  *
  * Identifiers that are passed to #CoglFrameCallback functions
  * (registered using cogl_onscreen_add_frame_callback()) that
@@ -353,11 +355,14 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
  * means that new information will have been accumulated in the
  * frame's corresponding #CoglFrameInfo object.
  *
- * <note>Applications should not make assumptions about the relative
- * ordering of different types of frame events. A
- * %COGL_FRAME_EVENT_PRESENTED event can be received before a
- * %COGL_FRAME_EVENT_SYNC if the compositor is agressively throttling
- * your application.</note>
+ * The last event that will be sent for a frame will be a
+ * @COGL_FRAME_EVENT_COMPLETE event and so these are a good
+ * opportunity to collect statistics about a frame since the
+ * #CoglFrameInfo should hold the most data at this point.
+ *
+ * <note>A frame may not be completed before the next frame can start
+ * so applications should avoid needing to collect all statistics for
+ * a particular frame before they can start a new frame.</note>
  *
  * Since: 1.14
  * Stability: unstable
@@ -365,7 +370,7 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
 typedef enum _CoglFrameEvent
 {
   COGL_FRAME_EVENT_SYNC = 1,
-  COGL_FRAME_EVENT_PRESENTED
+  COGL_FRAME_EVENT_COMPLETE
 } CoglFrameEvent;
 
 /**
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index f3e5e67..1c185c6 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -753,9 +753,11 @@ _cogl_winsys_egl_context_init (CoglContext *context,
                                CoglError **error)
 {
   COGL_FLAGS_SET (context->features,
+                  COGL_FEATURE_ID_FRAME_SYNC, TRUE);
+  COGL_FLAGS_SET (context->features,
                   COGL_FEATURE_ID_SWAP_BUFFERS_EVENT, TRUE);
   COGL_FLAGS_SET (context->features,
-                  COGL_FEATURE_ID_PRESENTATION_EVENTS, TRUE);
+                  COGL_FEATURE_ID_PRESENTATION_TIME, TRUE);
   COGL_FLAGS_SET (context->winsys_features,
                   COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT,
                   TRUE);
@@ -896,8 +898,13 @@ flush_pending_swap_notify_cb (void *data,
 
       if (kms_onscreen->pending_swap_notify)
         {
-          _cogl_onscreen_notify_swap_buffers (onscreen);
+          CoglFrameInfo *info = g_queue_pop_tail (&onscreen->pending_frame_infos);
+
+          _cogl_onscreen_notify_frame_sync (onscreen, info);
+          _cogl_onscreen_notify_complete (onscreen, info);
           kms_onscreen->pending_swap_notify = FALSE;
+
+          cogl_object_unref (info);
         }
     }
 }
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 1a56bb9..9e096fb 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -684,10 +684,13 @@ update_winsys_features (CoglContext *context, CoglError **error)
   if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
     {
       COGL_FLAGS_SET (context->features,
+                      COGL_FEATURE_ID_FRAME_SYNC,
+                      TRUE);
+      COGL_FLAGS_SET (context->features,
                       COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
                       TRUE);
       COGL_FLAGS_SET (context->features,
-                      COGL_FEATURE_ID_PRESENTATION_EVENTS,
+                      COGL_FEATURE_ID_PRESENTATION_TIME,
                       TRUE);
     }
 
@@ -2424,8 +2427,13 @@ flush_pending_notifications_cb (void *data,
 
       if (glx_onscreen->pending_swap_notify)
         {
-          _cogl_onscreen_notify_swap_buffers (onscreen);
+          CoglFrameInfo *info = g_queue_pop_tail (&onscreen->pending_frame_infos);
+
+          _cogl_onscreen_notify_frame_sync (onscreen, info);
+          _cogl_onscreen_notify_complete (onscreen, info);
           glx_onscreen->pending_swap_notify = FALSE;
+
+          cogl_object_unref (info);
         }
 
       if (glx_onscreen->pending_resize_notify)
-- 
1.8.1.1



More information about the Cogl mailing list