[Cogl] [PATCH] Add cogl_onscreen_add_swap_complete_callback() api

Robert Bragg robert at sixbynine.org
Thu Jan 24 13:28:26 PST 2013


On Thu, Jan 24, 2013 at 7:11 PM, Owen Taylor <otaylor at redhat.com> wrote:
> At this point, I lose track of what's going on in
>
>  wip/rib/frame-synchronization
>
> This patch does a bunch of different things.
>
>  * Reworks the callback structure - I think with the later patches
>    on top in your branch the final API is fine,  but code is removed
>    from the GLX code that I believe is necessary to dispatch the right
>    event at the right time, and I don't see it added back later.
>
>  * Removes a public frame history indexed by frame counter.
>    If you dislike it, I don't need it, could be added back later.
>
>  * Removes begin_frame() and the idea that there is a current frame
>    while drawing and any ability to access the FrameInfo until you
>    get the first event. I disagree with these changes. It means that
>    any history that an application keeps is going to have a strange
>    structure where frames that have been drawn don't appear in the
>    history until later.
>
>  * Removes the frame time. Don't really care - I think it's a useful
>    concept, but if you want COGL really to be minimal and imply nothing
>    about the structure of the application, I can see where it could
>    be considered an extraneous
>
>  * Replaces the refresh interval in the FrameInfo with the Output - with
>    your later changes to add the refresh interval back in addition,
>    this is OK.
>
> My plan of attack here is to rebase your patches that I agree
> with before this patch, and then rework this patch to go directly to
> your final API and not pull in the changes that I disagree with, then we
> can discuss those more separately :-)

hmm, I guess this is the problem of having a long Christmas holiday
break since starting our discussions.

In particular your concern about not being able to access the
FrameInfo mid-frame was something you raised before and I tried to
re-assure you that this approach does not preclude us accessing the
FrameInfo mid-frame. It is only a technical detail with the current
implementation that means the FrameInfo is only allocated at the point
of swap_buffers() and it's done that way because in practice we don't
currently need the FrameInfo earlier. Conceptually though the
frame-info can be considered to exist for the full duration of the
frame while commands are being submitted etc and it should be trivial
to change the internals so that this is the case. I don't think any
_begin_frame() api is required to address this concern. If it would
help I can write a patch to clarify what I mean, but basically I think
it just means allocating the first CoglFrameInfo when the framebuffer
itself is allocated, and then all subsequent FrameInfos are allocated
in the _swap_buffers() but instead of allocating the FrameInfo for the
current frame (as is done with my current patch) it would allocate the
info for the next frame instead.

regarding the frame time, this is something we went back and forth
over a few times, and to confuse matters I also changed my mind over
this, and then back again, at one point. The rationale for dropping
this wasn't really about minimalism, but in the end we concluded that
CoglOnscreen is not the right place conceptually to be trying to track
that frame timestamp, and even in practice it doesn't look like it
would be a good place to store the data.

I think you had previously suggested that associating the stamp with
the FrameInfo made it easy to share between the different
toolkit/application components that need access that frame timestamp,
but since since there can be numerous framebuffers involved in
rendering a frame, including multiple onscreen framebuffers
potentially, it wouldn't seem like a good/convenient way to share the
data in clutter for example. In clutter it seems like the stage would
be a more appropriate place to share that timestamp if sharing is
required. Related to this, I think that at some point it would be good
for Clutter to introduce the idea of a PaintContext and if it did
that, that may be an even more appropriate place to share the frame
time.

I guess I was kind of hoping we were already pretty close to having
something that we could land (mostly just a case of squashing commits
with some relatively minor cleanups/fixes) but either way I guess it
shouldn't be too much trouble if you do as you say and squash the bits
you are happy with (at least that way I guess you don't end up with
attribution for stuff you disagree with :-)) and then we can hopefully
resolve the remaining issues from there.

Depending on how quickly you get started on squashing work, hopefully
you will see my latest wip/rib/frame-synchronization which is based on
the cogl-1.14 branch including the change to emitting _COMPLETE events
instead of _PRESENTED events.

kind regards,
- Robert

>
> - Owen
>
> On Tue, 2012-12-04 at 18:08 +0000, Robert Bragg wrote:
>> From: Robert Bragg <robert at linux.intel.com>
>>
>> Here's another patch to show what I was thinking about with regards to
>> removing the history related apis and instead passing the information to
>> applications via a modified swap-complete callback api.
>>
>> -- >8--
>>
>> 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 5d1bda5..2917b6c 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)
>> @@ -1616,21 +1581,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
>> @@ -1711,11 +1675,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
>> @@ -2415,12 +2378,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;
>> -        }
>>      }
>>  }
>>
>
>


More information about the Cogl mailing list