[Cogl] [PATCH 3/3] Update some of the examples to use the dirty callback
Neil Roberts
neil at linux.intel.com
Tue May 14 09:03:31 PDT 2013
This updates Cogland and the three hello examples to use the dirty
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 | 55 ++++++++++++++++++++++++---
examples/cogl-sdl-hello.c | 20 +++++++---
examples/cogl-sdl2-hello.c | 20 +++++++---
examples/cogland.c | 93 ++++++++--------------------------------------
4 files changed, 94 insertions(+), 94 deletions(-)
diff --git a/examples/cogl-hello.c b/examples/cogl-hello.c
index 3ba1e31..49f9336 100644
--- a/examples/cogl-hello.c
+++ b/examples/cogl-hello.c
@@ -8,18 +8,39 @@ typedef struct _Data
CoglFramebuffer *fb;
CoglPrimitive *triangle;
CoglPipeline *pipeline;
+
+ unsigned int redraw_idle;
+ CoglBool is_dirty;
+ CoglBool draw_ready;
} Data;
-static CoglBool
+static gboolean
paint_cb (void *user_data)
{
Data *data = user_data;
+ data->redraw_idle = 0;
+ data->is_dirty = FALSE;
+ data->draw_ready = FALSE;
+
cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
- cogl_framebuffer_draw_primitive (data->fb, data->pipeline, data->triangle);
+ cogl_framebuffer_draw_primitive (data->fb,
+ data->pipeline,
+ data->triangle);
cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb));
- return FALSE; /* remove the callback */
+ return G_SOURCE_REMOVE;
+}
+
+static void
+maybe_redraw (Data *data)
+{
+ if (data->is_dirty && data->draw_ready && data->redraw_idle == 0) {
+ /* We'll draw on idle instead of drawing immediately so that
+ * if Cogl reports multiple dirty rectangles we won't
+ * redundantly draw multiple frames */
+ data->redraw_idle = g_idle_add (paint_cb, data);
+ }
}
static void
@@ -28,8 +49,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
+dirty_cb (CoglOnscreen *onscreen,
+ const CoglOnscreenDirtyInfo *info,
+ void *user_data)
+{
+ Data *data = user_data;
+
+ data->is_dirty = TRUE;
+ maybe_redraw (data);
}
int
@@ -46,6 +82,10 @@ main (int argc, char **argv)
GSource *cogl_source;
GMainLoop *loop;
+ data.redraw_idle = 0;
+ data.is_dirty = 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 +111,10 @@ main (int argc, char **argv)
frame_event_cb,
&data,
NULL); /* destroy notify */
- g_idle_add (paint_cb, &data);
+ cogl_onscreen_add_dirty_callback (COGL_ONSCREEN (data.fb),
+ dirty_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..ef0d08d 100644
--- a/examples/cogl-sdl-hello.c
+++ b/examples/cogl-sdl-hello.c
@@ -33,14 +33,20 @@ redraw (Data *data)
}
static void
+dirty_cb (CoglOnscreen *onscreen,
+ const CoglOnscreenDirtyInfo *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_dirty_callback (onscreen,
+ dirty_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..fb51c7f 100644
--- a/examples/cogl-sdl2-hello.c
+++ b/examples/cogl-sdl2-hello.c
@@ -33,6 +33,16 @@ redraw (Data *data)
}
static void
+dirty_cb (CoglOnscreen *onscreen,
+ const CoglOnscreenDirtyInfo *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_dirty_callback (onscreen,
+ dirty_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..98865f0 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
+dirty_cb (CoglOnscreen *onscreen,
+ const CoglOnscreenDirtyInfo *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_dirty_callback (output->onscreen,
+ dirty_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