diff options
Diffstat (limited to 'src/egl/drivers')
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.h | 2 | ||||
-rw-r--r-- | src/egl/drivers/dri2/platform_wayland.c | 57 |
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; |