onscreen: Make the resize callback work the same as the frame callback

When adding the frame callback API in 70040166 we decided on a common
idiom for adding callbacks which would return an opaque pointer
representing the closure for the callback. This pointer can then be
used to later remove the callback. The closure can also contain an
optional callback to invoke when the user data parameter is destroyed.
The resize callback didn't work this way and instead had an integer
handle to identify the closure. This patch changes it to work the same
way as the frame callback.

Reviewed-by: Robert Bragg <robert@linux.intel.com>

(cherry picked from commit 33164c4b04d253ebe0ff41b12c1e90232c519274)
This commit is contained in:
Neil Roberts 2013-04-04 20:25:42 +01:00 committed by Robert Bragg
parent b01e0e6a48
commit 816a5bc437
5 changed files with 81 additions and 69 deletions

View File

@ -46,17 +46,16 @@ struct _CoglFrameClosure
CoglUserDataDestroyCallback destroy;
};
typedef struct _CoglResizeNotifyEntry CoglResizeNotifyEntry;
COGL_TAILQ_HEAD (CoglOnscreenResizeCallbackList, CoglOnscreenResizeClosure);
COGL_TAILQ_HEAD (CoglResizeNotifyList, CoglResizeNotifyEntry);
struct _CoglResizeNotifyEntry
struct _CoglOnscreenResizeClosure
{
COGL_TAILQ_ENTRY (CoglResizeNotifyEntry) list_node;
COGL_TAILQ_ENTRY (CoglOnscreenResizeClosure) list_node;
CoglOnscreenResizeCallback callback;
void *user_data;
unsigned int id;
CoglUserDataDestroyCallback destroy;
};
typedef struct _CoglOnscreenEvent CoglOnscreenEvent;
@ -95,7 +94,7 @@ struct _CoglOnscreen
CoglFrameCallbackList frame_closures;
CoglBool resizable;
CoglResizeNotifyList resize_callbacks;
CoglOnscreenResizeCallbackList resize_closures;
int64_t frame_counter;
int64_t swap_frame_counter; /* frame counter at last all to

View File

@ -47,7 +47,7 @@ _cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
COGL_TAILQ_INIT (&onscreen->frame_closures);
COGL_TAILQ_INIT (&onscreen->resize_callbacks);
COGL_TAILQ_INIT (&onscreen->resize_closures);
framebuffer->config = onscreen_template->config;
cogl_object_ref (framebuffer->config.swap_chain);
@ -115,24 +115,20 @@ _cogl_onscreen_free (CoglOnscreen *onscreen)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
CoglResizeNotifyEntry *resize_entry;
CoglFrameClosure *frame_closure;
CoglFrameInfo *frame_info;
while ((resize_entry = COGL_TAILQ_FIRST (&onscreen->resize_callbacks)))
while (!COGL_TAILQ_EMPTY (&onscreen->resize_closures))
{
COGL_TAILQ_REMOVE (&onscreen->resize_callbacks, resize_entry, list_node);
g_slice_free (CoglResizeNotifyEntry, resize_entry);
CoglOnscreenResizeClosure *resize_closure =
COGL_TAILQ_FIRST (&onscreen->resize_closures);
cogl_onscreen_remove_resize_callback (onscreen, resize_closure);
}
while ((frame_closure = COGL_TAILQ_FIRST (&onscreen->frame_closures)))
while (!COGL_TAILQ_EMPTY (&onscreen->frame_closures))
{
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);
CoglFrameClosure *frame_closure =
COGL_TAILQ_FIRST (&onscreen->frame_closures);
cogl_onscreen_remove_frame_callback (onscreen, frame_closure);
}
while ((frame_info = g_queue_pop_tail (&onscreen->pending_frame_infos)))
@ -566,17 +562,17 @@ _cogl_onscreen_notify_complete (CoglOnscreen *onscreen, CoglFrameInfo *info)
void
_cogl_onscreen_notify_resize (CoglOnscreen *onscreen)
{
CoglResizeNotifyEntry *entry, *tmp;
CoglOnscreenResizeClosure *closure, *tmp;
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
COGL_TAILQ_FOREACH_SAFE (entry,
&onscreen->resize_callbacks,
COGL_TAILQ_FOREACH_SAFE (closure,
&onscreen->resize_closures,
list_node,
tmp)
entry->callback (onscreen,
framebuffer->width,
framebuffer->height,
entry->user_data);
closure->callback (onscreen,
framebuffer->width,
framebuffer->height,
closure->user_data);
}
void
@ -620,38 +616,33 @@ cogl_onscreen_get_resizable (CoglOnscreen *onscreen)
return onscreen->resizable;
}
unsigned int
cogl_onscreen_add_resize_handler (CoglOnscreen *onscreen,
CoglOnscreenResizeCallback callback,
void *user_data)
CoglOnscreenResizeClosure *
cogl_onscreen_add_resize_callback (CoglOnscreen *onscreen,
CoglOnscreenResizeCallback callback,
void *user_data,
CoglUserDataDestroyCallback destroy)
{
CoglResizeNotifyEntry *entry = g_slice_new (CoglResizeNotifyEntry);
static int next_resize_callback_id = 0;
CoglOnscreenResizeClosure *closure = g_slice_new (CoglOnscreenResizeClosure);
entry->callback = callback;
entry->user_data = user_data;
entry->id = next_resize_callback_id++;
closure->callback = callback;
closure->user_data = user_data;
closure->destroy = destroy;
COGL_TAILQ_INSERT_TAIL (&onscreen->resize_callbacks, entry, list_node);
COGL_TAILQ_INSERT_TAIL (&onscreen->resize_closures, closure, list_node);
return entry->id;
return closure;
}
void
cogl_onscreen_remove_resize_handler (CoglOnscreen *onscreen,
unsigned int id)
cogl_onscreen_remove_resize_callback (CoglOnscreen *onscreen,
CoglOnscreenResizeClosure *closure)
{
CoglResizeNotifyEntry *entry;
if (closure->destroy)
closure->destroy (closure->user_data);
COGL_TAILQ_FOREACH (entry, &onscreen->resize_callbacks, list_node)
{
if (entry->id == id)
{
COGL_TAILQ_REMOVE (&onscreen->resize_callbacks, entry, list_node);
g_slice_free (CoglResizeNotifyEntry, entry);
break;
}
}
COGL_TAILQ_REMOVE (&onscreen->resize_closures, closure, list_node);
g_slice_free (CoglOnscreenResizeClosure, closure);
}
int64_t

View File

@ -614,7 +614,7 @@ cogl_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
* will be automatically updated to match the new size of the
* framebuffer with an origin of (0,0). If your application needs more
* specialized control of the viewport it will need to register a
* resize handler using cogl_onscreen_add_resize_handler() so that it
* resize handler using cogl_onscreen_add_resize_callback() so that it
* can track when the viewport has been changed automatically.</note>
*
* Since: 2.0
@ -655,10 +655,10 @@ cogl_onscreen_get_resizable (CoglOnscreen *onscreen);
* @width: The new width of @onscreen
* @height: The new height of @onscreen
* @user_data: The private passed to
* cogl_onscreen_add_resize_handler()
* cogl_onscreen_add_resize_callback()
*
* Is a callback type used with the
* cogl_onscreen_add_resize_handler() allowing applications to be
* cogl_onscreen_add_resize_callback() allowing applications to be
* notified whenever an @onscreen framebuffer is resized.
*
* <note>Cogl automatically updates the viewport of an @onscreen
@ -679,18 +679,34 @@ typedef void (*CoglOnscreenResizeCallback) (CoglOnscreen *onscreen,
void *user_data);
/**
* cogl_onscreen_add_resize_handler:
* CoglOnscreenResizeClosure:
*
* An opaque type that tracks a #CoglOnscreenResizeCallback and
* associated user data. A #CoglOnscreenResizeClosure pointer will be
* returned from cogl_onscreen_add_resize_callback() and it allows you
* to remove a callback later using
* cogl_onscreen_remove_resize_callback().
*
* Since: 2.0
* Stability: unstable
*/
typedef struct _CoglOnscreenResizeClosure CoglOnscreenResizeClosure;
/**
* cogl_onscreen_add_resize_callback:
* @onscreen: A #CoglOnscreen framebuffer
* @callback: A #CoglOnscreenResizeCallback to call when the @onscreen
* changes size.
* @user_data: Private data to be passed to @callback.
* @destroy: An optional callback to destroy @user_data when the
* @callback is removed or @onscreen is freed.
*
* Registers a @callback with @onscreen that will be called whenever
* the @onscreen framebuffer changes size.
*
* The @callback can be removed using
* cogl_onscreen_remove_resize_handler() passing the same @callback
* and @user_data pair.
* cogl_onscreen_remove_resize_callback() passing the returned closure
* pointer.
*
* <note>Since Cogl automatically updates the viewport of an @onscreen
* framebuffer that is resized, a resize callback can also be used to
@ -704,29 +720,29 @@ typedef void (*CoglOnscreenResizeCallback) (CoglOnscreen *onscreen,
* while an application might have arbitrary locks held for
* example.</note>
*
* Return value: a unique identifier that can be used to remove to remove
* the callback later.
*
* Return value: a #CoglOnscreenResizeClosure pointer that can be used to
* remove the callback and associated @user_data later.
* Since: 2.0
*/
unsigned int
cogl_onscreen_add_resize_handler (CoglOnscreen *onscreen,
CoglOnscreenResizeCallback callback,
void *user_data);
CoglOnscreenResizeClosure *
cogl_onscreen_add_resize_callback (CoglOnscreen *onscreen,
CoglOnscreenResizeCallback callback,
void *user_data,
CoglUserDataDestroyCallback destroy);
/**
* cogl_onscreen_remove_resize_handler:
* cogl_onscreen_remove_resize_callback:
* @onscreen: A #CoglOnscreen framebuffer
* @id: An identifier returned from cogl_onscreen_add_resize_handler()
* @closure: An identifier returned from cogl_onscreen_add_resize_callback()
*
* Removes a resize @callback and @user_data pair that were previously
* associated with @onscreen via cogl_onscreen_add_resize_handler().
* associated with @onscreen via cogl_onscreen_add_resize_callback().
*
* Since: 2.0
*/
void
cogl_onscreen_remove_resize_handler (CoglOnscreen *onscreen,
unsigned int id);
cogl_onscreen_remove_resize_callback (CoglOnscreen *onscreen,
CoglOnscreenResizeClosure *closure);
/**
* cogl_is_onscreen:

View File

@ -609,6 +609,12 @@ CoglFrameClosure
cogl_onscreen_add_frame_callback
cogl_onscreen_remove_frame_callback
<SUBSECTION>
CoglOnscreenResizeCallback
CoglOnscreenResizeClosure
cogl_onscreen_add_resize_callback
cogl_onscreen_remove_resize_callback
<SUBSECTION>
cogl_onscreen_swap_buffers
cogl_onscreen_swap_region

View File

@ -160,7 +160,7 @@ main (int argc, char **argv)
fb = COGL_FRAMEBUFFER (onscreen);
cogl_onscreen_set_resizable (onscreen, TRUE);
cogl_onscreen_add_resize_handler (onscreen, resize_handler, onscreen);
cogl_onscreen_add_resize_callback (onscreen, resize_handler, onscreen, NULL);
triangle = cogl_primitive_new_p2c4 (ctx, COGL_VERTICES_MODE_TRIANGLES,
3, triangle_vertices);