renderer/native: Retry page flip after one vsync if EBUSY

We might fail to page flip a new buffer, often after resuming, due to
the FIFO being full. Prior to this commit, we handled this by switching
over to plain mode setting instead of page flipping. This is bad because
we won't be synchronized to the refresh rate anymore, but just the
clock.

Instead, deal with this by trying again until the FIFO is no longer
full. Do this on a v-sync based interval, until it works.

This also changes the error handling code for drivers not supporting
page flipping to rely on them returning -EINVAL. The handling is moved
from pretending a page flip working to explicit mode setting in
meta-renderer-native.c.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/460
This commit is contained in:
Jonas Ådahl 2019-02-12 19:10:59 +01:00
parent 2c1ab8b3cc
commit 979e689278
3 changed files with 345 additions and 122 deletions

View File

@ -74,8 +74,6 @@ struct _MetaGpuKms
int max_buffer_width; int max_buffer_width;
int max_buffer_height; int max_buffer_height;
gboolean page_flips_not_supported;
gboolean resources_init_failed_before; gboolean resources_init_failed_before;
MetaGpuKmsFlag flags; MetaGpuKmsFlag flags;
@ -199,7 +197,6 @@ invoke_flip_closure (GClosure *flip_closure,
g_value_init (&params[3], G_TYPE_INT64); g_value_init (&params[3], G_TYPE_INT64);
g_value_set_int64 (&params[3], page_flip_time_ns); g_value_set_int64 (&params[3], page_flip_time_ns);
g_closure_invoke (flip_closure, NULL, 4, params, NULL); g_closure_invoke (flip_closure, NULL, 4, params, NULL);
g_closure_unref (flip_closure);
} }
gboolean gboolean
@ -245,7 +242,7 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1); closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
*closure_container = (MetaGpuKmsFlipClosureContainer) { *closure_container = (MetaGpuKmsFlipClosureContainer) {
.flip_closure = flip_closure, .flip_closure = g_closure_ref (flip_closure),
.gpu_kms = gpu_kms, .gpu_kms = gpu_kms,
.crtc = crtc .crtc = crtc
}; };
@ -256,20 +253,21 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
void void
meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container) meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container)
{ {
g_closure_unref (closure_container->flip_closure);
g_free (closure_container); g_free (closure_container);
} }
gboolean gboolean
meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms, meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
MetaCrtc *crtc, MetaCrtc *crtc,
int x,
int y,
uint32_t fb_id, uint32_t fb_id,
GClosure *flip_closure, GClosure *flip_closure,
gboolean *fb_in_use) GError **error)
{ {
MetaGpu *gpu = META_GPU (gpu_kms); MetaGpu *gpu = META_GPU (gpu_kms);
MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu);
MetaGpuKmsFlipClosureContainer *closure_container;
int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
uint32_t *connectors; uint32_t *connectors;
unsigned int n_connectors; unsigned int n_connectors;
int ret = -1; int ret = -1;
@ -283,11 +281,6 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
g_assert (fb_id != 0); g_assert (fb_id != 0);
if (!gpu_kms->page_flips_not_supported)
{
MetaGpuKmsFlipClosureContainer *closure_container;
int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms, closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
crtc, crtc,
flip_closure); flip_closure);
@ -297,28 +290,14 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
fb_id, fb_id,
DRM_MODE_PAGE_FLIP_EVENT, DRM_MODE_PAGE_FLIP_EVENT,
closure_container); closure_container);
if (ret != 0 && ret != -EACCES) if (ret != 0)
{ {
meta_gpu_kms_flip_closure_container_free (closure_container); meta_gpu_kms_flip_closure_container_free (closure_container);
g_warning ("Failed to flip: %s", strerror (-ret)); g_set_error (error, G_IO_ERROR,
gpu_kms->page_flips_not_supported = TRUE; g_io_error_from_errno (-ret),
} "drmModePageFlip failed: %s", g_strerror (-ret));
}
if (gpu_kms->page_flips_not_supported)
{
if (meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, x, y, fb_id))
{
*fb_in_use = TRUE;
return FALSE; return FALSE;
} }
}
if (ret != 0)
return FALSE;
*fb_in_use = TRUE;
g_closure_ref (flip_closure);
return TRUE; return TRUE;
} }
@ -365,13 +344,6 @@ meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
{ {
drmEventContext evctx; drmEventContext evctx;
if (gpu_kms->page_flips_not_supported)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Page flips not supported");
return FALSE;
}
memset (&evctx, 0, sizeof evctx); memset (&evctx, 0, sizeof evctx);
evctx.version = 2; evctx.version = 2;
evctx.page_flip_handler = page_flip_handler; evctx.page_flip_handler = page_flip_handler;

View File

@ -72,11 +72,9 @@ gboolean meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms);
gboolean meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms, gboolean meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
MetaCrtc *crtc, MetaCrtc *crtc,
int x,
int y,
uint32_t fb_id, uint32_t fb_id,
GClosure *flip_closure, GClosure *flip_closure,
gboolean *fb_in_use); GError **error);
gboolean meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms, gboolean meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
GError **error); GError **error);

