wayland: Send COGL_FRAME_EVENT_SYNC based on the frame callback
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. 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. Reviewed-by: Robert Bragg <robert@linux.intel.com> (cherry picked from commit f7ea370a0d5013c9f0263f37c7f892adc8a2f087)
This commit is contained in:
parent
737806bcee
commit
b3cc4d26d9
@ -95,6 +95,11 @@ void
|
||||
_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);
|
||||
|
||||
|
@ -242,7 +242,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)
|
||||
|
@ -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,
|
||||
@ -404,6 +415,9 @@ _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);
|
||||
|
||||
/* We'll manually handle queueing dirty events when the surface is
|
||||
* first shown or when it is resized. Note that this is slightly
|
||||
@ -434,6 +448,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,11 +492,27 @@ _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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,13 +567,60 @@ 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);
|
||||
|
||||
_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);
|
||||
|
Loading…
Reference in New Issue
Block a user