diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 99d8729..69bf26a 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -50,7 +50,8 @@ sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
 {
    int *done = data;
 
-   *done = 1;
+   if (done)
+      *done = 1;
    wl_callback_destroy(callback);
 }
 
@@ -91,6 +92,8 @@ wl_buffer_release(void *data, struct wl_buffer *buffer)
       return;
    }
 
+   _eglLog(_EGL_DEBUG, "unlock buffer %d\n", i);
+
    dri2_surf->color_buffers[i].locked = 0;
 }
 
@@ -260,10 +263,23 @@ get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
 {
    struct dri2_egl_display *dri2_dpy =
       dri2_egl_display(dri2_surf->base.Resource.Display);
-   int i;
+   int i, lock_count;
+
+   lock_count = 0;
+   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
+      if (dri2_surf->color_buffers[i].locked)
+         lock_count++;
 
-   /* There might be a buffer release already queued that wasn't processed */
-   wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
+   _eglLog(_EGL_DEBUG, "get_back_bo lock count %d\n", lock_count);
+
+   if (dri2_surf->base.SwapInterval == 0 && lock_count >= 2)
+      /* If swap interval is 0, we want to wait for the release buffer that
+       * the server sent in response to the previous SwapBuffers. */
+      wl_display_dispatch_queue(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
+   else 
+      /* If swap interval is 1, there might be a buffer release already queued
+       * that wasn't processed. */
+      wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
 
    if (dri2_surf->back == NULL) {
       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
@@ -291,6 +307,9 @@ get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
    if (dri2_surf->back->dri_buffer == NULL)
       return -1;
 
+   _eglLog(_EGL_DEBUG, "lock buffer %d\n",
+           dri2_surf->back - dri2_surf->color_buffers);
+
    dri2_surf->back->locked = 1;
    memcpy(buffer, dri2_surf->back->dri_buffer, sizeof *buffer);
 
@@ -446,6 +465,7 @@ 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 wl_callback *callback;
    __DRIbuffer buffer;
    int i, ret = 0;
 
@@ -454,11 +474,13 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
    if (ret < 0)
       return EGL_FALSE;
 
-   dri2_surf->frame_callback = wl_surface_frame(dri2_surf->wl_win->surface);
-   wl_callback_add_listener(dri2_surf->frame_callback,
-                            &frame_listener, dri2_surf);
-   wl_proxy_set_queue((struct wl_proxy *) dri2_surf->frame_callback,
-                      dri2_dpy->wl_queue);
+   if (dri2_surf->base.SwapInterval == 1) {
+      dri2_surf->frame_callback = wl_surface_frame(dri2_surf->wl_win->surface);
+      wl_callback_add_listener(dri2_surf->frame_callback,
+                               &frame_listener, dri2_surf);
+      wl_proxy_set_queue((struct wl_proxy *) dri2_surf->frame_callback,
+                         dri2_dpy->wl_queue);
+   }
 
    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
       if (dri2_surf->color_buffers[i].age > 0)
@@ -507,6 +529,14 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
    (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
    (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
 
+   /* Send a sync request to make sure the buffer.release event is sent
+    * immediately in case we have swap interval 0. */
+   if (dri2_surf->base.SwapInterval == 0) {
+      callback = wl_display_sync(dri2_dpy->wl_dpy);
+      wl_callback_add_listener(callback, &sync_listener, NULL);
+      wl_proxy_set_queue((struct wl_proxy *) callback, dri2_dpy->wl_queue);
+   }
+
    return EGL_TRUE;
 }
 
@@ -717,6 +747,9 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri2_create_screen(disp))
       goto cleanup_driver;
 
+   dri2_dpy->min_swap_interval = 0;
+   dri2_dpy->max_swap_interval = 1;
+
    types = EGL_WINDOW_BIT;
    for (i = 0; dri2_dpy->driver_configs[i]; i++) {
       config = dri2_dpy->driver_configs[i];
