[cogl/wip/rib/frame-synchronization: 26/32] Add cogl_onscreen_add_swap_complete_callback() api



commit a312d4f453a839dfffb03f764db1c65dc7e0a675
Author: Robert Bragg <robert linux intel com>
Date:   Tue Dec 4 16:29:51 2012 +0000

    Add cogl_onscreen_add_swap_complete_callback() api
    
    This adds cogl_onscreen_add/remove_swap_complete_callback() functions to
    replace the cogl_onscreen_add/remove_swap_buffers_callback() functions
    where the new api passes a CoglSwapInfo pointer to the callback which
    provides meta data about the completed swap such as timing information.
    
    This patch also removes the following public functions:
    cogl_onscreen_begin_frame
    cogl_onscreen_get_frame_history_start
    cogl_onscreen_get_swap_info
    cogl_onscreen_add_swap_info_callback
    cogl_onscreen_remove_swap_info_callback
    cogl_swap_info_get_complete
    cogl_swap_info_get_frame_time
    cogl_swap_info_get_refresh_interval
    
    and adds cogl_swap_info_get_output
    
    TODO: squash this back into owen's patch

 cogl/cogl-context-private.h   |    2 +
 cogl/cogl-onscreen-private.h  |   36 ++------
 cogl/cogl-onscreen.c          |  214 ++++++++++++++++++-----------------------
 cogl/cogl-onscreen.h          |  169 +++++++++++++--------------------
 cogl/cogl-swap-info-private.h |    5 +-
 cogl/cogl-swap-info.c         |   18 +---
 cogl/cogl-swap-info.h         |   44 ++-------
 cogl/winsys/cogl-winsys-glx.c |   81 ++++------------
 8 files changed, 198 insertions(+), 371 deletions(-)
---
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 85d107c..da114ba 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -184,6 +184,8 @@ struct _CoglContext
   gboolean have_last_offscreen_allocate_flags;
   CoglOffscreenAllocateFlags last_offscreen_allocate_flags;
 
+  int next_swap_complete_callback_id;
+
   CoglGLES2Context *current_gles2_context;
   GQueue gles2_context_stack;
 
diff --git a/cogl/cogl-onscreen-private.h b/cogl/cogl-onscreen-private.h
index 08fd5ec..a90ac43 100644
--- a/cogl/cogl-onscreen-private.h
+++ b/cogl/cogl-onscreen-private.h
@@ -33,17 +33,15 @@
 #include <windows.h>
 #endif
 
-#define COGL_ONSCREEN_MAX_SWAP_INFOS 16
+typedef struct _CoglSwapCompleteNotifyEntry CoglSwapCompleteNotifyEntry;
 
-typedef struct _CoglSwapBuffersNotifyEntry CoglSwapBuffersNotifyEntry;
+COGL_TAILQ_HEAD (CoglSwapCompleteNotifyList, CoglSwapCompleteNotifyEntry);
 
-COGL_TAILQ_HEAD (CoglSwapBuffersNotifyList, CoglSwapBuffersNotifyEntry);
-
-struct _CoglSwapBuffersNotifyEntry
+struct _CoglSwapCompleteNotifyEntry
 {
-  COGL_TAILQ_ENTRY (CoglSwapBuffersNotifyEntry) list_node;
+  COGL_TAILQ_ENTRY (CoglSwapCompleteNotifyEntry) list_node;
 
-  CoglSwapBuffersNotify callback;
+  CoglSwapCompleteNotify callback;
   void *user_data;
   unsigned int id;
 };
@@ -61,19 +59,6 @@ struct _CoglResizeNotifyEntry
   unsigned int id;
 };
 
-typedef struct _CoglSwapInfoCallbackEntry CoglSwapInfoCallbackEntry;
-
-COGL_TAILQ_HEAD (CoglSwapInfoCallbackList, CoglSwapInfoCallbackEntry);
-
-struct _CoglSwapInfoCallbackEntry
-{
-  COGL_TAILQ_ENTRY (CoglSwapInfoCallbackEntry) list_node;
-
-  CoglSwapInfoCallback callback;
-  void *user_data;
-  unsigned int id;
-};
-
 struct _CoglOnscreen
 {
   CoglFramebuffer  _parent;
@@ -90,20 +75,16 @@ struct _CoglOnscreen
 
   CoglBool swap_throttled;
 
-  CoglSwapBuffersNotifyList swap_callbacks;
+  CoglSwapCompleteNotifyList swap_callbacks;
 
   CoglBool resizable;
   CoglResizeNotifyList resize_callbacks;
 
-  CoglSwapInfoCallbackList swap_info_callbacks;
-
   int64_t frame_counter;
   int64_t swap_frame_counter; /* frame counter at last all to
                                * cogl_onscreen_swap_region() or
                                * cogl_onscreen_swap_buffers() */
-  CoglSwapInfo *swap_info[COGL_ONSCREEN_MAX_SWAP_INFOS];
-  int current_swap_info;
-  int n_swap_infos;
+  GQueue pending_swap_infos;
 
   void *winsys;
 };
