[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