From 8282cee367703006f075f95ed5654c8c85371151 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 14 May 2013 13:41:29 +0100 Subject: [PATCH] Update some of the examples to use the dirty callback 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. Reviewed-by: Robert Bragg (cherry picked from commit 108e3c548b7866190845f163c84a05212718bd70) --- 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 3ba1e31c4..49f9336de 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 acb9125aa..ef0d08d79 100644 --- a/examples/cogl-sdl-hello.c +++ b/examples/cogl-sdl-hello.c @@ -32,15 +32,21 @@ redraw (Data *data) cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } +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 12e6ced29..fb51c7fad 100644 --- a/examples/cogl-sdl2-hello.c +++ b/examples/cogl-sdl2-hello.c @@ -32,6 +32,16 @@ redraw (Data *data) cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } +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) { @@ -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 4e95bc1a4..77aa6f7e7 100644 --- a/examples/cogland.c +++ b/examples/cogland.c @@ -8,10 +8,6 @@ #include -#ifdef COGL_HAS_XLIB_SUPPORT -#include -#endif - typedef struct _CoglandCompositor CoglandCompositor; typedef struct @@ -781,6 +777,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, @@ -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, compositor->virtual_width, @@ -1050,78 +1061,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) { @@ -1228,8 +1167,6 @@ main (int argc, char **argv) g_source_attach (cogl_source, NULL); - init_redraws (&compositor); - g_main_loop_run (loop); return 0;