[Cogl] [PATCH] onscreen: Make the resize callback work the same as the frame callback

Neil Roberts neil at linux.intel.com
Thu Apr 4 12:41:25 PDT 2013


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.
---
 cogl/cogl-onscreen-private.h           | 13 +++---
 cogl/cogl-onscreen.c                   | 77 +++++++++++++++-------------------
 cogl/cogl-onscreen.h                   | 52 +++++++++++++++--------
 doc/reference/cogl2/cogl2-sections.txt |  6 +++
 examples/cogl-x11-foreign.c            |  2 +-
 5 files changed, 81 insertions(+), 69 deletions(-)

diff --git a/cogl/cogl-onscreen-private.h b/cogl/cogl-onscreen-private.h
index 89efb0e..f40c515 100644
--- a/cogl/cogl-onscreen-private.h
+++ b/cogl/cogl-onscreen-private.h
@@ -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;
@@ -91,7 +90,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
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index e79bf22..338f747 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -46,7 +46,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);
@@ -86,24 +86,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)))
@@ -460,17 +456,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
@@ -514,38 +510,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
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index 13b51a1..ed4e25c 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -567,7 +567,7 @@ cogl_onscreen_remove_frame_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
@@ -608,10 +608,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
@@ -632,18 +632,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
@@ -657,29 +673,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:
diff --git a/doc/reference/cogl2/cogl2-sections.txt b/doc/reference/cogl2/cogl2-sections.txt
index d75fa3f..e160a74 100644
--- a/doc/reference/cogl2/cogl2-sections.txt
+++ b/doc/reference/cogl2/cogl2-sections.txt
@@ -554,6 +554,12 @@ 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
 cogl_onscreen_set_swap_throttled
diff --git a/examples/cogl-x11-foreign.c b/examples/cogl-x11-foreign.c
index ca9e3ed..849646c 100644
--- a/examples/cogl-x11-foreign.c
+++ b/examples/cogl-x11-foreign.c
@@ -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);
-- 
1.7.11.3.g3c3efa5



More information about the Cogl mailing list