@@ -121,7 +102,4 @@ _cogl_onscreen_notify_swap_buffers (CoglOnscreen *onscreen);
 void
 _cogl_onscreen_notify_resize (CoglOnscreen *onscreen);
 
-void
-_cogl_onscreen_notify_swap_info (CoglOnscreen *onscreen);
-
 #endif /* __COGL_ONSCREEN_PRIVATE_H */
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index 6df0583..374e0b9 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -36,8 +36,6 @@
 
 static void _cogl_onscreen_free (CoglOnscreen *onscreen);
 
-static void cogl_onscreen_before_swap (CoglOnscreen *onscreen);
-
 COGL_OBJECT_DEFINE_WITH_CODE (Onscreen, onscreen,
                               _cogl_onscreen_class.virt_unref =
                               _cogl_framebuffer_unref);
@@ -50,7 +48,6 @@ _cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
 
   COGL_TAILQ_INIT (&onscreen->swap_callbacks);
   COGL_TAILQ_INIT (&onscreen->resize_callbacks);
-  COGL_TAILQ_INIT (&onscreen->swap_info_callbacks);
 
   framebuffer->config = onscreen_template->config;
   cogl_object_ref (framebuffer->config.swap_chain);
@@ -79,9 +76,6 @@ _cogl_onscreen_new (void)
 
   COGL_FRAMEBUFFER (onscreen)->allocated = TRUE;
 
-  onscreen->frame_counter = -1;
-  onscreen->current_swap_info = COGL_ONSCREEN_MAX_SWAP_INFOS - 1;
-
   /* XXX: Note we don't initialize onscreen->winsys in this case. */
 
   return _cogl_onscreen_object_new (onscreen);
@@ -122,7 +116,8 @@ _cogl_onscreen_free (CoglOnscreen *onscreen)
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
   CoglResizeNotifyEntry *resize_entry;
-  CoglSwapBuffersNotifyEntry *swap_entry;
+  CoglSwapCompleteNotifyEntry *swap_entry;
+  CoglSwapInfo *swap_info;
 
   while ((resize_entry = COGL_TAILQ_FIRST (&onscreen->resize_callbacks)))
     {
@@ -133,9 +128,13 @@ _cogl_onscreen_free (CoglOnscreen *onscreen)
   while ((swap_entry = COGL_TAILQ_FIRST (&onscreen->swap_callbacks)))
     {
       COGL_TAILQ_REMOVE (&onscreen->swap_callbacks, swap_entry, list_node);
-      g_slice_free (CoglSwapBuffersNotifyEntry, swap_entry);
+      g_slice_free (CoglSwapCompleteNotifyEntry, swap_entry);
     }
 
+  while ((swap_info = g_queue_pop_tail (&onscreen->pending_swap_infos)))
+    cogl_object_unref (swap_info);
+  g_queue_clear (&onscreen->pending_swap_infos);
+
   if (framebuffer->context->window_buffer == COGL_FRAMEBUFFER (onscreen))
     framebuffer->context->window_buffer = NULL;
 
@@ -153,10 +152,13 @@ cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   const CoglWinsysVtable *winsys;
+  CoglSwapInfo *info;
 
   _COGL_RETURN_IF_FAIL  (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
 
-  cogl_onscreen_before_swap (onscreen);
+  info = _cogl_swap_info_new ();
+  info->frame_counter = onscreen->frame_counter;
+  g_queue_push_tail (&onscreen->pending_swap_infos, info);
 
   /* FIXME: we shouldn't need to flush *all* journals here! */
   cogl_flush ();
@@ -166,6 +168,7 @@ cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
                                     COGL_BUFFER_BIT_COLOR |
                                     COGL_BUFFER_BIT_DEPTH |
                                     COGL_BUFFER_BIT_STENCIL);
+  onscreen->frame_counter++;
 }
 
 void
