[Cogl] [PATCH 2/2] Update some of the examples to use the expose callback

Neil Roberts neil at linux.intel.com
Tue May 14 06:34:47 PDT 2013


This updates Cogland and the three hello examples to use the expose
callback. For Cogland, this removes the manual handling of X events
and for the other examples it removes the need to redraw continously.
---
 examples/cogl-hello.c      | 49 ++++++++++++++++++------
 examples/cogl-sdl-hello.c  | 20 +++++++---
 examples/cogl-sdl2-hello.c | 20 +++++++---
 examples/cogland.c         | 93 ++++++++--------------------------------------
 4 files changed, 83 insertions(+), 99 deletions(-)

diff --git a/examples/cogl-hello.c b/examples/cogl-hello.c
index 3ba1e31..36f43b1 100644
--- a/examples/cogl-hello.c
+++ b/examples/cogl-hello.c
@@ -8,18 +8,24 @@ typedef struct _Data
     CoglFramebuffer *fb;
     CoglPrimitive *triangle;
     CoglPipeline *pipeline;
+
+    CoglBool redraw_queued;
+    CoglBool draw_ready;
 } Data;
 
-static CoglBool
-paint_cb (void *user_data)
+static void
+maybe_redraw (Data *data)
 {
-    Data *data = user_data;
-
-    cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
-    cogl_framebuffer_draw_primitive (data->fb, data->pipeline, data->triangle);
-    cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb));
+    if (data->redraw_queued && data->draw_ready) {
+        data->redraw_queued = FALSE;
+        data->draw_ready = FALSE;
 
-    return FALSE; /* remove the callback */
+        cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
+        cogl_framebuffer_draw_primitive (data->fb,
+                                         data->pipeline,
+                                         data->triangle);
+        cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb));
+    }
 }
 
 static void
@@ -28,8 +34,23 @@ frame_event_cb (CoglOnscreen *onscreen,
                 CoglFrameInfo *info,
                 void *user_data)
 {
-    if (event == COGL_FRAME_EVENT_SYNC)
-        paint_cb (user_data);
+    Data *data = user_data;
+
+    if (event == COGL_FRAME_EVENT_SYNC) {
+        data->draw_ready = TRUE;
+        maybe_redraw (data);
+    }
+}
+
+static void
+expose_cb (CoglOnscreen *onscreen,
+           const CoglOnscreenExposeInfo *info,
+           void *user_data)
+{
+    Data *data = user_data;
+
+    data->redraw_queued = TRUE;
+    maybe_redraw (data);
 }
 
 int
@@ -46,6 +67,9 @@ main (int argc, char **argv)
     GSource *cogl_source;
     GMainLoop *loop;
 
+    data.redraw_queued = FALSE;
+    data.draw_ready = TRUE;
+
     data.ctx = cogl_context_new (NULL, &error);
     if (!data.ctx) {
         fprintf (stderr, "Failed to create context: %s\n", error->message);
@@ -71,7 +95,10 @@ main (int argc, char **argv)
                                       frame_event_cb,
                                       &data,
                                       NULL); /* destroy notify */
-    g_idle_add (paint_cb, &data);
+    cogl_onscreen_add_expose_callback (COGL_ONSCREEN (data.fb),
+                                       expose_cb,
+                                       &data,
+                                       NULL); /* destroy notify */
 
     loop = g_main_loop_new (NULL, TRUE);
     g_main_loop_run (loop);
diff --git a/examples/cogl-sdl-hello.c b/examples/cogl-sdl-hello.c
index acb9125..f2ebaa7 100644
--- a/examples/cogl-sdl-hello.c
+++ b/examples/cogl-sdl-hello.c
@@ -33,14 +33,20 @@ redraw (Data *data)
 }
 
 static void
+expose_cb (CoglOnscreen *onscreen,
+           const CoglOnscreenExposeInfo *info,
+           void *user_data)
+{
+  Data *data = user_data;
+
+  data->redraw_queued = TRUE;
+}
+
+static void
 handle_event (Data *data, SDL_Event *event)
 {
   switch (event->type)
     {
-    case SDL_VIDEOEXPOSE:
-      data->redraw_queued = TRUE;
-      break;
-
     case SDL_MOUSEMOTION:
       {
         int width =
@@ -101,6 +107,10 @@ main (int argc, char **argv)
                                     frame_cb,
                                     &data,
                                     NULL /* destroy callback */);
+  cogl_onscreen_add_expose_callback (onscreen,
+                                     expose_cb,
+                                     &data,
+                                     NULL /* destroy callback */);
 
   data.center_x = 0.0f;
   data.center_y = 0.0f;
@@ -112,7 +122,7 @@ main (int argc, char **argv)
                                            3, triangle_vertices);
   data.pipeline = cogl_pipeline_new (ctx);
 
-  data.redraw_queued = TRUE;
+  data.redraw_queued = FALSE;
   data.ready_to_draw = TRUE;
 
   while (!data.quit)
diff --git a/examples/cogl-sdl2-hello.c b/examples/cogl-sdl2-hello.c
index 12e6ced..c2f0ea0 100644
--- a/examples/cogl-sdl2-hello.c
+++ b/examples/cogl-sdl2-hello.c
@@ -33,6 +33,16 @@ redraw (Data *data)
 }
 
 static void
