[Cogl] [PATCH 3/3] Update some of the examples to use the dirty callback

Robert Bragg robert at sixbynine.org
Tue May 28 04:43:27 PDT 2013


This looks good to land to me:

Reviewed-by: Robert Bragg <robert at linux.intel.com>

thanks,
- Robert

On Tue, May 14, 2013 at 5:03 PM, Neil Roberts <neil at linux.intel.com> wrote:
> 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
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl


More information about the Cogl mailing list