@@ -175,10 +178,13 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   const CoglWinsysVtable *winsys;
+  CoglSwapInfo *info;
 
   _COGL_RETURN_IF_FAIL  (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
 
-  cogl_onscreen_before_swap (onscreen);
+  info = _cogl_swap_info_new ();
+  info->frame_counter = onscreen->frame_counter;
+  g_queue_push_tail (&onscreen->pending_swap_infos, info);
 
   /* FIXME: we shouldn't need to flush *all* journals here! */
   cogl_flush ();
@@ -197,6 +203,7 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
                                     COGL_BUFFER_BIT_COLOR |
                                     COGL_BUFFER_BIT_DEPTH |
                                     COGL_BUFFER_BIT_STENCIL);
+  onscreen->frame_counter++;
 }
 
 #ifdef COGL_HAS_X11_SUPPORT
@@ -282,37 +289,94 @@ cogl_win32_onscreen_get_window (CoglOnscreen *onscreen)
 #endif /* COGL_HAS_WIN32_SUPPORT */
 
 unsigned int
-cogl_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
-                                         CoglSwapBuffersNotify callback,
-                                         void *user_data)
+cogl_onscreen_add_swap_complete_callback (CoglOnscreen *onscreen,
+                                          CoglSwapCompleteNotify callback,
+                                          void *user_data)
 {
-  CoglSwapBuffersNotifyEntry *entry = g_slice_new0 (CoglSwapBuffersNotifyEntry);
-  static int next_swap_buffers_callback_id = 0;
+  CoglSwapCompleteNotifyEntry *entry = g_slice_new0 (CoglSwapCompleteNotifyEntry);
+  CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context;
 
   entry->callback = callback;
   entry->user_data = user_data;
-  entry->id = next_swap_buffers_callback_id++;
+  entry->id = ctx->next_swap_complete_callback_id++;
 
   COGL_TAILQ_INSERT_TAIL (&onscreen->swap_callbacks, entry, list_node);
 
   return entry->id;
 }
 
-void
-cogl_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
-                                            unsigned int id)
+static CoglSwapCompleteNotifyEntry *
+remove_swap_complete_notify_entry (CoglOnscreen *onscreen,
+                                   unsigned int id)
 {
-  CoglSwapBuffersNotifyEntry *entry;
+  CoglSwapCompleteNotifyEntry *entry;
 
   COGL_TAILQ_FOREACH (entry, &onscreen->swap_callbacks, list_node)
     {
       if (entry->id == id)
         {
           COGL_TAILQ_REMOVE (&onscreen->swap_callbacks, entry, list_node);
-          g_slice_free (CoglSwapBuffersNotifyEntry, entry);
-          break;
+          return entry;
         }
     }
+
+  return NULL;
+}
+
+void
+cogl_onscreen_remove_swap_complete_callback (CoglOnscreen *onscreen,
+                                             unsigned int id)
+{
+  CoglSwapCompleteNotifyEntry *entry =
+    remove_swap_complete_notify_entry (onscreen, id);
+
+  if (entry)
+    g_slice_free (CoglSwapCompleteNotifyEntry, entry);
+}
+
+typedef struct _SwapBufferCallbackState
+{
+  CoglSwapBuffersNotify callback;
+  void *user_data;
+} SwapBufferCallbackState;
+
+static void
+shim_swap_buffers_callback (CoglOnscreen *onscreen,
+                            CoglSwapInfo *info,
+                            void *user_data)
+{
+  SwapBufferCallbackState *state = user_data;
+
+  state->callback (COGL_FRAMEBUFFER (onscreen), state->user_data);
+}
+
+unsigned int
+cogl_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
+                                         CoglSwapBuffersNotify callback,
+                                         void *user_data)
+{
+  SwapBufferCallbackState *state = g_slice_new (SwapBufferCallbackState);
+
+  state->callback = callback;
+  state->user_data = user_data;
+
+  return cogl_onscreen_add_swap_complete_callback (onscreen,
+                                                   shim_swap_buffers_callback,
+                                                   state);
+}
+
+void
+cogl_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
+                                            unsigned int id)
+{
+  CoglSwapCompleteNotifyEntry *entry =
+    remove_swap_complete_notify_entry (onscreen, id);
+
+  if (entry)
+    {
+      g_slice_free (SwapBufferCallbackState, entry->user_data);
+      g_slice_free (CoglSwapCompleteNotifyEntry, entry);
+    }
 }
 
 void
