I've been playing around with egl_glx lately and noticed it was missing
something I wanted. A quick look at source revealed it'd be an easy
addition. This is my first time contributing to Mesa.

Honestly, I tried setting up a Mesa dev environment, but I never quite got
it working. That shouldn't make my code go to waste though! I was hoping
someone could take a look at the code and if you think it's sound, maybe fix
any compiler errors there might be and give it a test run.

There's a minor difference between how EGL handles swap intervals and how
GLX_EXT_swap_control does it. The MaxSwapInterval in EGL is per-config, but
GLX_EXT_swap_control does it per-drawable. My trick around this is to just
assume double-buffered configs have a MaxSwapInterval of at least 1 (which
is a reasonable assumption I think), and on the off chance that they don't,
still report they do to the EGL user and silently ignore it.
From c062e30233ddd45d9b4c9b88233ba29771996c55 Mon Sep 17 00:00:00 2001
From: J. Bates <doste...@gmail.com>
Date: Sun, 28 Aug 2011 21:00:51 -0500
Subject: [PATCH] Added eglSwapInterval support via GLX_EXT_swap_control

---
 src/egl/drivers/glx/egl_glx.c |   54 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
index 7cf8f4d..2618772 100644
--- a/src/egl/drivers/glx/egl_glx.c
+++ b/src/egl/drivers/glx/egl_glx.c
@@ -116,6 +116,9 @@ struct GLX_egl_driver
    /* GLX_SGIX_pbuffer */
    PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
    PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
+
+   /* GLX_EXT_swap_control */
+   PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
 };
 
 
@@ -133,6 +136,7 @@ struct GLX_egl_display
    EGLBoolean have_make_current_read;
    EGLBoolean have_fbconfig;
    EGLBoolean have_pbuffer;
+   EGLBoolean have_EXT_swap_control;
 
    /* workaround quirks of different GLX implementations */
    EGLBoolean single_buffered_quirk;
@@ -325,6 +329,14 @@ convert_fbconfig(struct GLX_egl_driver *GLX_drv,
    if (!GLX_conf->Base.SurfaceType)
       return EGL_FALSE;
 
+   /**
+    * EGL defines this per-config, but GLX per-drawable. Let's just assume
+    * it's available for double-buffered configs. Being silently ignored is
+    * the worst that could happen
+    */
+   if (GLX_dpy->have_EXT_swap_control && GLX_conf->double_buffered)
+      GLX_conf->Base.MaxSwapInterval = 1;
+
    return EGL_TRUE;
 }
 
@@ -390,6 +402,14 @@ convert_visual(struct GLX_egl_driver *GLX_drv,
    GLX_conf->Base.NativeVisualType = vinfo->class;
    GLX_conf->Base.NativeRenderable = EGL_TRUE;
 
+   /**
+    * EGL defines this per-config, but GLX per-drawable. Let's just assume
+    * it's available for double-buffered configs. Being silently ignored is
+    * the worst that could happen
+    */
+   if (GLX_dpy->have_EXT_swap_control && GLX_conf->double_buffered)
+      GLX_conf->Base.MaxSwapInterval = 1;
+
    for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) {
       EGLint egl_attr, egl_val;
 
@@ -547,6 +567,11 @@ check_extensions(struct GLX_egl_driver *GLX_drv,
              GLX_dpy->have_fbconfig)
             GLX_dpy->have_pbuffer = EGL_TRUE;
       }
+
+      if (strstr(GLX_dpy->extensions, "GLX_EXT_swap_control")) {
+         if (GLX_drv->glXSwapIntervalEXT)
+            GLX_dpy->have_EXT_swap_control = EGL_TRUE;
+      }
    }
 
    if (GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3) {
@@ -850,6 +875,10 @@ GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp,
    GLX_surf->Base.Width = width;
    GLX_surf->Base.Height = height;
 
+   if (GLX_dpy->have_EXT_swap_control && GLX_surf->Base.SwapInterval == 1) {
+      GLX_drv->glXSwapIntervalEXT(GLX_dpy->dpy, GLX_surf->glx_drawable, 1);
+   }
+
    return &GLX_surf->Base;
 }
 
@@ -1036,6 +1065,27 @@ GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
    return EGL_TRUE;
 }
 
+EGLBoolean
+GLX_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
+                    EGLint interval)
+{
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(dpy);
+   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+   if (GLX_dpy->have_EXT_swap_control) {
+      if (interval > surf->Config->MaxSwapInterval)
+         interval = surf->Config->MaxSwapInterval;
+      else if (interval < surf->Config->MinSwapInterval)
+         interval = surf->Config->MinSwapInterval;
+      surf->SwapInterval = interval;
+      GLX_drv->glXSwapIntervalEXT(GLX_dpy->dpy, GLX_surf->glx_drawable,
+            interval);
+      return EGL_TRUE;
+   }
+   else
+      return _eglSwapInterval(drv, dpy, surf, interval);
+}
+
 static void
 GLX_Unload(_EGLDriver *drv)
 {
@@ -1105,6 +1155,9 @@ GLX_Load(_EGLDriver *drv)
          glXCreateGLXPbufferSGIX, EGL_FALSE);
    GET_PROC(PFNGLXDESTROYGLXPBUFFERSGIXPROC,
          glXDestroyGLXPbufferSGIX, EGL_FALSE);
+
+   /* GLX_EXT_swap_control */
+   GET_PROC(PFNGLXSWAPINTERVALEXTPROC, glXSwapIntervalEXT, EGL_FALSE);
 #undef GET_PROC
 
    GLX_drv->handle = handle;
@@ -1151,6 +1204,7 @@ _EGL_MAIN(const char *args)
    GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
    GLX_drv->Base.API.WaitClient = GLX_eglWaitClient;
    GLX_drv->Base.API.WaitNative = GLX_eglWaitNative;
+   GLX_drv->Base.API.SwapInterval = GLX_eglSwapInterval;
 
    GLX_drv->Base.Name = "GLX";
    GLX_drv->Base.Unload = GLX_Unload;
-- 
1.7.4.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to