egl_dri2/x11: Add support for eglSwapInterval
authorFredrik Höglund <fredrik@kde.org>
Tue, 20 Dec 2011 16:17:02 +0000 (17:17 +0100)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 21 Dec 2011 03:11:17 +0000 (22:11 -0500)
src/egl/drivers/dri2/egl_dri2.c
src/egl/drivers/dri2/egl_dri2.h
src/egl/drivers/dri2/platform_x11.c

index 4c9ece351af2e6db7ce8253b6411ac16e928b14e..47de978404dfc0c155ab641d6f72bc54ae95716c 100644 (file)
@@ -259,9 +259,15 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
       return NULL;
    }
 
-   if (double_buffer)
+   if (double_buffer) {
       surface_type &= ~EGL_PIXMAP_BIT;
 
+      if (dri2_dpy->swap_available) {
+         conf->base.MinSwapInterval = 0;
+         conf->base.MaxSwapInterval = 1000; /* XXX arbitrary value */
+      }
+   }
+
    conf->base.SurfaceType |= surface_type;
 
    return conf;
index 193a866324fde7cac7be475c245a775c0e652b63..bead446dad62ecc1c64ce93d5bb52c3118b1183b 100644 (file)
@@ -102,6 +102,7 @@ struct dri2_egl_display
    int                       fd;
 
    int                       own_device;
+   int                       swap_available;
 #ifdef HAVE_DRM_PLATFORM
    struct gbm_dri_device    *gbm_dri;
 #endif
index d789ec6793a791eeed816157ad990b9a1e87b3bb..d761fe053d6a4da0f4f996a1b918827af812703b 100644 (file)
@@ -763,6 +763,31 @@ dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
    return dri2_swap_buffers_region(drv, disp, draw, 1, rect);
 }
 
+static EGLBoolean
+dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
+{
+#if XCB_DRI2_MINOR_VERSION >= 3
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+
+   /* XXX Check vblank_mode here? */
+
+   if (interval > surf->Config->MaxSwapInterval)
+      interval = surf->Config->MaxSwapInterval;
+   else if (interval < surf->Config->MinSwapInterval)
+      interval = surf->Config->MinSwapInterval;
+
+   if (interval != surf->SwapInterval && dri2_dpy->swap_available)
+      xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval);
+
+   surf->SwapInterval = interval;
+
+   return EGL_TRUE;
+#else
+   return EGL_FALSE;
+#endif
+}
+
 static EGLBoolean
 dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
                  EGLNativePixmapType target)
@@ -987,6 +1012,7 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
    drv->API.CreateImageKHR = dri2_x11_create_image_khr;
    drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
    drv->API.PostSubBufferNV = dri2_post_sub_buffer;
+   drv->API.SwapInterval = dri2_swap_interval;
 
    dri2_dpy = malloc(sizeof *dri2_dpy);
    if (!dri2_dpy)
@@ -1046,6 +1072,8 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
    dri2_dpy->extensions[1] = &image_lookup_extension.base;
    dri2_dpy->extensions[2] = NULL;
 
+   dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2);
+
    if (!dri2_create_screen(disp))
       goto cleanup_fd;