summaryrefslogtreecommitdiff
path: root/src/egl/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/drivers')
-rw-r--r--src/egl/drivers/dri2/egl_dri2.h2
-rw-r--r--src/egl/drivers/dri2/platform_wayland.c57
2 files changed, 37 insertions, 22 deletions
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 1c2c7fe5a6..8f6b0b57ac 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -162,7 +162,7 @@ struct dri2_egl_surface
__DRIbuffer *dri_buffers[__DRI_BUFFER_COUNT];
__DRIbuffer *third_buffer;
__DRIbuffer *pending_buffer;
- EGLBoolean block_swap_buffers;
+ int framefd[2];
int format;
#endif
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 7a70d8d590..86157c337c 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -105,7 +105,7 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
dri2_surf->pending_buffer = NULL;
dri2_surf->third_buffer = NULL;
- dri2_surf->block_swap_buffers = EGL_FALSE;
+ dri2_surf->framefd[0] = dri2_surf->framefd[1] = -1;
if (conf->AlphaSize == 0)
dri2_surf->format = WL_DRM_FORMAT_XRGB32;
@@ -195,6 +195,10 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
(*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
+ for (i = 0; i < 2; ++i)
+ if (dri2_surf->framefd[i] != -1)
+ close(dri2_surf->framefd[i]);
+
for (i = 0; i < WL_BUFFER_COUNT; ++i)
if (dri2_surf->wl_drm_buffer[i])
wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]);
@@ -550,18 +554,35 @@ dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
#endif
}
-static void
-wayland_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
+static EGLBoolean
+synchronize_to_frame(struct dri2_egl_surface *dri2_surf)
{
- struct dri2_egl_surface *dri2_surf = data;
+ int ret;
+ uint32_t time;
+
+ if (dri2_surf->framefd[0] != -1) {
+ /* Block for server sync. */
+ do {
+ ret = read(dri2_surf->framefd[0], &time, sizeof time);
+ } while (ret < 0 && errno == EINTR);
+ close(dri2_surf->framefd[0]);
+ dri2_surf->framefd[0] = -1;
+ }
- dri2_surf->block_swap_buffers = EGL_FALSE;
- wl_callback_destroy(callback);
-}
+ /* Prepare for next frame. */
+ ret = pipe2(dri2_surf->framefd, O_CLOEXEC);
+ if (ret == -1) {
+ _eglLog(_EGL_WARNING, "Failed to create frame synchronization pipe: %s",
+ strerror(errno));
+ return EGL_FALSE;
+ }
-static const struct wl_callback_listener frame_listener = {
- wayland_frame_callback
-};
+ wl_surface_frame_fd(dri2_surf->wl_win->surface, dri2_surf->framefd[1]);
+ close(dri2_surf->framefd[1]);
+ dri2_surf->framefd[1] = -1;
+
+ return EGL_TRUE;
+}
/**
* Called via eglSwapBuffers(), drv->API.SwapBuffers().
@@ -572,19 +593,9 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
- struct wl_callback *callback;
-
- if (dri2_surf->block_swap_buffers) {
- wl_display_flush(dri2_dpy->wl_dpy);
- while (dri2_surf->block_swap_buffers)
- wl_display_iterate(dri2_dpy->wl_dpy, WL_DISPLAY_READABLE);
- }
-
- dri2_surf->block_swap_buffers = EGL_TRUE;
- callback = wl_surface_frame(dri2_surf->wl_win->surface);
- wl_callback_add_listener(callback, &frame_listener, dri2_surf);
if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
+ synchronize_to_frame(dri2_surf);
pointer_swap(
(const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT],
(const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]);
@@ -616,6 +627,10 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
wl_surface_damage(dri2_surf->wl_win->surface, 0, 0,
dri2_surf->base.Width, dri2_surf->base.Height);
+
+ /* Ensure wl_surface_frame_fd is send to server before
+ * we block in next swap_buffers. */
+ wl_display_flush(dri2_dpy->wl_dpy);
}
_EGLContext *ctx;