[Cogl] [PATCH 2/2] wayland: Send COGL_FRAME_EVENT_SYNC based on the frame callback

Robert Bragg robert at sixbynine.org
Wed Jul 10 08:44:29 PDT 2013


+  COGL_FLAGS_SET (context->features,
+                  COGL_FEATURE_ID_PRESENTATION_TIME,
+                  TRUE);

I'm not sure that we should be claiming to support this feature for
Wayland yet should we? I didn't think the frame wl_callback interface
gave a timestamp for when a buffer was posted to the display.

Apart from that the patch looks good to land to me:

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

thanks,
- Robert

On Tue, Jul 9, 2013 at 7:26 PM, Neil Roberts <neil at linux.intel.com> wrote:
> Instead of queuing the frame sync event immediately after a swap, the
> Wayland winsys now installs a frame callback and queues the event when
> Wayland reports that the frame is complete. It also reports the
> COGL_FRAME_EVENT_COMPLETE event at the same time because there is no
> more information we can give. The presentation time on the
> CoglFrameInfo is filled in from the timestamp in the callback
> function.
>
> This patch is a bit of a divergence from how the events are handled in
> the GLX winsys. Instead of installing its own idle function, the
> _cogl_onscreen_queue_event() function has now been made non-static so
> that it can be used by the Wayland winsys. The frame callback now just
> queues an event using that. The pending_frame_infos queue on the
> CoglOnscreen isn't used and instead the CoglFrameInfo is immediately
> popped off the queue so that it can be stored as part of the closure
> data when the frame callback is set up. That way it would use the
> right frame info even if somehow the Wayland callbacks were invoked in
> the wrong order and the code is a bit simpler.
> ---
>  cogl/cogl-onscreen-private.h          |  5 +++
>  cogl/cogl-onscreen.c                  |  2 +-
>  cogl/winsys/cogl-winsys-egl-wayland.c | 84 +++++++++++++++++++++++++++++++++++
>  3 files changed, 90 insertions(+), 1 deletion(-)
>
> diff --git a/cogl/cogl-onscreen-private.h b/cogl/cogl-onscreen-private.h
> index 1fd62ea..7314c86 100644
> --- a/cogl/cogl-onscreen-private.h
> +++ b/cogl/cogl-onscreen-private.h
> @@ -93,6 +93,11 @@ _cogl_framebuffer_winsys_update_size (CoglFramebuffer *framebuffer,
>                                        int width, int height);
>
>  void
> +_cogl_onscreen_queue_event (CoglOnscreen *onscreen,
> +                            CoglFrameEvent type,
> +                            CoglFrameInfo *info);
> +
> +void
>  _cogl_onscreen_notify_frame_sync (CoglOnscreen *onscreen, CoglFrameInfo *info);
>
>  void
> diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
> index c7492c8..3782a21 100644
> --- a/cogl/cogl-onscreen.c
> +++ b/cogl/cogl-onscreen.c
> @@ -209,7 +209,7 @@ _cogl_onscreen_queue_full_dirty (CoglOnscreen *onscreen)
>    _cogl_onscreen_queue_dirty (onscreen, &info);
>  }
>
> -static void
> +void
>  _cogl_onscreen_queue_event (CoglOnscreen *onscreen,
>                              CoglFrameEvent type,
>                              CoglFrameInfo *info)
> diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c
> index 075c258..2d20382 100644
> --- a/cogl/winsys/cogl-winsys-egl-wayland.c
> +++ b/cogl/winsys/cogl-winsys-egl-wayland.c
> @@ -41,6 +41,7 @@
>  #include "cogl-wayland-renderer.h"
>  #include "cogl-error-private.h"
>  #include "cogl-poll-private.h"
> +#include "cogl-frame-info-private.h"
>
>  static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
>
> @@ -77,8 +78,18 @@ typedef struct _CoglOnscreenWayland
>    CoglBool has_pending;
>
>    CoglBool shell_surface_type_set;
> +
> +  CoglList frame_callbacks;
>  } CoglOnscreenWayland;
>
> +typedef struct
> +{
> +  CoglList link;
> +  CoglFrameInfo *frame_info;
> +  struct wl_callback *callback;
> +  CoglOnscreen *onscreen;
> +} FrameCallbackData;
> +
>  static void
>  registry_handle_global_cb (void *data,
>                             struct wl_registry *registry,
> @@ -403,6 +414,12 @@ _cogl_winsys_egl_context_init (CoglContext *context,
>    COGL_FLAGS_SET (context->winsys_features,
>                    COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
>                    TRUE);
> +  COGL_FLAGS_SET (context->winsys_features,
> +                  COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT,
> +                  TRUE);
> +  COGL_FLAGS_SET (context->features,
> +                  COGL_FEATURE_ID_PRESENTATION_TIME,
> +                  TRUE);
>
>    /* We'll manually handle queueing dirty events when the surface is
>     * first shown or when it is resized. Note that this is slightly
> @@ -433,6 +450,8 @@ _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen,
>    wayland_onscreen = g_slice_new0 (CoglOnscreenWayland);
>    egl_onscreen->platform = wayland_onscreen;
>
> +  _cogl_list_init (&wayland_onscreen->frame_callbacks);
> +
>    if (onscreen->foreign_surface)
>      wayland_onscreen->wayland_surface = onscreen->foreign_surface;
>    else
> @@ -476,10 +495,26 @@ _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen,
>  }
>
>  static void
> +free_frame_callback_data (FrameCallbackData *callback_data)
> +{
> +  cogl_object_unref (callback_data->frame_info);
> +  wl_callback_destroy (callback_data->callback);
> +  _cogl_list_remove (&callback_data->link);
> +  g_slice_free (FrameCallbackData, callback_data);
> +}
> +
> +static void
>  _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen)
>  {
>    CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
>    CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;
> +  FrameCallbackData *frame_callback_data, *tmp;
> +
> +  _cogl_list_for_each_safe (frame_callback_data,
> +                            tmp,
> +                            &wayland_onscreen->frame_callbacks,
> +                            link)
> +    free_frame_callback_data (frame_callback_data);
>
>    if (wayland_onscreen->wayland_egl_native_window)
>      {
> @@ -535,12 +570,61 @@ flush_pending_resize (CoglOnscreen *onscreen)
>  }
>
>  static void
> +frame_cb (void *data,
> +          struct wl_callback *callback,
> +          uint32_t time)
> +{
> +  FrameCallbackData *callback_data = data;
> +  CoglFrameInfo *info = callback_data->frame_info;
> +  CoglOnscreen *onscreen = callback_data->onscreen;
> +
> +  g_assert (callback_data->callback == callback);
> +
> +  info->presentation_time = time * (int64_t) 1000000;
> +
> +  _cogl_onscreen_queue_event (onscreen, COGL_FRAME_EVENT_SYNC, info);
> +  _cogl_onscreen_queue_event (onscreen, COGL_FRAME_EVENT_COMPLETE, info);
> +
> +  free_frame_callback_data (callback_data);
> +}
> +
> +static const struct wl_callback_listener
> +frame_listener =
> +{
> +  frame_cb
> +};
> +
> +static void
>  _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
>                                                  const int *rectangles,
>                                                  int n_rectangles)
>  {
> +  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
> +  CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform;
> +  FrameCallbackData *frame_callback_data = g_slice_new (FrameCallbackData);
> +
>    flush_pending_resize (onscreen);
>
> +  /* Before calling the winsys function,
> +   * cogl_onscreen_swap_buffers_with_damage() will have pushed the
> +   * frame info object onto the end of the pending frames. We can grab
> +   * it out of the queue now because we don't care about the order and
> +   * we will just directly queue the event corresponding to the exact
> +   * frame that Wayland reports as completed. This will steal the
> +   * reference */
> +  frame_callback_data->frame_info =
> +    g_queue_pop_tail (&onscreen->pending_frame_infos);
> +  frame_callback_data->onscreen = onscreen;
> +
> +  frame_callback_data->callback =
> +    wl_surface_frame (wayland_onscreen->wayland_surface);
> +  wl_callback_add_listener (frame_callback_data->callback,
> +                            &frame_listener,
> +                            frame_callback_data);
> +
> +  _cogl_list_insert (&wayland_onscreen->frame_callbacks,
> +                     &frame_callback_data->link);
> +
>    parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
>                                                      rectangles,
>                                                      n_rectangles);
> --
> 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