+expose_cb (CoglOnscreen *onscreen,
+           const CoglOnscreenExposeInfo *info,
+           void *user_data)
+{
+  Data *data = user_data;
+
+  data->redraw_queued = TRUE;
+}
+
+static void
 handle_event (Data *data, SDL_Event *event)
 {
   switch (event->type)
@@ -40,10 +50,6 @@ handle_event (Data *data, SDL_Event *event)
     case SDL_WINDOWEVENT:
       switch (event->window.event)
         {
-        case SDL_WINDOWEVENT_EXPOSED:
-          data->redraw_queued = TRUE;
-          break;
-
         case SDL_WINDOWEVENT_CLOSE:
           data->quit = TRUE;
           break;
@@ -110,6 +116,10 @@ main (int argc, char **argv)
                                     frame_cb,
                                     &data,
                                     NULL /* destroy callback */);
+  cogl_onscreen_add_expose_callback (onscreen,
+                                     expose_cb,
+                                     &data,
+                                     NULL /* destroy callback */);
 
   data.center_x = 0.0f;
   data.center_y = 0.0f;
@@ -125,7 +135,7 @@ main (int argc, char **argv)
                                            3, triangle_vertices);
   data.pipeline = cogl_pipeline_new (ctx);
 
-  data.redraw_queued = TRUE;
+  data.redraw_queued = FALSE;
   data.ready_to_draw = TRUE;
 
   while (!data.quit)
diff --git a/examples/cogland.c b/examples/cogland.c
index 928a735..eb4e10c 100644
--- a/examples/cogland.c
+++ b/examples/cogland.c
@@ -8,10 +8,6 @@
 
 #include <wayland-server.h>
 
-#ifdef COGL_HAS_XLIB_SUPPORT
-#include <cogl/cogl-xlib.h>
-#endif
-
 typedef struct _CoglandCompositor CoglandCompositor;
 
 typedef struct
@@ -782,6 +778,16 @@ bind_output (struct wl_client *client,
 }
 
 static void
+expose_cb (CoglOnscreen *onscreen,
+           const CoglOnscreenExposeInfo *info,
+           void *user_data)
+{
+  CoglandCompositor *compositor = user_data;
+
+  cogland_queue_redraw (compositor);
+}
+
+static void
 cogland_compositor_create_output (CoglandCompositor *compositor,
                                   int x,
                                   int y,
@@ -813,6 +819,11 @@ cogland_compositor_create_output (CoglandCompositor *compositor,
   if (!cogl_framebuffer_allocate (fb, &error))
     g_error ("Failed to allocate framebuffer: %s\n", error->message);
 
+  cogl_onscreen_add_expose_callback (output->onscreen,
+                                     expose_cb,
+                                     compositor,
+                                     NULL /* destroy */);
+
   cogl_onscreen_show (output->onscreen);
   cogl_framebuffer_set_viewport (fb,
                                  -x, -y,
@@ -1051,78 +1062,6 @@ create_cogl_context (CoglandCompositor *compositor,
   return context;
 }
 
-#ifdef COGL_HAS_XLIB_SUPPORT
-
-static CoglFilterReturn
-x_event_cb (XEvent *event,
-            void *data)
-{
-  CoglandCompositor *compositor = data;
-
-  if (event->type == Expose)
-    cogland_queue_redraw (compositor);
-
-  return COGL_FILTER_CONTINUE;
-}
-
-#endif /* COGL_HAS_XLIB_SUPPORT */
-
-static gboolean
-timeout_cb (void *data)
-{
-  cogland_queue_redraw (data);
-
-  return TRUE;
-}
-
-static void
-init_redraws (CoglandCompositor *compositor)
-{
-#ifdef COGL_HAS_XLIB_SUPPORT
-  CoglRenderer *renderer = cogl_context_get_renderer (compositor->cogl_context);
-  CoglWinsysID winsys = cogl_renderer_get_winsys_id (renderer);
-
-  /* If Cogl is using X then we can listen for Expose events to know
-   * when to repaint the window. Otherwise we don't have any code to
-   * know when the contents of the window is dirty so we'll just
-   * redraw constantly */
-  switch (winsys)
-    {
-    case COGL_WINSYS_ID_GLX:
-    case COGL_WINSYS_ID_EGL_XLIB:
-      {
-        Display *display = cogl_xlib_renderer_get_display (renderer);
-        GList *l;
-
-        for (l = compositor->outputs; l; l = l->next)
-          {
-            CoglandOutput *output = l->data;
-            XWindowAttributes win_attribs;
-            Window win;
-
-            win = cogl_x11_onscreen_get_window_xid (output->onscreen);
-            if (XGetWindowAttributes (display, win, &win_attribs))
-              {
-                XSelectInput (display,
-                              win,
-                              win_attribs.your_event_mask | ExposureMask);
-                cogl_xlib_renderer_add_filter (renderer,
-                                               x_event_cb,
-                                               compositor);
-
-              }
-          }
-      }
-      return;
-
-    default:
-      break;
-    }
-#endif /* COGL_HAS_XLIB_SUPPORT */
-
-  g_timeout_add (16, timeout_cb, compositor);
-}
-
 int
 main (int argc, char **argv)
 {
@@ -1229,8 +1168,6 @@ main (int argc, char **argv)
 
   g_source_attach (cogl_source, NULL);
 
-  init_redraws (&compositor);
-
   g_main_loop_run (loop);
 
   return 0;
-- 
1.7.11.3.g3c3efa5



More information about the Cogl mailing list