@@ -363,13 +427,17 @@ cogl_onscreen_hide (CoglOnscreen *onscreen)
 void
 _cogl_onscreen_notify_swap_buffers (CoglOnscreen *onscreen)
 {
-  CoglSwapBuffersNotifyEntry *entry, *tmp;
+  CoglSwapCompleteNotifyEntry *entry, *tmp;
 
   COGL_TAILQ_FOREACH_SAFE (entry,
                            &onscreen->swap_callbacks,
                            list_node,
                            tmp)
-    entry->callback (COGL_FRAMEBUFFER (onscreen), entry->user_data);
+    {
+      CoglSwapInfo *info = g_queue_pop_tail (&onscreen->pending_swap_infos);
+
+      entry->callback (onscreen, info, entry->user_data);
+    }
 }
 
 void
@@ -478,101 +546,3 @@ cogl_onscreen_get_frame_counter (CoglOnscreen *onscreen)
 {
   return onscreen->frame_counter;
 }
-
-void
-cogl_onscreen_begin_frame (CoglOnscreen *onscreen,
-                           int64_t frame_time)
-{
-  onscreen->frame_counter++;
-  onscreen->current_swap_info = (onscreen->current_swap_info + 1) % COGL_ONSCREEN_MAX_SWAP_INFOS;
-
-  if (onscreen->n_swap_infos < COGL_ONSCREEN_MAX_SWAP_INFOS)
-    onscreen->n_swap_infos++;
-  else
-    cogl_object_unref (onscreen->swap_info[onscreen->current_swap_info]);
-
-  onscreen->swap_info[onscreen->current_swap_info] = _cogl_swap_info_new ();
-  onscreen->swap_info[onscreen->current_swap_info]->frame_counter = onscreen->frame_counter;
-  onscreen->swap_info[onscreen->current_swap_info]->frame_time = frame_time;
-}
-
-static void
-cogl_onscreen_before_swap (CoglOnscreen *onscreen)
-{
-  if (onscreen->swap_frame_counter == onscreen->frame_counter)
-    cogl_onscreen_begin_frame (onscreen, 0);
-
-  onscreen->swap_frame_counter = onscreen->frame_counter;
-}
-
-int64_t
-cogl_onscreen_get_frame_history_start (CoglOnscreen *onscreen)
-{
-  return onscreen->frame_counter - onscreen->n_swap_infos;
-}
-
-CoglSwapInfo *
-cogl_onscreen_get_swap_info (CoglOnscreen *onscreen,
-                                 int64_t       frame_counter)
-{
-  int pos;
-
-  if (frame_counter > onscreen->frame_counter)
-    return NULL;
-
-  if (frame_counter <= onscreen->frame_counter - onscreen->n_swap_infos)
-    return NULL;
-
-  pos = ((onscreen->current_swap_info -
-          (onscreen->frame_counter - frame_counter) + COGL_ONSCREEN_MAX_SWAP_INFOS)
-         % COGL_ONSCREEN_MAX_SWAP_INFOS);
-
-  return onscreen->swap_info[pos];
-}
-
-unsigned int
-cogl_onscreen_add_swap_info_callback (CoglOnscreen *onscreen,
-                                          CoglSwapInfoCallback callback,
-                                          void *user_data)
-{
-  CoglSwapInfoCallbackEntry *entry = g_slice_new (CoglSwapInfoCallbackEntry);
-  static int next_resize_callback_id = 0;
-
-  entry->callback = callback;
-  entry->user_data = user_data;
-  entry->id = next_resize_callback_id++;
-
-  COGL_TAILQ_INSERT_TAIL (&onscreen->swap_info_callbacks, entry, list_node);
-
-  return entry->id;
-}
-
-void
-cogl_onscreen_remove_swap_info_callback (CoglOnscreen *onscreen,
-                                             unsigned int id)
-{
-  CoglSwapInfoCallbackEntry *entry;
-
-  COGL_TAILQ_FOREACH (entry, &onscreen->swap_info_callbacks, list_node)
-    {
-      if (entry->id == id)
-        {
-          COGL_TAILQ_REMOVE (&onscreen->swap_info_callbacks, entry, list_node);
-          g_slice_free (CoglSwapInfoCallbackEntry, entry);
-          break;
-        }
-    }
-}
-
-void
-_cogl_onscreen_notify_swap_info (CoglOnscreen *onscreen)
-{
-  CoglSwapInfoCallbackEntry *entry, *tmp;
-
-  COGL_TAILQ_FOREACH_SAFE (entry,
-                           &onscreen->swap_info_callbacks,
-                           list_node,
-                           tmp)
-    entry->callback (onscreen, entry->user_data);
-}
-
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index a82895b..d31aebc 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -333,6 +333,70 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
                            const int *rectangles,
                            int n_rectangles);
 
