+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2008 VMware, Inc.
- * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
- * Copyright 2010-2011 LunarG, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-
-/**
- * This is an EGL driver that wraps GLX. This gives the benefit of being
- * completely agnostic of the direct rendering implementation.
- *
- * Authors: Alan Hourihane <alanh@vmware.com>
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <X11/Xlib.h>
-#include <dlfcn.h>
-#include "GL/glx.h"
-
-#include "eglconfig.h"
-#include "eglcontext.h"
-#include "egldefines.h"
-#include "egldisplay.h"
-#include "egldriver.h"
-#include "eglcurrent.h"
-#include "egllog.h"
-#include "eglsurface.h"
-
-#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
-
-#ifndef GLX_VERSION_1_4
-#error "GL/glx.h must be equal to or greater than GLX 1.4"
-#endif
-
-/* GLX 1.0 */
-typedef GLXContext (*GLXCREATECONTEXTPROC)( Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct );
-typedef void (*GLXDESTROYCONTEXTPROC)( Display *dpy, GLXContext ctx );
-typedef Bool (*GLXMAKECURRENTPROC)( Display *dpy, GLXDrawable drawable, GLXContext ctx);
-typedef void (*GLXSWAPBUFFERSPROC)( Display *dpy, GLXDrawable drawable );
-typedef GLXPixmap (*GLXCREATEGLXPIXMAPPROC)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
-typedef void (*GLXDESTROYGLXPIXMAPPROC)( Display *dpy, GLXPixmap pixmap );
-typedef Bool (*GLXQUERYVERSIONPROC)( Display *dpy, int *maj, int *min );
-typedef int (*GLXGETCONFIGPROC)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
-typedef void (*GLXWAITGLPROC)( void );
-typedef void (*GLXWAITXPROC)( void );
-
-/* GLX 1.1 */
-typedef const char *(*GLXQUERYEXTENSIONSSTRINGPROC)( Display *dpy, int screen );
-typedef const char *(*GLXQUERYSERVERSTRINGPROC)( Display *dpy, int screen, int name );
-typedef const char *(*GLXGETCLIENTSTRINGPROC)( Display *dpy, int name );
-
-/** subclass of _EGLDriver */
-struct GLX_egl_driver
-{
- _EGLDriver Base; /**< base class */
-
- void *handle;
-
- /* GLX 1.0 */
- GLXCREATECONTEXTPROC glXCreateContext;
- GLXDESTROYCONTEXTPROC glXDestroyContext;
- GLXMAKECURRENTPROC glXMakeCurrent;
- GLXSWAPBUFFERSPROC glXSwapBuffers;
- GLXCREATEGLXPIXMAPPROC glXCreateGLXPixmap;
- GLXDESTROYGLXPIXMAPPROC glXDestroyGLXPixmap;
- GLXQUERYVERSIONPROC glXQueryVersion;
- GLXGETCONFIGPROC glXGetConfig;
- GLXWAITGLPROC glXWaitGL;
- GLXWAITXPROC glXWaitX;
-
- /* GLX 1.1 */
- GLXQUERYEXTENSIONSSTRINGPROC glXQueryExtensionsString;
- GLXQUERYSERVERSTRINGPROC glXQueryServerString;
- GLXGETCLIENTSTRINGPROC glXGetClientString;
-
- /* GLX 1.3 or (GLX_SGI_make_current_read and GLX_SGIX_fbconfig) */
- PFNGLXGETFBCONFIGSPROC glXGetFBConfigs;
- PFNGLXGETFBCONFIGATTRIBPROC glXGetFBConfigAttrib;
- PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfig;
- PFNGLXCREATEWINDOWPROC glXCreateWindow;
- PFNGLXDESTROYWINDOWPROC glXDestroyWindow;
- PFNGLXCREATEPIXMAPPROC glXCreatePixmap;
- PFNGLXDESTROYPIXMAPPROC glXDestroyPixmap;
- PFNGLXCREATEPBUFFERPROC glXCreatePbuffer;
- PFNGLXDESTROYPBUFFERPROC glXDestroyPbuffer;
- PFNGLXCREATENEWCONTEXTPROC glXCreateNewContext;
- PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent;
-
- /* GLX 1.4 or GLX_ARB_get_proc_address */
- PFNGLXGETPROCADDRESSPROC glXGetProcAddress;
-
- /* GLX_SGIX_pbuffer */
- PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
- PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
-};
-
-
-/** driver data of _EGLDisplay */
-struct GLX_egl_display
-{
- Display *dpy;
- XVisualInfo *visuals;
- GLXFBConfig *fbconfigs;
-
- int glx_maj, glx_min;
-
- const char *extensions;
- EGLBoolean have_1_3;
- EGLBoolean have_make_current_read;
- EGLBoolean have_fbconfig;
- EGLBoolean have_pbuffer;
-
- /* workaround quirks of different GLX implementations */
- EGLBoolean single_buffered_quirk;
- EGLBoolean glx_window_quirk;
-};
-
-
-/** subclass of _EGLContext */
-struct GLX_egl_context
-{
- _EGLContext Base; /**< base class */
-
- GLXContext context;
-};
-
-
-/** subclass of _EGLSurface */
-struct GLX_egl_surface
-{
- _EGLSurface Base; /**< base class */
-
- Drawable drawable;
- GLXDrawable glx_drawable;
-
- void (*destroy)(Display *, GLXDrawable);
-};
-
-
-/** subclass of _EGLConfig */
-struct GLX_egl_config
-{
- _EGLConfig Base; /**< base class */
- EGLBoolean double_buffered;
- int index;
-};
-
-/* standard typecasts */
-_EGL_DRIVER_STANDARD_TYPECASTS(GLX_egl)
-
-static int
-GLX_egl_config_index(_EGLConfig *conf)
-{
- struct GLX_egl_config *GLX_conf = GLX_egl_config(conf);
- return GLX_conf->index;
-}
-
-
-static const struct {
- int attr;
- int egl_attr;
-} fbconfig_attributes[] = {
- /* table 3.1 of GLX 1.4 */
- { GLX_FBCONFIG_ID, 0 },
- { GLX_BUFFER_SIZE, EGL_BUFFER_SIZE },
- { GLX_LEVEL, EGL_LEVEL },
- { GLX_DOUBLEBUFFER, 0 },
- { GLX_STEREO, 0 },
- { GLX_AUX_BUFFERS, 0 },
- { GLX_RED_SIZE, EGL_RED_SIZE },
- { GLX_GREEN_SIZE, EGL_GREEN_SIZE },
- { GLX_BLUE_SIZE, EGL_BLUE_SIZE },
- { GLX_ALPHA_SIZE, EGL_ALPHA_SIZE },
- { GLX_DEPTH_SIZE, EGL_DEPTH_SIZE },
- { GLX_STENCIL_SIZE, EGL_STENCIL_SIZE },
- { GLX_ACCUM_RED_SIZE, 0 },
- { GLX_ACCUM_GREEN_SIZE, 0 },
- { GLX_ACCUM_BLUE_SIZE, 0 },
- { GLX_ACCUM_ALPHA_SIZE, 0 },
- { GLX_SAMPLE_BUFFERS, EGL_SAMPLE_BUFFERS },
- { GLX_SAMPLES, EGL_SAMPLES },
- { GLX_RENDER_TYPE, 0 },
- { GLX_DRAWABLE_TYPE, EGL_SURFACE_TYPE },
- { GLX_X_RENDERABLE, EGL_NATIVE_RENDERABLE },
- { GLX_X_VISUAL_TYPE, EGL_NATIVE_VISUAL_TYPE },
- { GLX_CONFIG_CAVEAT, EGL_CONFIG_CAVEAT },
- { GLX_TRANSPARENT_TYPE, EGL_TRANSPARENT_TYPE },
- { GLX_TRANSPARENT_INDEX_VALUE, 0 },
- { GLX_TRANSPARENT_RED_VALUE, EGL_TRANSPARENT_RED_VALUE },
- { GLX_TRANSPARENT_GREEN_VALUE, EGL_TRANSPARENT_GREEN_VALUE },
- { GLX_TRANSPARENT_BLUE_VALUE, EGL_TRANSPARENT_BLUE_VALUE },
- { GLX_MAX_PBUFFER_WIDTH, EGL_MAX_PBUFFER_WIDTH },
- { GLX_MAX_PBUFFER_HEIGHT, EGL_MAX_PBUFFER_HEIGHT },
- { GLX_MAX_PBUFFER_PIXELS, EGL_MAX_PBUFFER_PIXELS },
- { GLX_VISUAL_ID, EGL_NATIVE_VISUAL_ID }
-};
-
-
-static EGLBoolean
-convert_fbconfig(struct GLX_egl_driver *GLX_drv,
- struct GLX_egl_display *GLX_dpy, GLXFBConfig fbconfig,
- struct GLX_egl_config *GLX_conf)
-{
- Display *dpy = GLX_dpy->dpy;
- int err, attr, val;
- unsigned i;
-
- /* must have rgba bit */
- err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &val);
- if (err || !(val & GLX_RGBA_BIT))
- return EGL_FALSE;
-
- /* must know whether it is double-buffered */
- err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &val);
- if (err)
- return EGL_FALSE;
- GLX_conf->double_buffered = val;
-
- GLX_conf->Base.RenderableType = EGL_OPENGL_BIT;
- GLX_conf->Base.Conformant = EGL_OPENGL_BIT;
-
- for (i = 0; i < ARRAY_SIZE(fbconfig_attributes); i++) {
- EGLint egl_attr, egl_val;
-
- attr = fbconfig_attributes[i].attr;
- egl_attr = fbconfig_attributes[i].egl_attr;
- if (!egl_attr)
- continue;
-
- err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, attr, &val);
- if (err) {
- if (err == GLX_BAD_ATTRIBUTE) {
- err = 0;
- continue;
- }
- break;
- }
-
- switch (egl_attr) {
- case EGL_SURFACE_TYPE:
- egl_val = 0;
- if (val & GLX_WINDOW_BIT)
- egl_val |= EGL_WINDOW_BIT;
- /* pixmap and pbuffer surfaces must be single-buffered in EGL */
- if (!GLX_conf->double_buffered) {
- if (val & GLX_PIXMAP_BIT)
- egl_val |= EGL_PIXMAP_BIT;
- if (val & GLX_PBUFFER_BIT)
- egl_val |= EGL_PBUFFER_BIT;
- }
- break;
- case EGL_NATIVE_VISUAL_TYPE:
- switch (val) {
- case GLX_TRUE_COLOR:
- egl_val = TrueColor;
- break;
- case GLX_DIRECT_COLOR:
- egl_val = DirectColor;
- break;
- case GLX_PSEUDO_COLOR:
- egl_val = PseudoColor;
- break;
- case GLX_STATIC_COLOR:
- egl_val = StaticColor;
- break;
- case GLX_GRAY_SCALE:
- egl_val = GrayScale;
- break;
- case GLX_STATIC_GRAY:
- egl_val = StaticGray;
- break;
- default:
- egl_val = EGL_NONE;
- break;
- }
- break;
- case EGL_CONFIG_CAVEAT:
- egl_val = EGL_NONE;
- if (val == GLX_SLOW_CONFIG) {
- egl_val = EGL_SLOW_CONFIG;
- }
- else if (val == GLX_NON_CONFORMANT_CONFIG) {
- GLX_conf->Base.Conformant &= ~EGL_OPENGL_BIT;
- egl_val = EGL_NONE;
- }
- break;
- case EGL_TRANSPARENT_TYPE:
- egl_val = (val == GLX_TRANSPARENT_RGB) ?
- EGL_TRANSPARENT_RGB : EGL_NONE;
- break;
- default:
- egl_val = val;
- break;
- }
-
- _eglSetConfigKey(&GLX_conf->Base, egl_attr, egl_val);
- }
- if (err)
- return EGL_FALSE;
-
- if (!GLX_conf->Base.SurfaceType)
- return EGL_FALSE;
-
- return EGL_TRUE;
-}
-
-static const struct {
- int attr;
- int egl_attr;
-} visual_attributes[] = {
- /* table 3.7 of GLX 1.4 */
- { GLX_USE_GL, 0 },
- { GLX_BUFFER_SIZE, EGL_BUFFER_SIZE },
- { GLX_LEVEL, EGL_LEVEL },
- { GLX_RGBA, 0 },
- { GLX_DOUBLEBUFFER, 0 },
- { GLX_STEREO, 0 },
- { GLX_AUX_BUFFERS, 0 },
- { GLX_RED_SIZE, EGL_RED_SIZE },
- { GLX_GREEN_SIZE, EGL_GREEN_SIZE },
- { GLX_BLUE_SIZE, EGL_BLUE_SIZE },
- { GLX_ALPHA_SIZE, EGL_ALPHA_SIZE },
- { GLX_DEPTH_SIZE, EGL_DEPTH_SIZE },
- { GLX_STENCIL_SIZE, EGL_STENCIL_SIZE },
- { GLX_ACCUM_RED_SIZE, 0 },
- { GLX_ACCUM_GREEN_SIZE, 0 },
- { GLX_ACCUM_BLUE_SIZE, 0 },
- { GLX_ACCUM_ALPHA_SIZE, 0 },
- { GLX_SAMPLE_BUFFERS, EGL_SAMPLE_BUFFERS },
- { GLX_SAMPLES, EGL_SAMPLES },
- { GLX_FBCONFIG_ID, 0 },
- /* GLX_EXT_visual_rating */
- { GLX_VISUAL_CAVEAT_EXT, EGL_CONFIG_CAVEAT }
-};
-
-static EGLBoolean
-convert_visual(struct GLX_egl_driver *GLX_drv,
- struct GLX_egl_display *GLX_dpy, XVisualInfo *vinfo,
- struct GLX_egl_config *GLX_conf)
-{
- Display *dpy = GLX_dpy->dpy;
- int err, attr, val;
- unsigned i;
-
- /* the visual must support OpenGL and RGBA buffer */
- err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_USE_GL, &val);
- if (!err && val)
- err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_RGBA, &val);
- if (err || !val)
- return EGL_FALSE;
-
- /* must know whether it is double-buffered */
- err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_DOUBLEBUFFER, &val);
- if (err)
- return EGL_FALSE;
- GLX_conf->double_buffered = val;
-
- GLX_conf->Base.RenderableType = EGL_OPENGL_BIT;
- GLX_conf->Base.Conformant = EGL_OPENGL_BIT;
- GLX_conf->Base.SurfaceType = EGL_WINDOW_BIT;
- /* pixmap surfaces must be single-buffered in EGL */
- if (!GLX_conf->double_buffered)
- GLX_conf->Base.SurfaceType |= EGL_PIXMAP_BIT;
-
- GLX_conf->Base.NativeVisualID = vinfo->visualid;
- GLX_conf->Base.NativeVisualType = vinfo->class;
- GLX_conf->Base.NativeRenderable = EGL_TRUE;
-
- for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) {
- EGLint egl_attr, egl_val;
-
- attr = visual_attributes[i].attr;
- egl_attr = visual_attributes[i].egl_attr;
- if (!egl_attr)
- continue;
-
- err = GLX_drv->glXGetConfig(dpy, vinfo, attr, &val);
- if (err) {
- if (err == GLX_BAD_ATTRIBUTE) {
- err = 0;
- continue;
- }
- break;
- }
-
- switch (egl_attr) {
- case EGL_CONFIG_CAVEAT:
- egl_val = EGL_NONE;
- if (val == GLX_SLOW_VISUAL_EXT) {
- egl_val = EGL_SLOW_CONFIG;
- }
- else if (val == GLX_NON_CONFORMANT_VISUAL_EXT) {
- GLX_conf->Base.Conformant &= ~EGL_OPENGL_BIT;
- egl_val = EGL_NONE;
- }
- break;
- break;
- default:
- egl_val = val;
- break;
- }
- _eglSetConfigKey(&GLX_conf->Base, egl_attr, egl_val);
- }
-
- return (err) ? EGL_FALSE : EGL_TRUE;
-}
-
-
-static void
-fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf)
-{
- _EGLConfig *conf = &GLX_conf->Base;
-
- if (!GLX_conf->double_buffered && GLX_dpy->single_buffered_quirk) {
- /* some GLX impls do not like single-buffered window surface */
- conf->SurfaceType &= ~EGL_WINDOW_BIT;
- /* pbuffer bit is usually not set */
- if (GLX_dpy->have_pbuffer)
- conf->SurfaceType |= EGL_PBUFFER_BIT;
- }
-
- /* no visual attribs unless window bit is set */
- if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
- conf->NativeVisualID = 0;
- conf->NativeVisualType = EGL_NONE;
- }
-
- if (conf->TransparentType != EGL_TRANSPARENT_RGB) {
- /* some impls set them to -1 (GLX_DONT_CARE) */
- conf->TransparentRedValue = 0;
- conf->TransparentGreenValue = 0;
- conf->TransparentBlueValue = 0;
- }
-
- /* make sure buffer size is set correctly */
- conf->BufferSize =
- conf->RedSize + conf->GreenSize + conf->BlueSize + conf->AlphaSize;
-}
-
-
-static EGLBoolean
-create_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint screen)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(dpy);
- EGLint num_configs = 0, i;
- EGLint id = 1;
-
- if (GLX_dpy->have_fbconfig) {
- GLX_dpy->fbconfigs =
- GLX_drv->glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs);
- }
- else {
- XVisualInfo vinfo_template;
- long mask;
-
- vinfo_template.screen = screen;
- mask = VisualScreenMask;
- GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &vinfo_template,
- &num_configs);
- }
-
- if (!num_configs)
- return EGL_FALSE;
-
- for (i = 0; i < num_configs; i++) {
- struct GLX_egl_config *GLX_conf, template;
- EGLBoolean ok;
-
- memset(&template, 0, sizeof(template));
- _eglInitConfig(&template.Base, dpy, id);
- if (GLX_dpy->have_fbconfig) {
- ok = convert_fbconfig(GLX_drv, GLX_dpy,
- GLX_dpy->fbconfigs[i], &template);
- }
- else {
- ok = convert_visual(GLX_drv, GLX_dpy,
- &GLX_dpy->visuals[i], &template);
- }
- if (!ok)
- continue;
-
- fix_config(GLX_dpy, &template);
- if (!_eglValidateConfig(&template.Base, EGL_FALSE)) {
- _eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i);
- continue;
- }
-
- GLX_conf = CALLOC_STRUCT(GLX_egl_config);
- if (GLX_conf) {
- memcpy(GLX_conf, &template, sizeof(template));
- GLX_conf->index = i;
-
- _eglLinkConfig(&GLX_conf->Base);
- id++;
- }
- }
-
- return EGL_TRUE;
-}
-
-
-static void
-check_extensions(struct GLX_egl_driver *GLX_drv,
- struct GLX_egl_display *GLX_dpy, EGLint screen)
-{
- GLX_dpy->extensions =
- GLX_drv->glXQueryExtensionsString(GLX_dpy->dpy, screen);
- if (GLX_dpy->extensions) {
- if (strstr(GLX_dpy->extensions, "GLX_SGI_make_current_read")) {
- /* GLX 1.3 entry points are used */
- GLX_dpy->have_make_current_read = EGL_TRUE;
- }
-
- if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) {
- /* GLX 1.3 entry points are used */
- GLX_dpy->have_fbconfig = EGL_TRUE;
- }
-
- if (strstr(GLX_dpy->extensions, "GLX_SGIX_pbuffer")) {
- if (GLX_drv->glXCreateGLXPbufferSGIX &&
- GLX_drv->glXDestroyGLXPbufferSGIX &&
- GLX_dpy->have_fbconfig)
- GLX_dpy->have_pbuffer = EGL_TRUE;
- }
- }
-
- if (GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3) {
- GLX_dpy->have_1_3 = EGL_TRUE;
- GLX_dpy->have_make_current_read = EGL_TRUE;
- GLX_dpy->have_fbconfig = EGL_TRUE;
- GLX_dpy->have_pbuffer = EGL_TRUE;
- }
-}
-
-
-static void
-check_quirks(struct GLX_egl_driver *GLX_drv,
- struct GLX_egl_display *GLX_dpy, EGLint screen)
-{
- const char *vendor;
-
- GLX_dpy->single_buffered_quirk = EGL_TRUE;
- GLX_dpy->glx_window_quirk = EGL_TRUE;
-
- vendor = GLX_drv->glXGetClientString(GLX_dpy->dpy, GLX_VENDOR);
- if (vendor && strstr(vendor, "NVIDIA")) {
- vendor = GLX_drv->glXQueryServerString(GLX_dpy->dpy, screen, GLX_VENDOR);
- if (vendor && strstr(vendor, "NVIDIA")) {
- _eglLog(_EGL_DEBUG, "disable quirks");
- GLX_dpy->single_buffered_quirk = EGL_FALSE;
- GLX_dpy->glx_window_quirk = EGL_FALSE;
- }
- }
-}
-
-
-/**
- * Called via eglInitialize(), GLX_drv->API.Initialize().
- */
-static EGLBoolean
-GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_display *GLX_dpy;
-
- if (disp->Platform != _EGL_PLATFORM_X11)
- return EGL_FALSE;
-
- /* this is a fallback driver */
- if (!disp->Options.UseFallback)
- return EGL_FALSE;
-
- if (disp->Options.TestOnly)
- return EGL_TRUE;
-
- GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
- if (!GLX_dpy)
- return _eglError(EGL_BAD_ALLOC, "eglInitialize");
-
- GLX_dpy->dpy = (Display *) disp->PlatformDisplay;
- if (!GLX_dpy->dpy) {
- GLX_dpy->dpy = XOpenDisplay(NULL);
- if (!GLX_dpy->dpy) {
- _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed");
- free(GLX_dpy);
- return EGL_FALSE;
- }
- }
-
- if (!GLX_drv->glXQueryVersion(GLX_dpy->dpy,
- &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
- _eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
- if (!disp->PlatformDisplay)
- XCloseDisplay(GLX_dpy->dpy);
- free(GLX_dpy);
- return EGL_FALSE;
- }
-
- disp->DriverData = (void *) GLX_dpy;
- disp->ClientAPIs = EGL_OPENGL_BIT;
-
- check_extensions(GLX_drv, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
- check_quirks(GLX_drv, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
-
- create_configs(drv, disp, DefaultScreen(GLX_dpy->dpy));
- if (!_eglGetArraySize(disp->Configs)) {
- _eglLog(_EGL_WARNING, "GLX: failed to create any config");
- if (!disp->PlatformDisplay)
- XCloseDisplay(GLX_dpy->dpy);
- free(GLX_dpy);
- return EGL_FALSE;
- }
-
- /* we're supporting EGL 1.4 */
- disp->VersionMajor = 1;
- disp->VersionMinor = 4;
-
- return EGL_TRUE;
-}
-
-
-/**
- * Called via eglTerminate(), drv->API.Terminate().
- */
-static EGLBoolean
-GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
-{
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
-
- _eglReleaseDisplayResources(drv, disp);
- _eglCleanupDisplay(disp);
-
- free(GLX_dpy->visuals);
- free(GLX_dpy->fbconfigs);
-
- if (!disp->PlatformDisplay)
- XCloseDisplay(GLX_dpy->dpy);
- free(GLX_dpy);
-
- disp->DriverData = NULL;
-
- return EGL_TRUE;
-}
-
-
-/**
- * Called via eglCreateContext(), drv->API.CreateContext().
- */
-static _EGLContext *
-GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
- _EGLContext *share_list, const EGLint *attrib_list)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list);
-
- if (!GLX_ctx) {
- _eglError(EGL_BAD_ALLOC, "eglCreateContext");
- return NULL;
- }
-
- if (!_eglInitContext(&GLX_ctx->Base, disp, conf, attrib_list)) {
- free(GLX_ctx);
- return NULL;
- }
-
- if (GLX_dpy->have_fbconfig) {
- GLX_ctx->context = GLX_drv->glXCreateNewContext(GLX_dpy->dpy,
- GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
- GLX_RGBA_TYPE,
- GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
- GL_TRUE);
- }
- else {
- GLX_ctx->context = GLX_drv->glXCreateContext(GLX_dpy->dpy,
- &GLX_dpy->visuals[GLX_egl_config_index(conf)],
- GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
- GL_TRUE);
- }
- if (!GLX_ctx->context) {
- free(GLX_ctx);
- return NULL;
- }
-
- return &GLX_ctx->Base;
-}
-
-/**
- * Called via eglDestroyContext(), drv->API.DestroyContext().
- */
-static EGLBoolean
-GLX_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
-
- if (_eglPutContext(ctx)) {
- assert(GLX_ctx);
- GLX_drv->glXDestroyContext(GLX_dpy->dpy, GLX_ctx->context);
-
- free(GLX_ctx);
- }
-
- return EGL_TRUE;
-}
-
-/**
- * Destroy a surface. The display is allowed to be uninitialized.
- */
-static void
-destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
-{
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
-
- if (GLX_surf->destroy)
- GLX_surf->destroy(GLX_dpy->dpy, GLX_surf->glx_drawable);
-
- free(GLX_surf);
-}
-
-
-/**
- * Called via eglMakeCurrent(), drv->API.MakeCurrent().
- */
-static EGLBoolean
-GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
- _EGLSurface *rsurf, _EGLContext *ctx)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
- struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
- struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
- _EGLContext *old_ctx;
- _EGLSurface *old_dsurf, *old_rsurf;
- GLXDrawable ddraw, rdraw;
- GLXContext cctx;
- EGLBoolean ret = EGL_FALSE;
-
- /* make new bindings */
- if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
- return EGL_FALSE;
-
- ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None;
- rdraw = (GLX_rsurf) ? GLX_rsurf->glx_drawable : None;
- cctx = (GLX_ctx) ? GLX_ctx->context : NULL;
-
- if (GLX_dpy->have_make_current_read)
- ret = GLX_drv->glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx);
- else if (ddraw == rdraw)
- ret = GLX_drv->glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx);
-
- if (ret) {
- if (_eglPutSurface(old_dsurf))
- destroy_surface(disp, old_dsurf);
- if (_eglPutSurface(old_rsurf))
- destroy_surface(disp, old_rsurf);
- /* no destroy? */
- _eglPutContext(old_ctx);
- }
- else {
- /* undo the previous _eglBindContext */
- _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
- assert(&GLX_ctx->Base == ctx &&
- &GLX_dsurf->Base == dsurf &&
- &GLX_rsurf->Base == rsurf);
-
- _eglPutSurface(dsurf);
- _eglPutSurface(rsurf);
- _eglPutContext(ctx);
-
- _eglPutSurface(old_dsurf);
- _eglPutSurface(old_rsurf);
- _eglPutContext(old_ctx);
- }
-
- return ret;
-}
-
-/** Get size of given window */
-static Status
-get_drawable_size(Display *dpy, Drawable d, unsigned *width, unsigned *height)
-{
- Window root;
- Status stat;
- int xpos, ypos;
- unsigned int w, h, bw, depth;
- stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
- *width = w;
- *height = h;
- return stat;
-}
-
-/**
- * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
- */
-static _EGLSurface *
-GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp,
- _EGLConfig *conf, EGLNativeWindowType window,
- const EGLint *attrib_list)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_surface *GLX_surf;
- unsigned width, height;
-
- GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
- if (!GLX_surf) {
- _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
- return NULL;
- }
-
- if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_WINDOW_BIT,
- conf, attrib_list)) {
- free(GLX_surf);
- return NULL;
- }
-
- GLX_surf->drawable = window;
-
- if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk) {
- GLX_surf->glx_drawable = GLX_drv->glXCreateWindow(GLX_dpy->dpy,
- GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
- GLX_surf->drawable, NULL);
- }
- else {
- GLX_surf->glx_drawable = GLX_surf->drawable;
- }
-
- if (!GLX_surf->glx_drawable) {
- free(GLX_surf);
- return NULL;
- }
-
- if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk)
- GLX_surf->destroy = GLX_drv->glXDestroyWindow;
-
- get_drawable_size(GLX_dpy->dpy, window, &width, &height);
- GLX_surf->Base.Width = width;
- GLX_surf->Base.Height = height;
-
- return &GLX_surf->Base;
-}
-
-static _EGLSurface *
-GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp,
- _EGLConfig *conf, EGLNativePixmapType pixmap,
- const EGLint *attrib_list)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_surface *GLX_surf;
- unsigned width, height;
-
- GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
- if (!GLX_surf) {
- _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
- return NULL;
- }
-
- if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PIXMAP_BIT,
- conf, attrib_list)) {
- free(GLX_surf);
- return NULL;
- }
-
- GLX_surf->drawable = pixmap;
-
- if (GLX_dpy->have_1_3) {
- GLX_surf->glx_drawable = GLX_drv->glXCreatePixmap(GLX_dpy->dpy,
- GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
- GLX_surf->drawable, NULL);
- }
- else if (GLX_dpy->have_fbconfig) {
- GLXFBConfig fbconfig = GLX_dpy->fbconfigs[GLX_egl_config_index(conf)];
- XVisualInfo *vinfo;
-
- vinfo = GLX_drv->glXGetVisualFromFBConfig(GLX_dpy->dpy, fbconfig);
- if (vinfo) {
- GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy,
- vinfo, GLX_surf->drawable);
- free(vinfo);
- }
- }
- else {
- GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy,
- &GLX_dpy->visuals[GLX_egl_config_index(conf)],
- GLX_surf->drawable);
- }
-
- if (!GLX_surf->glx_drawable) {
- free(GLX_surf);
- return NULL;
- }
-
- GLX_surf->destroy = (GLX_dpy->have_1_3) ?
- GLX_drv->glXDestroyPixmap : GLX_drv->glXDestroyGLXPixmap;
-
- get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height);
- GLX_surf->Base.Width = width;
- GLX_surf->Base.Height = height;
-
- return &GLX_surf->Base;
-}
-
-static _EGLSurface *
-GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
- _EGLConfig *conf, const EGLint *attrib_list)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_surface *GLX_surf;
- int attribs[5];
- int i;
-
- GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
- if (!GLX_surf) {
- _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
- return NULL;
- }
-
- if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PBUFFER_BIT,
- conf, attrib_list)) {
- free(GLX_surf);
- return NULL;
- }
-
- i = 0;
- attribs[i] = None;
-
- GLX_surf->drawable = None;
-
- if (GLX_dpy->have_1_3) {
- /* put geometry in attribs */
- if (GLX_surf->Base.Width) {
- attribs[i++] = GLX_PBUFFER_WIDTH;
- attribs[i++] = GLX_surf->Base.Width;
- }
- if (GLX_surf->Base.Height) {
- attribs[i++] = GLX_PBUFFER_HEIGHT;
- attribs[i++] = GLX_surf->Base.Height;
- }
- attribs[i] = None;
-
- GLX_surf->glx_drawable = GLX_drv->glXCreatePbuffer(GLX_dpy->dpy,
- GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], attribs);
- }
- else if (GLX_dpy->have_pbuffer) {
- GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPbufferSGIX(GLX_dpy->dpy,
- GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
- GLX_surf->Base.Width,
- GLX_surf->Base.Height,
- attribs);
- }
-
- if (!GLX_surf->glx_drawable) {
- free(GLX_surf);
- return NULL;
- }
-
- GLX_surf->destroy = (GLX_dpy->have_1_3) ?
- GLX_drv->glXDestroyPbuffer : GLX_drv->glXDestroyGLXPbufferSGIX;
-
- return &GLX_surf->Base;
-}
-
-
-static EGLBoolean
-GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
-{
- (void) drv;
-
- if (_eglPutSurface(surf))
- destroy_surface(disp, surf);
-
- return EGL_TRUE;
-}
-
-
-static EGLBoolean
-GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
-
- GLX_drv->glXSwapBuffers(GLX_dpy->dpy, GLX_surf->glx_drawable);
-
- return EGL_TRUE;
-}
-
-/*
- * Called from eglGetProcAddress() via drv->API.GetProcAddress().
- */
-static _EGLProc
-GLX_eglGetProcAddress(_EGLDriver *drv, const char *procname)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
-
- return (_EGLProc) GLX_drv->glXGetProcAddress((const GLubyte *) procname);
-}
-
-static EGLBoolean
-GLX_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
-
- (void) dpy;
- (void) ctx;
-
- GLX_drv->glXWaitGL();
- return EGL_TRUE;
-}
-
-static EGLBoolean
-GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
-
- (void) dpy;
-
- if (engine != EGL_CORE_NATIVE_ENGINE)
- return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
- GLX_drv->glXWaitX();
- return EGL_TRUE;
-}
-
-static void
-GLX_Unload(_EGLDriver *drv)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
-
- if (GLX_drv->handle)
- dlclose(GLX_drv->handle);
- free(GLX_drv);
-}
-
-
-static EGLBoolean
-GLX_Load(_EGLDriver *drv)
-{
- struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
- void *handle = NULL;
-
- GLX_drv->glXGetProcAddress = dlsym(RTLD_DEFAULT, "glXGetProcAddress");
- if (!GLX_drv->glXGetProcAddress)
- GLX_drv->glXGetProcAddress = dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
- if (!GLX_drv->glXGetProcAddress) {
- handle = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
- if (!handle)
- goto fail;
-
- GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddress");
- if (!GLX_drv->glXGetProcAddress)
- GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddressARB");
- if (!GLX_drv->glXGetProcAddress)
- goto fail;
- }
-
-#define GET_PROC(proc_type, proc_name, check) \
- do { \
- GLX_drv->proc_name = (proc_type) \
- GLX_drv->glXGetProcAddress((const GLubyte *) #proc_name); \
- if (check && !GLX_drv->proc_name) goto fail; \
- } while (0)
-
- /* GLX 1.0 */
- GET_PROC(GLXCREATECONTEXTPROC, glXCreateContext, EGL_TRUE);
- GET_PROC(GLXDESTROYCONTEXTPROC, glXDestroyContext, EGL_TRUE);
- GET_PROC(GLXMAKECURRENTPROC, glXMakeCurrent, EGL_TRUE);
- GET_PROC(GLXSWAPBUFFERSPROC, glXSwapBuffers, EGL_TRUE);
- GET_PROC(GLXCREATEGLXPIXMAPPROC, glXCreateGLXPixmap, EGL_TRUE);
- GET_PROC(GLXDESTROYGLXPIXMAPPROC, glXDestroyGLXPixmap, EGL_TRUE);
- GET_PROC(GLXQUERYVERSIONPROC, glXQueryVersion, EGL_TRUE);
- GET_PROC(GLXGETCONFIGPROC, glXGetConfig, EGL_TRUE);
- GET_PROC(GLXWAITGLPROC, glXWaitGL, EGL_TRUE);
- GET_PROC(GLXWAITXPROC, glXWaitX, EGL_TRUE);
-
- /* GLX 1.1 */
- GET_PROC(GLXQUERYEXTENSIONSSTRINGPROC, glXQueryExtensionsString, EGL_TRUE);
- GET_PROC(GLXQUERYSERVERSTRINGPROC, glXQueryServerString, EGL_TRUE);
- GET_PROC(GLXGETCLIENTSTRINGPROC, glXGetClientString, EGL_TRUE);
-
- /* GLX 1.3 */
- GET_PROC(PFNGLXGETFBCONFIGSPROC, glXGetFBConfigs, EGL_FALSE);
- GET_PROC(PFNGLXGETFBCONFIGATTRIBPROC, glXGetFBConfigAttrib, EGL_FALSE);
- GET_PROC(PFNGLXGETVISUALFROMFBCONFIGPROC, glXGetVisualFromFBConfig, EGL_FALSE);
- GET_PROC(PFNGLXCREATEWINDOWPROC, glXCreateWindow, EGL_FALSE);
- GET_PROC(PFNGLXDESTROYWINDOWPROC, glXDestroyWindow, EGL_FALSE);
- GET_PROC(PFNGLXCREATEPIXMAPPROC, glXCreatePixmap, EGL_FALSE);
- GET_PROC(PFNGLXDESTROYPIXMAPPROC, glXDestroyPixmap, EGL_FALSE);
- GET_PROC(PFNGLXCREATEPBUFFERPROC, glXCreatePbuffer, EGL_FALSE);
- GET_PROC(PFNGLXDESTROYPBUFFERPROC, glXDestroyPbuffer, EGL_FALSE);
- GET_PROC(PFNGLXCREATENEWCONTEXTPROC, glXCreateNewContext, EGL_FALSE);
- GET_PROC(PFNGLXMAKECONTEXTCURRENTPROC, glXMakeContextCurrent, EGL_FALSE);
-
- /* GLX_SGIX_pbuffer */
- GET_PROC(PFNGLXCREATEGLXPBUFFERSGIXPROC,
- glXCreateGLXPbufferSGIX, EGL_FALSE);
- GET_PROC(PFNGLXDESTROYGLXPBUFFERSGIXPROC,
- glXDestroyGLXPbufferSGIX, EGL_FALSE);
-#undef GET_PROC
-
- GLX_drv->handle = handle;
-
- return EGL_TRUE;
-
-fail:
- if (handle)
- dlclose(handle);
- return EGL_FALSE;
-}
-
-
-/**
- * This is the main entrypoint into the driver, called by libEGL.
- * Create a new _EGLDriver object and init its dispatch table.
- */
-_EGLDriver *
-_eglBuiltInDriverGLX(const char *args)
-{
- struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
-
- (void) args;
-
- if (!GLX_drv)
- return NULL;
-
- if (!GLX_Load(&GLX_drv->Base)) {
- _eglLog(_EGL_WARNING, "GLX: failed to load GLX");
- free(GLX_drv);
- return NULL;
- }
-
- _eglInitDriverFallbacks(&GLX_drv->Base);
- GLX_drv->Base.API.Initialize = GLX_eglInitialize;
- GLX_drv->Base.API.Terminate = GLX_eglTerminate;
- GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
- GLX_drv->Base.API.DestroyContext = GLX_eglDestroyContext;
- GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
- GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
- GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
- GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
- GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
- GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
- GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
- GLX_drv->Base.API.WaitClient = GLX_eglWaitClient;
- GLX_drv->Base.API.WaitNative = GLX_eglWaitNative;
-
- GLX_drv->Base.Name = "GLX";
- GLX_drv->Base.Unload = GLX_Unload;
-
- return &GLX_drv->Base;
-}