View File

@ -192,6 +192,9 @@ typedef struct _MetaOnscreenNative
int64_t pending_queue_swap_notify_frame_count; int64_t pending_queue_swap_notify_frame_count;
int64_t pending_swap_notify_frame_count; int64_t pending_swap_notify_frame_count;
GList *pending_page_flip_retries;
GSource *retry_page_flips_source;
MetaRendererView *view; MetaRendererView *view;
int total_pending_flips; int total_pending_flips;
} MetaOnscreenNative; } MetaOnscreenNative;
@ -302,6 +305,13 @@ meta_create_renderer_native_gpu_data (MetaGpuKms *gpu_kms)
return g_new0 (MetaRendererNativeGpuData, 1); return g_new0 (MetaRendererNativeGpuData, 1);
} }
static MetaOnscreenNativeSecondaryGpuState *
meta_onscreen_native_get_secondary_gpu_state (MetaOnscreenNative *onscreen_native,
MetaGpuKms *gpu_kms)
{
return g_hash_table_lookup (onscreen_native->secondary_gpu_states, gpu_kms);
}
static MetaOnscreenNativeSecondaryGpuState * static MetaOnscreenNativeSecondaryGpuState *
get_secondary_gpu_state (CoglOnscreen *onscreen, get_secondary_gpu_state (CoglOnscreen *onscreen,
MetaGpuKms *gpu_kms) MetaGpuKms *gpu_kms)
@ -309,7 +319,8 @@ get_secondary_gpu_state (CoglOnscreen *onscreen,
CoglOnscreenEGL *onscreen_egl = onscreen->winsys; CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform; MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
return g_hash_table_lookup (onscreen_native->secondary_gpu_states, gpu_kms); return meta_onscreen_native_get_secondary_gpu_state (onscreen_native,
gpu_kms);
} }
static MetaEgl * static MetaEgl *
@ -1507,19 +1518,202 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
return FALSE; return FALSE;
} }
g_closure_ref (flip_closure);
return TRUE; return TRUE;
} }
#endif /* HAVE_EGL_DEVICE */ #endif /* HAVE_EGL_DEVICE */
static gboolean
is_timestamp_earlier_than (uint64_t ts1,
uint64_t ts2)
{
if (ts1 == ts2)
return FALSE;
else
return ts2 - ts1 < UINT64_MAX / 2;
}
typedef struct _RetryPageFlipData
{
MetaCrtc *crtc;
uint32_t fb_id;
GClosure *flip_closure;
uint64_t retry_time_us;
} RetryPageFlipData;
static void static void
retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data)
{
g_closure_unref (retry_page_flip_data->flip_closure);
g_free (retry_page_flip_data);
}
static gboolean
retry_page_flips (gpointer user_data)
{
MetaOnscreenNative *onscreen_native = user_data;
uint64_t now_us;
GList *l;
now_us = g_source_get_time (onscreen_native->retry_page_flips_source);
l = onscreen_native->pending_page_flip_retries;
while (l)
{
RetryPageFlipData *retry_page_flip_data = l->data;
MetaCrtc *crtc = retry_page_flip_data->crtc;
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
GList *l_next = l->next;
g_autoptr (GError) error = NULL;
gboolean did_flip;
if (is_timestamp_earlier_than (now_us,
retry_page_flip_data->retry_time_us))
{
l = l_next;
continue;
}
did_flip = meta_gpu_kms_flip_crtc (gpu_kms,
crtc,
retry_page_flip_data->fb_id,
retry_page_flip_data->flip_closure,
&error);
if (!did_flip &&
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_BUSY))
{
retry_page_flip_data->retry_time_us +=
G_USEC_PER_SEC / crtc->current_mode->refresh_rate;
l = l_next;
continue;
}
onscreen_native->pending_page_flip_retries =
g_list_remove_link (onscreen_native->pending_page_flip_retries, l);
if (!did_flip)
{
if (!g_error_matches (error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_critical ("Failed to page flip: %s", error->message);
if (gpu_kms != onscreen_native->render_gpu)
{
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
secondary_gpu_state =
meta_onscreen_native_get_secondary_gpu_state (onscreen_native,
gpu_kms);
secondary_gpu_state->pending_flips--;
}
onscreen_native->total_pending_flips--;
}
retry_page_flip_data_free (retry_page_flip_data);
l = l_next;
}
if (onscreen_native->pending_page_flip_retries)
{
GList *l;
uint64_t earliest_retry_time_us = 0;
for (l = onscreen_native->pending_page_flip_retries; l; l = l->next)
{
RetryPageFlipData *retry_page_flip_data = l->data;
if (l == onscreen_native->pending_page_flip_retries ||
is_timestamp_earlier_than (retry_page_flip_data->retry_time_us,
earliest_retry_time_us))
earliest_retry_time_us = retry_page_flip_data->retry_time_us;
}
g_source_set_ready_time (onscreen_native->retry_page_flips_source,
earliest_retry_time_us);
return G_SOURCE_CONTINUE;
}
else
{
g_clear_pointer (&onscreen_native->retry_page_flips_source,
g_source_unref);
return G_SOURCE_REMOVE;
}
}
static gboolean
retry_page_flips_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
return callback (user_data);
}
static GSourceFuncs retry_page_flips_source_funcs = {
.dispatch = retry_page_flips_source_dispatch,
};
static void
schedule_retry_page_flip (MetaOnscreenNative *onscreen_native,
MetaCrtc *crtc,
uint32_t fb_id,
GClosure *flip_closure)
{
RetryPageFlipData *retry_page_flip_data;
uint64_t now_us;
uint64_t retry_time_us;
now_us = g_get_monotonic_time ();
retry_time_us =
now_us + (G_USEC_PER_SEC / crtc->current_mode->refresh_rate);
retry_page_flip_data = g_new0 (RetryPageFlipData, 1);
retry_page_flip_data->crtc = crtc;
retry_page_flip_data->fb_id = fb_id;
retry_page_flip_data->flip_closure = g_closure_ref (flip_closure);
retry_page_flip_data->retry_time_us = retry_time_us;
if (!onscreen_native->retry_page_flips_source)
{
GSource *source;
source = g_source_new (&retry_page_flips_source_funcs, sizeof (GSource));
g_source_set_callback (source, retry_page_flips, onscreen_native, NULL);
g_source_set_ready_time (source, retry_time_us);
g_source_attach (source, NULL);
onscreen_native->retry_page_flips_source = source;
}
else
{
GList *l;
for (l = onscreen_native->pending_page_flip_retries; l; l = l->next)
{
RetryPageFlipData *pending_retry_page_flip_data = l->data;
uint64_t pending_retry_time_us =
pending_retry_page_flip_data->retry_time_us;
if (is_timestamp_earlier_than (retry_time_us, pending_retry_time_us))
{
g_source_set_ready_time (onscreen_native->retry_page_flips_source,
retry_time_us);
break;
}
}
}
onscreen_native->pending_page_flip_retries =
g_list_append (onscreen_native->pending_page_flip_retries,
retry_page_flip_data);
}
static gboolean
meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
GClosure *flip_closure, GClosure *flip_closure,
MetaCrtc *crtc, MetaCrtc *crtc,
int x, GError **error)
int y,
gboolean *fb_in_use)
{ {
CoglOnscreenEGL *onscreen_egl = onscreen->winsys; CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform; MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
@ -1533,8 +1727,9 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
if (!meta_gpu_kms_is_crtc_active (gpu_kms, crtc)) if (!meta_gpu_kms_is_crtc_active (gpu_kms, crtc))
{ {
*fb_in_use = FALSE; g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
return; "Tried to flip inactive CRTC");
return FALSE;
} }
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
@ -1554,11 +1749,23 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
if (!meta_gpu_kms_flip_crtc (gpu_kms, if (!meta_gpu_kms_flip_crtc (gpu_kms,
crtc, crtc,
x, y,
fb_id, fb_id,
flip_closure, flip_closure,
fb_in_use)) error))
return; {
if (g_error_matches (*error,
G_IO_ERROR,
G_IO_ERROR_BUSY))
{
g_clear_error (error);
schedule_retry_page_flip (onscreen_native, crtc,
fb_id, flip_closure);
}
else
{
return FALSE;
}
}
onscreen_native->total_pending_flips++; onscreen_native->total_pending_flips++;
if (secondary_gpu_state) if (secondary_gpu_state)
@ -1570,35 +1777,30 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
if (flip_egl_stream (onscreen_native, if (flip_egl_stream (onscreen_native,
flip_closure)) flip_closure))
onscreen_native->total_pending_flips++; onscreen_native->total_pending_flips++;
*fb_in_use = TRUE;
break; break;
#endif #endif
} }
return TRUE;
} }
typedef struct _SetCrtcFbData
{
MetaGpuKms *render_gpu;
CoglOnscreen *onscreen;
uint32_t fb_id;
} SetCrtcFbData;
static void static void
set_crtc_fb (MetaLogicalMonitor *logical_monitor, set_crtc_fb (CoglOnscreen *onscreen,
MetaLogicalMonitor *logical_monitor,
MetaCrtc *crtc, MetaCrtc *crtc,
gpointer user_data) uint32_t render_fb_id)
{ {
SetCrtcFbData *data = user_data; CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaGpuKms *render_gpu = data->render_gpu; MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
CoglOnscreen *onscreen = data->onscreen; MetaGpuKms *render_gpu = onscreen_native->render_gpu;
MetaGpuKms *gpu_kms; MetaGpuKms *gpu_kms;
uint32_t fb_id;
int x, y; int x, y;
uint32_t fb_id;
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
if (gpu_kms == render_gpu) if (gpu_kms == render_gpu)
{ {
fb_id = data->fb_id; fb_id = render_fb_id;
} }
else else
{ {
@ -1617,6 +1819,23 @@ set_crtc_fb (MetaLogicalMonitor *logical_monitor,
meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, x, y, fb_id); meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, x, y, fb_id);
} }
typedef struct _SetCrtcFbData
{
CoglOnscreen *onscreen;
uint32_t fb_id;
} SetCrtcFbData;
static void
set_crtc_fb_cb (MetaLogicalMonitor *logical_monitor,
MetaCrtc *crtc,
gpointer user_data)
{
SetCrtcFbData *data = user_data;
CoglOnscreen *onscreen = data->onscreen;
set_crtc_fb (onscreen, logical_monitor, crtc, data->fb_id);
}
static void static void
meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen) meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen)
{ {
@ -1649,13 +1868,12 @@ meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen)
if (logical_monitor) if (logical_monitor)
{ {
SetCrtcFbData data = { SetCrtcFbData data = {
.render_gpu = render_gpu,
.onscreen = onscreen, .onscreen = onscreen,
.fb_id = fb_id .fb_id = fb_id
}; };
meta_logical_monitor_foreach_crtc (logical_monitor, meta_logical_monitor_foreach_crtc (logical_monitor,
set_crtc_fb, set_crtc_fb_cb,
&data); &data);
} }
else else
@ -1674,12 +1892,47 @@ meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen)
} }
} }
static gboolean
crtc_mode_set_fallback (CoglOnscreen *onscreen,
MetaLogicalMonitor *logical_monitor,
MetaCrtc *crtc)
{
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
MetaRendererNative *renderer_native;
MetaRendererNativeGpuData *renderer_gpu_data;
uint32_t fb_id;
static gboolean warned_once = FALSE;
if (!warned_once)
{
g_warning ("Page flipping not supported by driver, "
"relying on the clock from now on");
warned_once = TRUE;
}
renderer_native = meta_renderer_native_from_gpu (render_gpu);
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
render_gpu);
if (renderer_gpu_data->mode != META_RENDERER_NATIVE_MODE_GBM)
{
g_warning ("Mode set fallback not handled for EGLStreams");
return FALSE;
}
fb_id = onscreen_native->gbm.next_fb_id;
set_crtc_fb (onscreen, logical_monitor, crtc, fb_id);
return TRUE;
}
typedef struct _FlipCrtcData typedef struct _FlipCrtcData
{ {
CoglOnscreen *onscreen; CoglOnscreen *onscreen;
GClosure *flip_closure; GClosure *flip_closure;
gboolean out_fb_in_use; gboolean did_flip;
gboolean did_mode_set;
} FlipCrtcData; } FlipCrtcData;
static void static void
@ -1688,15 +1941,28 @@ flip_crtc (MetaLogicalMonitor *logical_monitor,
gpointer user_data) gpointer user_data)
{ {
FlipCrtcData *data = user_data; FlipCrtcData *data = user_data;
int x, y; GError *error = NULL;
x = crtc->rect.x - logical_monitor->rect.x; if (!meta_onscreen_native_flip_crtc (data->onscreen,
y = crtc->rect.y - logical_monitor->rect.y;
meta_onscreen_native_flip_crtc (data->onscreen,
data->flip_closure, data->flip_closure,
crtc, x, y, crtc,
&data->out_fb_in_use); &error))
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT))
{
if (crtc_mode_set_fallback (data->onscreen, logical_monitor, crtc))
data->did_mode_set = TRUE;
}
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
{
g_warning ("Failed to flip onscreen: %s", error->message);
}
g_error_free (error);
}
else
{
data->did_flip = TRUE;
}
} }
static void static void
@ -1707,7 +1973,6 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
MetaRendererView *view = onscreen_native->view; MetaRendererView *view = onscreen_native->view;
GClosure *flip_closure; GClosure *flip_closure;
MetaLogicalMonitor *logical_monitor; MetaLogicalMonitor *logical_monitor;
gboolean fb_in_use = FALSE;
/* /*
* Create a closure that either will be invoked or destructed. * Create a closure that either will be invoked or destructed.
@ -1735,29 +2000,12 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
meta_logical_monitor_foreach_crtc (logical_monitor, flip_crtc, &data); meta_logical_monitor_foreach_crtc (logical_monitor, flip_crtc, &data);
/* /*
* If the framebuffer is in use, but we don't have any pending flips it means * If we didn't queue a page flip, but instead directly changed the mode due
* that flipping is not supported and we set the next framebuffer directly. * to the driver not supporting mode setting, wes must swap the buffers
* Since we won't receive a flip callback, lets just notify listeners * directly as we won't get a page flip callback.
* directly.
*/ */
if (fb_in_use && onscreen_native->total_pending_flips == 0) if (!data.did_flip && data.did_mode_set)
{
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
MetaRendererNativeGpuData *renderer_gpu_data;
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
render_gpu);
switch (renderer_gpu_data->mode)
{
case META_RENDERER_NATIVE_MODE_GBM:
meta_onscreen_native_swap_drm_fb (onscreen); meta_onscreen_native_swap_drm_fb (onscreen);
break;
#ifdef HAVE_EGL_DEVICE
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
break;
#endif
}
}
onscreen_native->pending_queue_swap_notify = TRUE; onscreen_native->pending_queue_swap_notify = TRUE;
@ -2720,6 +2968,11 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
onscreen_native = onscreen_egl->platform; onscreen_native = onscreen_egl->platform;
g_list_free_full (onscreen_native->pending_page_flip_retries,
(GDestroyNotify) retry_page_flip_data_free);
g_clear_pointer (&onscreen_native->retry_page_flips_source,
g_source_destroy);
if (onscreen_egl->egl_surface != EGL_NO_SURFACE) if (onscreen_egl->egl_surface != EGL_NO_SURFACE)
{ {
MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);