+/**
+ * CoglSwapCompleteNotify:
+ * @onscreen: The onscreen framebuffer who's swap has completed
+ * @info: Meta information, such as timing information, about the
+ *        completed swap
+ * @user_data: The user pointer passed to
+ *             cogl_onscreen_add_swap_complete_callback()
+ *
+ * Is a callback that can be registered via
+ * cogl_onscreen_add_swap_complete_callback() to be notified when a
+ * swap buffers request made with cogl_onscreen_swap_buffers() has
+ * completed and to be able to receive meta information about the
+ * completed swap, such as timing information.
+ *
+ * Since: 1.14
+ * Stability: unstable
+ */
+typedef void (*CoglSwapCompleteNotify) (CoglOnscreen *onscreen,
+                                        CoglSwapInfo *info,
+                                        void *user_data);
+
+/**
+ * cogl_onscreen_add_swap_complete_callback:
+ * @onscreen: A #CoglOnscreen framebuffer
+ * @callback: A callback function to call when a swap has completed
+ * @user_data: A private pointer to be passed to @callback
+ *
+ * Installs a @callback function that should be called whenever a swap buffers
+ * request (made using cogl_onscreen_swap_buffers()) for the given
+ * @onscreen completes.
+ *
+ * <note>Applications should check for the %COGL_FEATURE_ID_SWAP_BUFFERS_EVENT
+ * feature before using this API. It's currently undefined when and if
+ * registered callbacks will be called if this feature is not supported.</note>
+ *
+ * We recommend using this mechanism when available to manually throttle your
+ * applications (in conjunction with  cogl_onscreen_set_swap_throttled()) so
+ * your application will be able to avoid long blocks in the driver caused by
+ * throttling when you request to swap buffers too quickly.
+ *
+ * Return value: a unique identifier that can be used to remove to remove
+ *               the callback later.
+ * Since: 1.14
+ * Stability: unstable
+ */
+unsigned int
+cogl_onscreen_add_swap_complete_callback (CoglOnscreen *onscreen,
+                                          CoglSwapCompleteNotify callback,
+                                          void *user_data);
+
+/**
+ * cogl_onscreen_remove_swap_complete_callback:
+ * @onscreen: A #CoglOnscreen
+ * @id: An identifier returned from cogl_onscreen_add_swap_complete_callback()
+ *
+ * Removes a callback that was previously registered
+ * using cogl_onscreen_add_swap_complete_callback().
+ *
+ * Since: 1.14
+ * Stability: unstable
+ */
+void
+cogl_onscreen_remove_swap_complete_callback (CoglOnscreen *onscreen,
+                                             unsigned int id);
 
 typedef void (*CoglSwapBuffersNotify) (CoglFramebuffer *framebuffer,
                                        void *user_data);
