[cogl/wip/frame-synchronization: 217/223] onscreen: Provide more general CoglFrameCallback api
- From: Owen Taylor <otaylor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/frame-synchronization: 217/223] onscreen: Provide more general CoglFrameCallback api
- Date: Fri, 25 Jan 2013 05:57:19 +0000 (UTC)
commit 8a1a1f56135af22c7316529f9e6f400059e305b8
Author: Robert Bragg <robert linux intel com>
Date: Thu Jan 10 19:23:48 2013 +0000
onscreen: Provide more general CoglFrameCallback api
This reworks the cogl_onscreen_add_swap_complete_callback api to instead
be named cogl_onscreen_add_frame_callback and to take a callback that
can accept other events besides just swap completion events. This means
we can add more events in the future that signal the progression of a
frame without needing lots of new callback api for each event.
TODO: squash this back into owen's patch
cogl/cogl-context-private.h | 3 +
cogl/cogl-context.c | 6 +
cogl/cogl-context.h | 6 +
cogl/cogl-glx-display-private.h | 4 +-
cogl/cogl-onscreen-private.h | 37 ++-----
cogl/cogl-onscreen.c | 198 +++++++++++++++++++++++--------------
cogl/cogl-onscreen.h | 202 ++++++++++++++++++++++++++----------
cogl/winsys/cogl-winsys-egl-kms.c | 10 ++-
cogl/winsys/cogl-winsys-glx.c | 88 +++++++++-------
9 files changed, 356 insertions(+), 198 deletions(-)
---
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 2780a59..ce92aa7 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -190,6 +190,9 @@ struct _CoglContext
gboolean have_last_offscreen_allocate_flags;
CoglOffscreenAllocateFlags last_offscreen_allocate_flags;
+ GHashTable *swap_callback_closures;
+ int next_frame_callback_id;
+
CoglGLES2Context *current_gles2_context;
GQueue gles2_context_stack;
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 6dff50c..5f3453f 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -308,6 +308,9 @@ cogl_context_new (CoglDisplay *display,
context->current_draw_buffer_state_flushed = 0;
context->current_draw_buffer_changes = COGL_FRAMEBUFFER_STATE_ALL;
+ context->swap_callback_closures =
+ g_hash_table_new (g_direct_hash, g_direct_equal);
+
g_queue_init (&context->gles2_context_stack);
context->journal_flush_attributes_array =
@@ -503,6 +506,9 @@ _cogl_context_free (CoglContext *context)
if (context->blit_texture_pipeline)
cogl_object_unref (context->blit_texture_pipeline);
+ if (context->swap_callback_closures)
+ g_hash_table_destroy (context->swap_callback_closures);
+
g_warn_if_fail (context->gles2_context_stack.length == 0);
if (context->journal_flush_attributes_array)
diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h
index 3356440..ae306d6 100644
--- a/cogl/cogl-context.h
+++ b/cogl/cogl-context.h
@@ -208,6 +208,10 @@ cogl_is_context (void *object);
* suported.
* @COGL_FEATURE_ID_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering
* 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_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
@@ -237,6 +241,8 @@ typedef enum _CoglFeatureID
COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
COGL_FEATURE_ID_GLES2_CONTEXT,
COGL_FEATURE_ID_DEPTH_TEXTURE,
+ COGL_FEATURE_ID_FRAME_SYNC,
+ COGL_FEATURE_ID_PRESENTATION_TIME,
/*< private >*/
_COGL_N_FEATURE_IDS /*< skip >*/
diff --git a/cogl/cogl-glx-display-private.h b/cogl/cogl-glx-display-private.h
index fb7f395..69b1570 100644
--- a/cogl/cogl-glx-display-private.h
+++ b/cogl/cogl-glx-display-private.h
@@ -50,9 +50,9 @@ typedef struct _CoglGLXDisplay
GLXContext glx_context;
GLXWindow dummy_glxwin;
Window dummy_xwin;
- CoglBool pending_swap_notify;
+ CoglBool pending_sync_notify;
+ CoglBool pending_complete_notify;
CoglBool pending_resize_notify;
- CoglBool pending_frame_info_notify;
} CoglGLXDisplay;
#endif /* __COGL_DISPLAY_GLX_PRIVATE_H */
diff --git a/cogl/cogl-onscreen-private.h b/cogl/cogl-onscreen-private.h
index e6c2b42..da36de0 100644
--- a/cogl/cogl-onscreen-private.h
+++ b/cogl/cogl-onscreen-private.h
@@ -24,6 +24,7 @@
#ifndef __COGL_ONSCREEN_PRIVATE_H
#define __COGL_ONSCREEN_PRIVATE_H
+#include "cogl-onscreen.h"
#include "cogl-framebuffer-private.h"
#include "cogl-queue.h"
@@ -35,17 +36,16 @@
#define COGL_ONSCREEN_MAX_FRAME_INFOS 16
-typedef struct _CoglSwapBuffersNotifyEntry CoglSwapBuffersNotifyEntry;
+COGL_TAILQ_HEAD (CoglFrameCallbackList, CoglFrameClosure);
-COGL_TAILQ_HEAD (CoglSwapBuffersNotifyList, CoglSwapBuffersNotifyEntry);
-
-struct _CoglSwapBuffersNotifyEntry
+struct _CoglFrameClosure
{
- COGL_TAILQ_ENTRY (CoglSwapBuffersNotifyEntry) list_node;
+ COGL_TAILQ_ENTRY (CoglFrameClosure) list_node;
+
+ CoglFrameCallback callback;
- CoglSwapBuffersNotify callback;
void *user_data;
- unsigned int id;
+ CoglUserDataDestroyCallback destroy;
};
typedef struct _CoglResizeNotifyEntry CoglResizeNotifyEntry;
@@ -61,19 +61,6 @@ struct _CoglResizeNotifyEntry
unsigned int id;
};
-typedef struct _CoglFrameInfoCallbackEntry CoglFrameInfoCallbackEntry;
-
-COGL_TAILQ_HEAD (CoglFrameInfoCallbackList, CoglFrameInfoCallbackEntry);
-
-struct _CoglFrameInfoCallbackEntry
-{
- COGL_TAILQ_ENTRY (CoglFrameInfoCallbackEntry) list_node;
-
- CoglFrameInfoCallback callback;
- void *user_data;
- unsigned int id;
-};
-
struct _CoglOnscreen
{
CoglFramebuffer _parent;
@@ -90,13 +77,11 @@ struct _CoglOnscreen
CoglBool swap_throttled;
- CoglSwapBuffersNotifyList swap_callbacks;
+ CoglFrameCallbackList frame_closures;
CoglBool resizable;
CoglResizeNotifyList resize_callbacks;
- CoglFrameInfoCallbackList frame_info_callbacks;
-
int64_t frame_counter;
int64_t swap_frame_counter; /* frame counter at last all to
* cogl_onscreen_swap_region() or
@@ -116,12 +101,12 @@ _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_resize (CoglOnscreen *onscreen);
+_cogl_onscreen_notify_complete (CoglOnscreen *onscreen, CoglFrameInfo *info);
void
-_cogl_onscreen_notify_frame_info (CoglOnscreen *onscreen);
+_cogl_onscreen_notify_resize (CoglOnscreen *onscreen);
#endif /* __COGL_ONSCREEN_PRIVATE_H */
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index 52490b6..a1481da 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -48,9 +48,8 @@ _cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- COGL_TAILQ_INIT (&onscreen->swap_callbacks);
+ COGL_TAILQ_INIT (&onscreen->frame_closures);
COGL_TAILQ_INIT (&onscreen->resize_callbacks);
- COGL_TAILQ_INIT (&onscreen->frame_info_callbacks);
framebuffer->config = onscreen_template->config;
cogl_object_ref (framebuffer->config.swap_chain);
@@ -122,7 +121,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;
+ CoglFrameClosure *frame_closure;
+ int i;
while ((resize_entry = COGL_TAILQ_FIRST (&onscreen->resize_callbacks)))
{
@@ -130,10 +130,20 @@ _cogl_onscreen_free (CoglOnscreen *onscreen)
g_slice_free (CoglResizeNotifyEntry, resize_entry);
}
- while ((swap_entry = COGL_TAILQ_FIRST (&onscreen->swap_callbacks)))
+ while ((frame_closure = COGL_TAILQ_FIRST (&onscreen->frame_closures)))
{
- COGL_TAILQ_REMOVE (&onscreen->swap_callbacks, swap_entry, list_node);
- g_slice_free (CoglSwapBuffersNotifyEntry, swap_entry);
+ COGL_TAILQ_REMOVE (&onscreen->frame_closures, frame_closure, list_node);
+
+ if (frame_closure->destroy)
+ frame_closure->destroy (frame_closure->user_data);
+
+ g_slice_free (CoglFrameClosure, frame_closure);
+ }
+
+ for (i = 0; i < onscreen->n_frame_infos; i++)
+ {
+ cogl_object_unref (onscreen->frame_info[i]);
+ onscreen->frame_info[i] = NULL;
}
if (framebuffer->context->window_buffer == COGL_FRAMEBUFFER (onscreen))
@@ -281,38 +291,107 @@ cogl_win32_onscreen_get_window (CoglOnscreen *onscreen)
#endif /* COGL_HAS_WIN32_SUPPORT */
+CoglFrameClosure *
+cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen,
+ CoglFrameCallback callback,
+ void *user_data,
+ CoglUserDataDestroyCallback destroy)
+{
+ CoglFrameClosure *closure = g_slice_new0 (CoglFrameClosure);
+
+ closure->callback = callback;
+ closure->user_data = user_data;
+ closure->destroy = destroy;
+
+ COGL_TAILQ_INSERT_TAIL (&onscreen->frame_closures, closure, list_node);
+
+ return closure;
+}
+
+void
+cogl_onscreen_remove_frame_callback (CoglOnscreen *onscreen,
+ CoglFrameClosure *closure)
+{
+ _COGL_RETURN_IF_FAIL (closure);
+
+ if (closure->destroy)
+ closure->destroy (closure->user_data);
+
+ COGL_TAILQ_REMOVE (&onscreen->frame_closures, closure, list_node);
+
+ g_slice_free (CoglFrameClosure, closure);
+}
+
+typedef struct _SwapBufferCallbackState
+{
+ CoglSwapBuffersNotify callback;
+ void *user_data;
+} SwapBufferCallbackState;
+
+static void
+destroy_swap_buffers_callback_state (void *user_data)
+{
+ g_slice_free (SwapBufferCallbackState, user_data);
+}
+
+static void
+shim_swap_buffers_callback (CoglOnscreen *onscreen,
+ CoglFrameEvent event,
+ CoglFrameInfo *info,
+ void *user_data)
+{
+ SwapBufferCallbackState *state = user_data;
+
+ /* 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);
+}
+
unsigned int
cogl_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
CoglSwapBuffersNotify callback,
void *user_data)
{
- CoglSwapBuffersNotifyEntry *entry = g_slice_new0 (CoglSwapBuffersNotifyEntry);
- static int next_swap_buffers_callback_id = 0;
+ CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context;
+ SwapBufferCallbackState *state = g_slice_new (SwapBufferCallbackState);
+ CoglFrameClosure *closure;
+ unsigned int id = ctx->next_frame_callback_id++;
- entry->callback = callback;
- entry->user_data = user_data;
- entry->id = next_swap_buffers_callback_id++;
+ state->callback = callback;
+ state->user_data = user_data;
- COGL_TAILQ_INSERT_TAIL (&onscreen->swap_callbacks, entry, list_node);
+ closure =
+ cogl_onscreen_add_frame_callback (onscreen,
+ shim_swap_buffers_callback,
+ state,
+ destroy_swap_buffers_callback_state);
- return entry->id;
+ g_hash_table_insert (ctx->swap_callback_closures,
+ GINT_TO_POINTER (id),
+ closure);
+
+ return id;
}
void
cogl_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
unsigned int id)
{
- CoglSwapBuffersNotifyEntry *entry;
+ CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglFrameClosure *closure = g_hash_table_lookup (ctx->swap_callback_closures,
+ GINT_TO_POINTER (id));
- 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;
- }
- }
+ _COGL_RETURN_IF_FAIL (closure);
+
+ cogl_onscreen_remove_frame_callback (onscreen, closure);
}
void
@@ -361,15 +440,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;
+
+ COGL_TAILQ_FOREACH_SAFE (entry,
+ &onscreen->frame_closures,
+ list_node,
+ tmp)
+ {
+ entry->callback (onscreen, COGL_FRAME_EVENT_SYNC, info,
+ entry->user_data);
+ }
+}
+
+void
+_cogl_onscreen_notify_complete (CoglOnscreen *onscreen, CoglFrameInfo *info)
{
- CoglSwapBuffersNotifyEntry *entry, *tmp;
+ CoglFrameClosure *entry, *tmp;
COGL_TAILQ_FOREACH_SAFE (entry,
- &onscreen->swap_callbacks,
+ &onscreen->frame_closures,
list_node,
tmp)
- entry->callback (COGL_FRAMEBUFFER (onscreen), entry->user_data);
+ {
+ entry->callback (onscreen, COGL_FRAME_EVENT_COMPLETE, info,
+ entry->user_data);
+ }
}
void
@@ -519,50 +616,3 @@ cogl_onscreen_get_frame_info (CoglOnscreen *onscreen,
return onscreen->frame_info[pos];
}
-
-unsigned int
-cogl_onscreen_add_frame_info_callback (CoglOnscreen *onscreen,
- CoglFrameInfoCallback callback,
- void *user_data)
-{
- CoglFrameInfoCallbackEntry *entry = g_slice_new (CoglFrameInfoCallbackEntry);
- 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->frame_info_callbacks, entry, list_node);
-
- return entry->id;
-}
-
-void
-cogl_onscreen_remove_frame_info_callback (CoglOnscreen *onscreen,
- unsigned int id)
-{
- CoglFrameInfoCallbackEntry *entry;
-
- COGL_TAILQ_FOREACH (entry, &onscreen->frame_info_callbacks, list_node)
- {
- if (entry->id == id)
- {
- COGL_TAILQ_REMOVE (&onscreen->frame_info_callbacks, entry, list_node);
- g_slice_free (CoglFrameInfoCallbackEntry, entry);
- break;
- }
- }
-}
-
-void
-_cogl_onscreen_notify_frame_info (CoglOnscreen *onscreen)
-{
- CoglFrameInfoCallbackEntry *entry, *tmp;
-
- COGL_TAILQ_FOREACH_SAFE (entry,
- &onscreen->frame_info_callbacks,
- list_node,
- tmp)
- entry->callback (onscreen, entry->user_data);
-}
-
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index e872b90..7954eb4 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -35,6 +35,7 @@
#include <cogl/cogl-context.h>
#include <cogl/cogl-framebuffer.h>
#include <cogl/cogl-frame-info.h>
+#include <cogl/cogl-object.h>
COGL_BEGIN_DECLS
@@ -333,6 +334,149 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles);
+/**
+ * CoglFrameEvent:
+ * @COGL_FRAME_EVENT_SYNC: Notifies that the system compositor has
+ * acknowledged a frame and is ready for a
+ * new frame to be created. Only delivered
+ * if the %COGL_FEATURE_ID_FRAME_SYNC
+ * 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
+ * mark the progression of a frame in some way which usually
+ * means that new information will have been accumulated in the
+ * frame's corresponding #CoglFrameInfo object.
+ *
+ * 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
+ */
+typedef enum _CoglFrameEvent
+{
+ COGL_FRAME_EVENT_SYNC = 1,
+ COGL_FRAME_EVENT_COMPLETE
+} CoglFrameEvent;
+
+/**
+ * CoglFrameCallback:
+ * @onscreen: The onscreen that the frame is associated with
+ * @event: A #CoglFrameEvent notifying how the frame has progressed
+ * @info: The meta information, such as timing information, about
+ * the frame that has progressed.
+ * @user_data: The user pointer passed to
+ * cogl_onscreen_add_frame_callback()
+ *
+ * Is a callback that can be registered via
+ * cogl_onscreen_add_frame_callback() to be called when a frame
+ * progresses in some notable way.
+ *
+ * Please see the documentation for #CoglFrameEvent and
+ * cogl_onscreen_add_frame_callback() for more details about what
+ * events can be notified.
+ *
+ * Since: 1.14
+ * Stability: unstable
+ */
+typedef void (*CoglFrameCallback) (CoglOnscreen *onscreen,
+ CoglFrameEvent event,
+ CoglFrameInfo *info,
+ void *user_data);
+
+/**
+ * CoglFrameClosure:
+ *
+ * An opaque type that tracks a #CoglFrameCallback and associated user
+ * data. A #CoglFrameClosure pointer will be returned from
+ * cogl_onscreen_add_frame_callback() and it allows you to remove a
+ * callback later using cogl_onscreen_remove_frame_callback().
+ *
+ * Since: 1.14
+ * Stability: unstable
+ */
+typedef struct _CoglFrameClosure CoglFrameClosure;
+
+/**
+ * cogl_onscreen_add_frame_callback:
+ * @onscreen: A #CoglOnscreen framebuffer
+ * @callback: A callback function to call for frame events
+ * @user_data: A private pointer to be passed to @callback
+ * @destroy: An optional callback to destroy @user_data when the
+ * @callback is removed or @onscreen is freed.
+ *
+ * Installs a @callback function that will be called for significant
+ * events relating to the given @onscreen framebuffer.
+ *
+ * If the %COGL_FEATURE_ID_FRAME_SYNC feature is supported
+ * then @callback will be used to notify when the system compositor is
+ * ready for this application to render a new frame. In this case
+ * %COGL_FRAME_EVENT_SYNC will be passed as the event argument to the
+ * given @callback in addition to the #CoglFrameInfo corresponding to
+ * the frame beeing acknowledged by the compositor.
+ *
+ * If the %COGL_FEATURE_ID_PRESENTATION_EVENTS is available then
+ * @callback will be called to notify when the frame has become
+ * visible to the user. In this case %COGL_FRAME_EVENT_PRESENTED will
+ * be passed as the event argument to the given @callback in addition
+ * to the #CoglFrameInfo corresponding to the newly presented frame.
+ *
+ * We recommend throttling your application according to
+ * %COGL_FRAME_EVENT_SYNC events whenever the
+ * %COGL_FEATURE_ID_FRAME_SYNC feature is available. This allows your
+ * application to avoid being blocked by the driver which will block
+ * your applications mainloop.
+ *
+ * <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>
+ *
+ * Return value: a #CoglFrameClosure pointer that can be used to
+ * remove the callback and associated @user_data later.
+ * Since: 1.14
+ * Stability: unstable
+ */
+CoglFrameClosure *
+cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen,
+ CoglFrameCallback callback,
+ void *user_data,
+ CoglUserDataDestroyCallback destroy);
+
+/**
+ * cogl_onscreen_remove_frame_callback:
+ * @onscreen: A #CoglOnscreen
+ * @closure: A #CoglFrameClosure returned from
+ * cogl_onscreen_add_frame_callback()
+ *
+ * Removes a callback and associated user data that were previously
+ * registered using cogl_onscreen_add_frame_callback().
+ *
+ * If a destroy callback was passed to
+ * cogl_onscreen_add_frame_callback() to destroy the user data then
+ * this will get called.
+ *
+ * Since: 1.14
+ * Stability: unstable
+ */
+void
+cogl_onscreen_remove_frame_callback (CoglOnscreen *onscreen,
+ CoglFrameClosure *closure);
typedef void (*CoglSwapBuffersNotify) (CoglFramebuffer *framebuffer,
void *user_data);
@@ -360,6 +504,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 +521,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,
@@ -594,62 +740,6 @@ CoglFrameInfo *
cogl_onscreen_get_frame_info (CoglOnscreen *onscreen,
int64_t frame_counter);
-/**
- * CoglFrameInfoCallback:
- * @onscreen: A #CoglOnscreen framebuffer that has updated timing information
- * @user_data: The private passed to
- * cogl_onscreen_add_frame_info_callback()
- *
- * Is a callback type used with the
- * cogl_onscreen_add_frame_info_callback() allowing applications to be
- * notified whenever new frame timings information is available
- * via cogl_onscreen_get_frame_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 (*CoglFrameInfoCallback) (CoglOnscreen *onscreen,
- void *user_data);
-
-/**
- * cogl_onscreen_add_frame_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_frame_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_frame_info_callback (CoglOnscreen *onscreen,
- CoglFrameInfoCallback callback,
- void *user_data);
-
-/**
- * cogl_onscreen_remove_frame_info_callback:
- * @onscreen: A #CoglOnscreen framebuffer
- * @id: An identifier returned from cogl_onscreen_add_frame_info_callback()
- *
- * Removes a callback that was previously registered
- * using cogl_onscreen_add_frame_info_callback().
- *
- * Since: 1.10
- * Stability: unstable
- */
-void
-cogl_onscreen_remove_frame_info_callback (CoglOnscreen *onscreen,
- unsigned int id);
-
COGL_END_DECLS
#endif /* __COGL_ONSCREEN_H */
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index ff538e2..498fb9d 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -753,6 +753,8 @@ _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->winsys_features,
COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT,
@@ -894,7 +896,13 @@ flush_pending_swap_notify_cb (void *data,
if (kms_onscreen->pending_swap_notify)
{
- _cogl_onscreen_notify_swap_buffers (onscreen);
+ int64_t frame_counter = cogl_onscreen_get_frame_counter (onscreen);
+ CoglFrameInfo *info = cogl_onscreen_get_frame_info (onscreen, frame_counter);
+
+ info->complete = TRUE;
+
+ _cogl_onscreen_notify_frame_sync (onscreen, info);
+ _cogl_onscreen_notify_complete (onscreen, info);
kms_onscreen->pending_swap_notify = FALSE;
}
}
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 75052a4..46e71e0 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -83,9 +83,9 @@ typedef struct _CoglOnscreenGLX
CoglOnscreenXlib _parent;
GLXDrawable glxwin;
uint32_t last_swap_vsync_counter;
- CoglBool pending_swap_notify;
+ CoglBool pending_sync_notify;
+ CoglBool pending_complete_notify;
CoglBool pending_resize_notify;
- CoglBool pending_frame_info_notify;
} CoglOnscreenGLX;
typedef struct _CoglTexturePixmapGLX
@@ -282,13 +282,13 @@ 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);
+ int64_t frame_counter = cogl_onscreen_get_frame_counter (onscreen);
CoglFrameInfo *info = cogl_onscreen_get_frame_info (onscreen, frame_counter);
info->complete = TRUE;
- glx_display->pending_frame_info_notify = TRUE;
- glx_onscreen->pending_frame_info_notify = TRUE;
+ glx_display->pending_complete_notify = TRUE;
+ glx_onscreen->pending_complete_notify = TRUE;
}
static void
@@ -298,8 +298,6 @@ notify_swap_buffers (CoglContext *context, GLXBufferSwapComplete *swap_event)
CoglDisplay *display = context->display;
CoglGLXDisplay *glx_display = display->winsys;
CoglOnscreenGLX *glx_onscreen;
- int frame_counter;
- CoglFrameInfo *info;
if (!onscreen)
return;
@@ -308,15 +306,19 @@ notify_swap_buffers (CoglContext *context, GLXBufferSwapComplete *swap_event)
/* We only want to notify that the swap is complete when the
application calls cogl_context_dispatch so instead of immediately
notifying we'll set a flag to remember to notify later */
- glx_display->pending_swap_notify = TRUE;
- glx_onscreen->pending_swap_notify = TRUE;
+ glx_display->pending_sync_notify = TRUE;
+ glx_onscreen->pending_sync_notify = TRUE;
- frame_counter = cogl_onscreen_get_frame_counter (onscreen);
- info = cogl_onscreen_get_frame_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);
+ {
+ int64_t frame_counter = cogl_onscreen_get_frame_counter (onscreen);
+ CoglFrameInfo *info = cogl_onscreen_get_frame_info (onscreen, frame_counter);
+
+ info->presentation_time =
+ ust_to_monotonic_time (context->display->renderer,
+ glx_onscreen->glxwin,
+ swap_event->ust);
+ }
set_info_complete (onscreen);
}
@@ -700,9 +702,17 @@ update_winsys_features (CoglContext *context, CoglError **error)
COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
- COGL_FLAGS_SET (context->features,
- COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
- TRUE);
+ {
+ 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_TIME,
+ TRUE);
+ }
return TRUE;
}
@@ -1407,11 +1417,8 @@ _cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen)
if (glx_renderer->glXWaitForMsc ||
glx_renderer->glXGetVideoSync)
{
- int frame_counter;
- CoglFrameInfo *info;
-
- frame_counter = cogl_onscreen_get_frame_counter (onscreen);
- info = cogl_onscreen_get_frame_info (onscreen, frame_counter);
+ int64_t frame_counter = cogl_onscreen_get_frame_counter (onscreen);
+ CoglFrameInfo *info = cogl_onscreen_get_frame_info (onscreen, frame_counter);
if (glx_renderer->glXWaitForMsc)
{
@@ -1463,9 +1470,8 @@ set_refresh_rate_from_output (CoglOnscreen *onscreen,
float refresh_rate = cogl_output_get_refresh_rate (output);
if (refresh_rate != 0.0)
{
- int frame_counter = cogl_onscreen_get_frame_counter (onscreen);
+ int64_t frame_counter = cogl_onscreen_get_frame_counter (onscreen);
CoglFrameInfo *info = cogl_onscreen_get_frame_info (onscreen, frame_counter);
-
info->refresh_rate = refresh_rate;
}
}
@@ -2419,9 +2425,9 @@ _cogl_winsys_poll_get_info (CoglContext *context,
/* If we've already got a pending swap notify then we'll dispatch
immediately */
- if (glx_display->pending_swap_notify ||
+ if (glx_display->pending_sync_notify ||
glx_display->pending_resize_notify ||
- glx_display->pending_frame_info_notify)
+ glx_display->pending_complete_notify)
*timeout = 0;
}
@@ -2436,22 +2442,26 @@ flush_pending_notifications_cb (void *data,
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
- if (glx_onscreen->pending_swap_notify)
+ if (glx_onscreen->pending_sync_notify)
{
- _cogl_onscreen_notify_swap_buffers (onscreen);
- glx_onscreen->pending_swap_notify = FALSE;
+ int64_t frame_counter = cogl_onscreen_get_frame_counter (onscreen);
+ CoglFrameInfo *info = cogl_onscreen_get_frame_info (onscreen, frame_counter);
+ _cogl_onscreen_notify_frame_sync (onscreen, info);
+ glx_onscreen->pending_sync_notify = FALSE;
}
- if (glx_onscreen->pending_resize_notify)
+ if (glx_onscreen->pending_complete_notify)
{
- _cogl_onscreen_notify_resize (onscreen);
- glx_onscreen->pending_resize_notify = FALSE;
+ int64_t frame_counter = cogl_onscreen_get_frame_counter (onscreen);
+ CoglFrameInfo *info = cogl_onscreen_get_frame_info (onscreen, frame_counter);
+ _cogl_onscreen_notify_complete (onscreen, info);
+ glx_onscreen->pending_complete_notify = FALSE;
}
- if (glx_onscreen->pending_frame_info_notify)
+ if (glx_onscreen->pending_resize_notify)
{
- _cogl_onscreen_notify_frame_info (onscreen);
- glx_onscreen->pending_frame_info_notify = FALSE;
+ _cogl_onscreen_notify_resize (onscreen);
+ glx_onscreen->pending_resize_notify = FALSE;
}
}
}
@@ -2468,16 +2478,16 @@ _cogl_winsys_poll_dispatch (CoglContext *context,
poll_fds,
n_poll_fds);
- if (glx_display->pending_swap_notify ||
+ if (glx_display->pending_sync_notify ||
glx_display->pending_resize_notify ||
- glx_display->pending_frame_info_notify)
+ glx_display->pending_complete_notify)
{
g_list_foreach (context->framebuffers,
flush_pending_notifications_cb,
NULL);
- glx_display->pending_swap_notify = FALSE;
+ glx_display->pending_sync_notify = FALSE;
glx_display->pending_resize_notify = FALSE;
- glx_display->pending_frame_info_notify = FALSE;
+ glx_display->pending_complete_notify = FALSE;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]