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