@@ -360,6 +424,7 @@ typedef void (*CoglSwapBuffersNotify) (CoglFramebuffer *framebuffer,
  *               the callback later.
  * Since: 1.10
  * Stability: unstable
+ * Deprecated: 1.14: Use cogl_onscreen_add_swap_complete_callback
  */
 unsigned int
 cogl_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
@@ -376,6 +441,7 @@ cogl_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
  *
  * Since: 1.10
  * Stability: unstable
+ * Deprecated: 1.14: Use cogl_onscreen_remove_swap_complete_callback
  */
 void
 cogl_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
@@ -547,109 +613,6 @@ cogl_is_onscreen (void *object);
 int64_t
 cogl_onscreen_get_frame_counter (CoglOnscreen *onscreen);
 
-/**
- * cogl_onscreen_begin_frame:
- * @onscreen: a #CoglOnscreen framebuffer
- * @frame_time: the time that should be used for creating
- *   content for this frame.
- *
- * Marks the beginning of a frame. This increases the frame
- * counter value and creates a new #CoglSwapInfo objeect.
- *
- * Since: 2.0
- */
-void
-cogl_onscreen_begin_frame (CoglOnscreen *onscreen,
-                           int64_t frame_time);
-
-/**
- * cogl_onscreen_get_frame_history_start:
- * @onscreen: a #CoglOnscreen framebuffer
- *
- * Gets the frame counter for the oldest #CoglSwapInfo that is
- * being kept in the history. cogl_onscreen_get_swap_info() will
- * always return %NULl for any frame counter before this.
- *
- * Return value: the frame counter for the oldest #CoglSwapInfo
- *  in the history.
- * Since: 2.0
- */
-int64_t
-cogl_onscreen_get_frame_history_start (CoglOnscreen *onscreen);
-
-
-/**
- * cogl_onscreen_get_swap_info:
- * @onscreen: A #CoglOnscreen framebuffer
- * @frame_counter: the value of cogl_onscreen_get_frame_counter()
- *       when the frame finished drawing.
- *
- * Gets frame timing information for a particular frame.
- *
- * Return value: a #CoglSwapInfo object, or %NULL if swap info
- *   information is not available for the given frame.
- * Since: 2.0
- */
-CoglSwapInfo *
-cogl_onscreen_get_swap_info (CoglOnscreen *onscreen,
-                             int64_t frame_counter);
-
-/**
- * CoglSwapInfoCallback:
- * @onscreen: A #CoglOnscreen framebuffer that has updated timing information
- * @user_data: The private passed to
- *             cogl_onscreen_add_swap_info_callback()
- *
- * Is a callback type used with the
- * cogl_onscreen_add_swap_info_callback() allowing applications to be
- * notified whenever new frame timings information is available
- * via cogl_onscreen_get_swap_info().
- *
- * <note>A frame timings callback will only ever be called while dispatching
- * Cogl events from the system mainloop; so for example during
- * cogl_poll_dispatch(). This is so that callbacks shouldn't occur
- * while an application might have arbitrary locks held for
- * example.</note>
- *
- * Since: 2.0
- */
-typedef void (*CoglSwapInfoCallback) (CoglOnscreen *onscreen,
-                                      void *user_data);
-
-/**
- * cogl_onscreen_add_swap_info_callback:
- * @onscreen: A #CoglOnscreen framebuffer
- * @callback: A callback function to call when new frame timings information is available
- * @user_data: A private pointer to be passed to @callback
- *
- * Installs a @callback function that should be called whenever new data
- * is available via cogl_onscreen_get_swap_info().
- *
- * Return value: a unique identifier that can be used to remove to remove
- *               the callback later.
- * Since: 2.0
- * Stability: unstable
- */
-unsigned int
-cogl_onscreen_add_swap_info_callback (CoglOnscreen *onscreen,
-                                      CoglSwapInfoCallback callback,
-                                      void *user_data);
-
-/**
- * cogl_onscreen_remove_swap_info_callback:
- * @onscreen: A #CoglOnscreen framebuffer
- * @id: An identifier returned from cogl_onscreen_add_swap_info_callback()
- *
- * Removes a callback that was previously registered
- * using cogl_onscreen_add_swap_info_callback().
- *
- * Since: 1.10
- * Stability: unstable
- */
-void
-cogl_onscreen_remove_swap_info_callback (CoglOnscreen *onscreen,
-                                         unsigned int id);
-
 G_END_DECLS
 
 #endif /* __COGL_ONSCREEN_H */
diff --git a/cogl/cogl-swap-info-private.h b/cogl/cogl-swap-info-private.h
index 2697d53..61953fa 100644
--- a/cogl/cogl-swap-info-private.h
+++ b/cogl/cogl-swap-info-private.h
@@ -26,17 +26,16 @@
 
 #include "cogl-swap-info.h"
 #include "cogl-object-private.h"
+#include "cogl-output.h"
 
 struct _CoglSwapInfo
 {
   CoglObject _parent;
 
   int64_t frame_counter;
-  int64_t frame_time;
   int64_t presentation_time;
-  int64_t refresh_interval;
 
-  unsigned int complete : 1;
+  CoglOutput *output;
 };
 
 CoglSwapInfo *_cogl_swap_info_new (void);
diff --git a/cogl/cogl-swap-info.c b/cogl/cogl-swap-info.c
index b2dda13..e8f83bd 100644
--- a/cogl/cogl-swap-info.c
+++ b/cogl/cogl-swap-info.c
@@ -47,12 +47,6 @@ _cogl_swap_info_free (CoglSwapInfo *info)
   g_slice_free (CoglSwapInfo, info);
 }
 
-CoglBool
-cogl_swap_info_get_complete (CoglSwapInfo *info)
-{
-  return info->complete;
-}
-
 int64_t
 cogl_swap_info_get_frame_counter (CoglSwapInfo *info)
 {
@@ -60,19 +54,13 @@ cogl_swap_info_get_frame_counter (CoglSwapInfo *info)
 }
 
 int64_t
-cogl_swap_info_get_frame_time (CoglSwapInfo *info)
-{
-  return info->frame_time;
-}
-
-int64_t
 cogl_swap_info_get_presentation_time (CoglSwapInfo *info)
 {
   return info->presentation_time;
 }
 
