[Cogl] [PATCH 2/3] cogland: Don't redraw constantly

Neil Roberts neil at linux.intel.com
Fri Mar 22 07:47:48 PDT 2013


Instead of always drawing at 60FPS without ever going idle, Cogland
now only redraws when a client commits a frame or a surface is
destroyed. This is acheived using an idle handler on the glib main
loop.
---
 examples/cogland.c | 135 +++++++++++++++++++++++++++++------------------------
 1 file changed, 75 insertions(+), 60 deletions(-)

diff --git a/examples/cogland.c b/examples/cogland.c
index 98e0efe..45de95a 100644
--- a/examples/cogland.c
+++ b/examples/cogland.c
@@ -108,6 +108,8 @@ struct _CoglandCompositor
   GSource *wayland_event_source;
 
   GList *surfaces;
+
+  unsigned int redraw_idle;
 };
 
 static CoglBool option_multiple_outputs = FALSE;
@@ -264,6 +266,73 @@ wayland_event_source_new (struct wl_display *display)
   return &source->source;
 }
 
+typedef struct _CoglandFrameCallback
+{
+  struct wl_list link;
+
+  /* Pointer back to the compositor */
+  CoglandCompositor *compositor;
+
+  struct wl_resource resource;
+} CoglandFrameCallback;
+
+static CoglBool
+paint_cb (void *user_data)
+{
+  CoglandCompositor *compositor = user_data;
+  GList *l;
+
+  for (l = compositor->outputs; l; l = l->next)
+    {
+      CoglandOutput *output = l->data;
+      CoglFramebuffer *fb = COGL_FRAMEBUFFER (output->onscreen);
+      GList *l2;
+
+      cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
+
+      cogl_framebuffer_draw_primitive (fb, compositor->triangle_pipeline,
+                                       compositor->triangle);
+
+      for (l2 = compositor->surfaces; l2; l2 = l2->next)
+        {
+          CoglandSurface *surface = l2->data;
+
+          if (surface->texture)
+            {
+              CoglTexture2D *texture = surface->texture;
+              CoglPipeline *pipeline =
+                cogl_pipeline_new (compositor->cogl_context);
+              cogl_pipeline_set_layer_texture (pipeline, 0,
+                                               COGL_TEXTURE (texture));
+              cogl_framebuffer_draw_rectangle (fb, pipeline, -1, 1, 1, -1);
+              cogl_object_unref (pipeline);
+            }
+        }
+      cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
+    }
+
+  while (!wl_list_empty (&compositor->frame_callbacks))
+    {
+      CoglandFrameCallback *callback =
+        wl_container_of (compositor->frame_callbacks.next, callback, link);
+
+      wl_resource_post_event (&callback->resource,
+                              WL_CALLBACK_DONE, get_time ());
+      wl_resource_destroy (&callback->resource);
+    }
+
+  compositor->redraw_idle = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+cogland_queue_redraw (CoglandCompositor *compositor)
+{
+  if (compositor->redraw_idle == 0)
+    compositor->redraw_idle = g_idle_add (paint_cb, compositor);
+}
+
 static void
 shm_buffer_damaged (CoglandSurface *surface,
                     int32_t x,
@@ -335,6 +404,8 @@ cogland_surface_detach_buffer (CoglandSurface *surface)
           cogl_object_unref (surface->texture);
           surface->texture = NULL;
         }
+
+      cogland_queue_redraw (surface->compositor);
     }
 }
 
@@ -399,16 +470,6 @@ cogland_surface_damage (struct wl_client *client,
   region_add (&surface->pending.damage, x, y, width, height);
 }
 
-typedef struct _CoglandFrameCallback
-{
-  struct wl_list link;
-
-  /* Pointer back to the compositor */
-  CoglandCompositor *compositor;
-
-  struct wl_resource resource;
-} CoglandFrameCallback;
-
 static void
 destroy_frame_callback (struct wl_resource *callback_resource)
 {
@@ -520,6 +581,8 @@ cogland_surface_commit (struct wl_client *client,
   wl_list_insert_list (&compositor->frame_callbacks,
                        &surface->pending.frame_callback_list);
   wl_list_init (&surface->pending.frame_callback_list);
+
+  cogland_queue_redraw (compositor);
 }
 
 static void
@@ -752,54 +815,6 @@ cogland_compositor_create_output (CoglandCompositor *compositor,
   compositor->outputs = g_list_prepend (compositor->outputs, output);
 }
 
-static CoglBool
-paint_cb (void *user_data)
-{
-  CoglandCompositor *compositor = user_data;
-  GList *l;
-
-  for (l = compositor->outputs; l; l = l->next)
-    {
-      CoglandOutput *output = l->data;
-      CoglFramebuffer *fb = COGL_FRAMEBUFFER (output->onscreen);
-      GList *l2;
-
-      cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
-
-      cogl_framebuffer_draw_primitive (fb, compositor->triangle_pipeline,
-                                       compositor->triangle);
-
-      for (l2 = compositor->surfaces; l2; l2 = l2->next)
-        {
-          CoglandSurface *surface = l2->data;
-
-          if (surface->texture)
-            {
-              CoglTexture2D *texture = surface->texture;
-              CoglPipeline *pipeline =
-                cogl_pipeline_new (compositor->cogl_context);
-              cogl_pipeline_set_layer_texture (pipeline, 0,
-                                               COGL_TEXTURE (texture));
-              cogl_framebuffer_draw_rectangle (fb, pipeline, -1, 1, 1, -1);
-              cogl_object_unref (pipeline);
-            }
-        }
-      cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
-    }
-
-  while (!wl_list_empty (&compositor->frame_callbacks))
-    {
-      CoglandFrameCallback *callback =
-        wl_container_of (compositor->frame_callbacks.next, callback, link);
-
-      wl_resource_post_event (&callback->resource,
-                              WL_CALLBACK_DONE, get_time ());
-      wl_resource_destroy (&callback->resource);
-    }
-
-  return TRUE;
-}
-
 const static struct wl_compositor_interface cogland_compositor_interface =
 {
   cogland_compositor_create_surface,
@@ -1074,13 +1089,13 @@ main (int argc, char **argv)
                                                  3, triangle_vertices);
   compositor.triangle_pipeline = cogl_pipeline_new (compositor.cogl_context);
 
-  g_timeout_add (16, paint_cb, &compositor);
-
   cogl_source = cogl_glib_source_new (compositor.cogl_context,
                                       G_PRIORITY_DEFAULT);
 
   g_source_attach (cogl_source, NULL);
 
+  cogland_queue_redraw (&compositor);
+
   g_main_loop_run (loop);
 
   return 0;
-- 
1.7.11.3.g3c3efa5



More information about the Cogl mailing list