-int64_t
-cogl_swap_info_get_refresh_interval (CoglSwapInfo *info)
+CoglOutput *
+cogl_swap_info_get_output (CoglSwapInfo *info)
 {
-  return info->refresh_interval;
+  return info->output;
 }
diff --git a/cogl/cogl-swap-info.h b/cogl/cogl-swap-info.h
index 710d005..62728b6 100644
--- a/cogl/cogl-swap-info.h
+++ b/cogl/cogl-swap-info.h
@@ -32,6 +32,7 @@
 #define __COGL_SWAP_INFO_H
 
 #include <cogl/cogl-types.h>
+#include <cogl/cogl-output.h>
 #include <glib.h>
 
 G_BEGIN_DECLS
@@ -54,20 +55,6 @@ CoglBool
 cogl_is_swap_info (void *object);
 
 /**
- * cogl_swap_info_get_complete:
- * @info: a #CoglSwapInfo object
- *
- * Gets whether all information that will potentially be provided for
- * the frame has been provided. Once a swap info object is complete,
- * no further changes will be made to it.
- *
- * Return value: whether the swap info object is complete.
- * Since: 2.0
- * Stability: unstable
- */
-CoglBool cogl_swap_info_get_complete (CoglSwapInfo *info);
-
-/**
  * cogl_swap_info_get_frame_counter:
  * @info: a #CoglSwapInfo object
  *
@@ -81,22 +68,6 @@ CoglBool cogl_swap_info_get_complete (CoglSwapInfo *info);
 int64_t cogl_swap_info_get_frame_counter (CoglSwapInfo *info);
 
 /**
- * cogl_swap_info_get_frame_time:
- * @info: a #CoglSwapInfo object
- *
- * Gets the time used for creating content for the frame. This
- * is determined by the time passed to cogl_onscreen_begin_frame(),
- * and will typically be the current time when rendering started
- * for the frame.
- *
- * Return value: the time used for coreating content for the frame,
- *  in the timescale of g_get_monotonic_time().
- * Since: 2.0
- * Stability: unstable
- */
-int64_t cogl_swap_info_get_frame_time (CoglSwapInfo *info);
-
-/**
  * cogl_swap_info_get_presentation_time:
  * @info: a #CoglSwapInfo object
  *
@@ -111,19 +82,18 @@ int64_t cogl_swap_info_get_frame_time (CoglSwapInfo *info);
 int64_t cogl_swap_info_get_presentation_time (CoglSwapInfo *info);
 
 /**
- * cogl_swap_info_get_refresh_interval:
+ * cogl_swap_info_get_output:
  * @info: a #CoglSwapInfo object
  *
- * Gets the refresh interval for the output that the frame was on at the
- * time the frame was presented. This is the number of microseconds between
- * refreshes of the screen, and is equal to 1000000 / refresh_rate.
+ * Gets the #CoglOutput that the swapped frame was presented to.
  *
- * Return value: the refresh interval, in microsecoonds.
- *  .
+ * Return value: The #CoglOutput that the frame was presented to, or
+ *               %NULL if this could not be determined.
  * Since: 2.0
  * Stability: unstable
  */
-int64_t cogl_swap_info_get_refresh_interval (CoglSwapInfo *info);
+CoglOutput *
+cogl_swap_info_get_output (CoglSwapInfo *info);
 
 G_END_DECLS
 
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 3814e9a..c8878a5 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -273,29 +273,12 @@ ust_to_monotonic_time (CoglRenderer *renderer,
 }
 
 static void
-set_info_complete (CoglOnscreen *onscreen)
-{
-  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
-  CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
-  CoglGLXDisplay *glx_display = context->display->winsys;
-  int frame_counter = cogl_onscreen_get_frame_counter (onscreen);
-  CoglSwapInfo *info = cogl_onscreen_get_swap_info (onscreen, frame_counter);
-
-  info->complete = TRUE;
-
-  glx_display->pending_swap_info_notify = TRUE;
-  glx_onscreen->pending_swap_info_notify = TRUE;
-}
-
-static void
 notify_swap_buffers (CoglContext *context, GLXBufferSwapComplete *swap_event)
 {
   CoglOnscreen *onscreen = find_onscreen_for_xid (context, (uint32_t)swap_event->drawable);
   CoglDisplay *display = context->display;
   CoglGLXDisplay *glx_display = display->winsys;
   CoglOnscreenGLX *glx_onscreen;
-  int frame_counter;
-  CoglSwapInfo *info;
 
   if (!onscreen)
     return;
@@ -307,14 +290,14 @@ notify_swap_buffers (CoglContext *context, GLXBufferSwapComplete *swap_event)
   glx_display->pending_swap_notify = TRUE;
   glx_onscreen->pending_swap_notify = TRUE;
 
-  frame_counter = cogl_onscreen_get_frame_counter (onscreen);
-  info = cogl_onscreen_get_swap_info (onscreen, frame_counter);
   if (swap_event->ust != 0)
-    info->presentation_time = ust_to_monotonic_time (context->display->renderer,
-                                                        glx_onscreen->glxwin,
-                                                        swap_event->ust);
-
-  set_info_complete (onscreen);
+    {
+      CoglSwapInfo *info = g_queue_peek_tail (&onscreen->pending_swap_infos);
+      info->presentation_time =
+        ust_to_monotonic_time (context->display->renderer,
+                               glx_onscreen->glxwin,
+                               swap_event->ust);
+    }
 }
 
 static void
@@ -1374,11 +1357,7 @@ _cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen)
   if (glx_renderer->pf_glXWaitForMsc ||
       glx_renderer->pf_glXGetVideoSync)
     {
-      int frame_counter;
-      CoglSwapInfo *info;
-
-      frame_counter = cogl_onscreen_get_frame_counter (onscreen);
-      info = cogl_onscreen_get_swap_info (onscreen, frame_counter);
+      CoglSwapInfo *info = g_queue_peek_tail (&onscreen->pending_swap_infos);
 
       if (glx_renderer->pf_glXWaitForMsc)
         {
@@ -1426,20 +1405,6 @@ _cogl_winsys_get_vsync_counter (void)
 }
 
 static void
-set_refresh_interval_from_output (CoglOnscreen *onscreen,
-                                  CoglOutput   *output)
-{
-  float refresh_rate = cogl_output_get_refresh_rate (output);
-  if (refresh_rate != 0.0)
-    {
-      int frame_counter = cogl_onscreen_get_frame_counter (onscreen);
-      CoglSwapInfo *info = cogl_onscreen_get_swap_info (onscreen, frame_counter);
-
-      info->refresh_interval = (int)(0.5 + (1000000. / refresh_rate));
-    }
-}
-
-static void
 _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
                                    const int *user_rectangles,
                                    int n_rectangles)
@@ -1625,21 +1590,20 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
 
   if (!xlib_onscreen->is_foreign_xwin)
     {
-      CoglOutput *output;
+      CoglSwapInfo *info = g_queue_peek_tail (&onscreen->pending_swap_infos);
 
       x_min = CLAMP (x_min, 0, framebuffer_width);
       x_max = CLAMP (x_max, 0, framebuffer_width);
       y_min = CLAMP (y_min, 0, framebuffer_width);
       y_max = CLAMP (y_max, 0, framebuffer_height);
 
-      output = _cogl_xlib_renderer_output_for_rectangle (context->display->renderer,
-                                                         xlib_onscreen->x + x_min, xlib_onscreen->y + y_min,
-                                                         x_max - x_min, y_max - y_min);
-      if (output)
-        set_refresh_interval_from_output (onscreen, output);
+      info->output =
+        _cogl_xlib_renderer_output_for_rectangle (context->display->renderer,
+                                                  xlib_onscreen->x + x_min,
+                                                  xlib_onscreen->y + y_min,
+                                                  x_max - x_min,
+                                                  y_max - y_min);
     }
-
-  set_info_complete (onscreen);
 }
 
 static void
@@ -1720,11 +1684,10 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
     glx_onscreen->last_swap_vsync_counter = _cogl_winsys_get_vsync_counter ();
 
   if (xlib_onscreen->output)
-    set_refresh_interval_from_output (onscreen, xlib_onscreen->output);
-
-  if (!(glx_renderer->pf_glXSwapInterval &&
-        _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT)))
-    set_info_complete (onscreen);
+    {
+      CoglSwapInfo *info = g_queue_peek_tail (&onscreen->pending_swap_infos);
+      info->output = xlib_onscreen->output;
+    }
 }
 
 static uint32_t
@@ -2424,12 +2387,6 @@ flush_pending_notifications_cb (void *data,
           _cogl_onscreen_notify_resize (onscreen);
           glx_onscreen->pending_resize_notify = FALSE;
         }
-
-      if (glx_onscreen->pending_swap_info_notify)
-        {
-          _cogl_onscreen_notify_swap_info (onscreen);
-          glx_onscreen->pending_swap_info_notify = FALSE;
-        }
     }
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]