Home | History | Annotate | Download | only in glx
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
      4  * Copyright 2009-2010 Chia-I Wu <olvaffe (at) gmail.com>
      5  * Copyright 2010-2011 LunarG, Inc.
      6  * All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation the rights to use, copy, modify, merge, publish,
     12  * distribute, sub license, and/or sell copies of the Software, and to
     13  * permit persons to whom the Software is furnished to do so, subject to
     14  * the following conditions:
     15  *
     16  * The above copyright notice and this permission notice (including the
     17  * next paragraph) shall be included in all copies or substantial portions
     18  * of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     26  * DEALINGS IN THE SOFTWARE.
     27  *
     28  **************************************************************************/
     29 
     30 
     31 /**
     32  * This is an EGL driver that wraps GLX. This gives the benefit of being
     33  * completely agnostic of the direct rendering implementation.
     34  *
     35  * Authors: Alan Hourihane <alanh (at) tungstengraphics.com>
     36  */
     37 
     38 #include <stdlib.h>
     39 #include <string.h>
     40 #include <X11/Xlib.h>
     41 #include <dlfcn.h>
     42 #include "GL/glx.h"
     43 
     44 #include "eglconfig.h"
     45 #include "eglcontext.h"
     46 #include "egldefines.h"
     47 #include "egldisplay.h"
     48 #include "egldriver.h"
     49 #include "eglcurrent.h"
     50 #include "egllog.h"
     51 #include "eglsurface.h"
     52 
     53 #define CALLOC_STRUCT(T)   (struct T *) calloc(1, sizeof(struct T))
     54 
     55 #ifndef GLX_VERSION_1_4
     56 #error "GL/glx.h must be equal to or greater than GLX 1.4"
     57 #endif
     58 
     59 /* GLX 1.0 */
     60 typedef GLXContext (*GLXCREATECONTEXTPROC)( Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct );
     61 typedef void (*GLXDESTROYCONTEXTPROC)( Display *dpy, GLXContext ctx );
     62 typedef Bool (*GLXMAKECURRENTPROC)( Display *dpy, GLXDrawable drawable, GLXContext ctx);
     63 typedef void (*GLXSWAPBUFFERSPROC)( Display *dpy, GLXDrawable drawable );
     64 typedef GLXPixmap (*GLXCREATEGLXPIXMAPPROC)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
     65 typedef void (*GLXDESTROYGLXPIXMAPPROC)( Display *dpy, GLXPixmap pixmap );
     66 typedef Bool (*GLXQUERYVERSIONPROC)( Display *dpy, int *maj, int *min );
     67 typedef int (*GLXGETCONFIGPROC)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
     68 typedef void (*GLXWAITGLPROC)( void );
     69 typedef void (*GLXWAITXPROC)( void );
     70 
     71 /* GLX 1.1 */
     72 typedef const char *(*GLXQUERYEXTENSIONSSTRINGPROC)( Display *dpy, int screen );
     73 typedef const char *(*GLXQUERYSERVERSTRINGPROC)( Display *dpy, int screen, int name );
     74 typedef const char *(*GLXGETCLIENTSTRINGPROC)( Display *dpy, int name );
     75 
     76 /** subclass of _EGLDriver */
     77 struct GLX_egl_driver
     78 {
     79    _EGLDriver Base;   /**< base class */
     80 
     81    void *handle;
     82 
     83    /* GLX 1.0 */
     84    GLXCREATECONTEXTPROC glXCreateContext;
     85    GLXDESTROYCONTEXTPROC glXDestroyContext;
     86    GLXMAKECURRENTPROC glXMakeCurrent;
     87    GLXSWAPBUFFERSPROC glXSwapBuffers;
     88    GLXCREATEGLXPIXMAPPROC glXCreateGLXPixmap;
     89    GLXDESTROYGLXPIXMAPPROC glXDestroyGLXPixmap;
     90    GLXQUERYVERSIONPROC glXQueryVersion;
     91    GLXGETCONFIGPROC glXGetConfig;
     92    GLXWAITGLPROC glXWaitGL;
     93    GLXWAITXPROC glXWaitX;
     94 
     95    /* GLX 1.1 */
     96    GLXQUERYEXTENSIONSSTRINGPROC glXQueryExtensionsString;
     97    GLXQUERYSERVERSTRINGPROC glXQueryServerString;
     98    GLXGETCLIENTSTRINGPROC glXGetClientString;
     99 
    100    /* GLX 1.3 or (GLX_SGI_make_current_read and GLX_SGIX_fbconfig) */
    101    PFNGLXGETFBCONFIGSPROC glXGetFBConfigs;
    102    PFNGLXGETFBCONFIGATTRIBPROC glXGetFBConfigAttrib;
    103    PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfig;
    104    PFNGLXCREATEWINDOWPROC glXCreateWindow;
    105    PFNGLXDESTROYWINDOWPROC glXDestroyWindow;
    106    PFNGLXCREATEPIXMAPPROC glXCreatePixmap;
    107    PFNGLXDESTROYPIXMAPPROC glXDestroyPixmap;
    108    PFNGLXCREATEPBUFFERPROC glXCreatePbuffer;
    109    PFNGLXDESTROYPBUFFERPROC glXDestroyPbuffer;
    110    PFNGLXCREATENEWCONTEXTPROC glXCreateNewContext;
    111    PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent;
    112 
    113    /* GLX 1.4 or GLX_ARB_get_proc_address */
    114    PFNGLXGETPROCADDRESSPROC glXGetProcAddress;
    115 
    116    /* GLX_SGIX_pbuffer */
    117    PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
    118    PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
    119 };
    120 
    121 
    122 /** driver data of _EGLDisplay */
    123 struct GLX_egl_display
    124 {
    125    Display *dpy;
    126    XVisualInfo *visuals;
    127    GLXFBConfig *fbconfigs;
    128 
    129    int glx_maj, glx_min;
    130 
    131    const char *extensions;
    132    EGLBoolean have_1_3;
    133    EGLBoolean have_make_current_read;
    134    EGLBoolean have_fbconfig;
    135    EGLBoolean have_pbuffer;
    136 
    137    /* workaround quirks of different GLX implementations */
    138    EGLBoolean single_buffered_quirk;
    139    EGLBoolean glx_window_quirk;
    140 };
    141 
    142 
    143 /** subclass of _EGLContext */
    144 struct GLX_egl_context
    145 {
    146    _EGLContext Base;   /**< base class */
    147 
    148    GLXContext context;
    149 };
    150 
    151 
    152 /** subclass of _EGLSurface */
    153 struct GLX_egl_surface
    154 {
    155    _EGLSurface Base;   /**< base class */
    156 
    157    Drawable drawable;
    158    GLXDrawable glx_drawable;
    159 
    160    void (*destroy)(Display *, GLXDrawable);
    161 };
    162 
    163 
    164 /** subclass of _EGLConfig */
    165 struct GLX_egl_config
    166 {
    167    _EGLConfig Base;   /**< base class */
    168    EGLBoolean double_buffered;
    169    int index;
    170 };
    171 
    172 /* standard typecasts */
    173 _EGL_DRIVER_STANDARD_TYPECASTS(GLX_egl)
    174 
    175 static int
    176 GLX_egl_config_index(_EGLConfig *conf)
    177 {
    178    struct GLX_egl_config *GLX_conf = GLX_egl_config(conf);
    179    return GLX_conf->index;
    180 }
    181 
    182 
    183 static const struct {
    184    int attr;
    185    int egl_attr;
    186 } fbconfig_attributes[] = {
    187    /* table 3.1 of GLX 1.4 */
    188    { GLX_FBCONFIG_ID,                  0 },
    189    { GLX_BUFFER_SIZE,                  EGL_BUFFER_SIZE },
    190    { GLX_LEVEL,                        EGL_LEVEL },
    191    { GLX_DOUBLEBUFFER,                 0 },
    192    { GLX_STEREO,                       0 },
    193    { GLX_AUX_BUFFERS,                  0 },
    194    { GLX_RED_SIZE,                     EGL_RED_SIZE },
    195    { GLX_GREEN_SIZE,                   EGL_GREEN_SIZE },
    196    { GLX_BLUE_SIZE,                    EGL_BLUE_SIZE },
    197    { GLX_ALPHA_SIZE,                   EGL_ALPHA_SIZE },
    198    { GLX_DEPTH_SIZE,                   EGL_DEPTH_SIZE },
    199    { GLX_STENCIL_SIZE,                 EGL_STENCIL_SIZE },
    200    { GLX_ACCUM_RED_SIZE,               0 },
    201    { GLX_ACCUM_GREEN_SIZE,             0 },
    202    { GLX_ACCUM_BLUE_SIZE,              0 },
    203    { GLX_ACCUM_ALPHA_SIZE,             0 },
    204    { GLX_SAMPLE_BUFFERS,               EGL_SAMPLE_BUFFERS },
    205    { GLX_SAMPLES,                      EGL_SAMPLES },
    206    { GLX_RENDER_TYPE,                  0 },
    207    { GLX_DRAWABLE_TYPE,                EGL_SURFACE_TYPE },
    208    { GLX_X_RENDERABLE,                 EGL_NATIVE_RENDERABLE },
    209    { GLX_X_VISUAL_TYPE,                EGL_NATIVE_VISUAL_TYPE },
    210    { GLX_CONFIG_CAVEAT,                EGL_CONFIG_CAVEAT },
    211    { GLX_TRANSPARENT_TYPE,             EGL_TRANSPARENT_TYPE },
    212    { GLX_TRANSPARENT_INDEX_VALUE,      0 },
    213    { GLX_TRANSPARENT_RED_VALUE,        EGL_TRANSPARENT_RED_VALUE },
    214    { GLX_TRANSPARENT_GREEN_VALUE,      EGL_TRANSPARENT_GREEN_VALUE },
    215    { GLX_TRANSPARENT_BLUE_VALUE,       EGL_TRANSPARENT_BLUE_VALUE },
    216    { GLX_MAX_PBUFFER_WIDTH,            EGL_MAX_PBUFFER_WIDTH },
    217    { GLX_MAX_PBUFFER_HEIGHT,           EGL_MAX_PBUFFER_HEIGHT },
    218    { GLX_MAX_PBUFFER_PIXELS,           EGL_MAX_PBUFFER_PIXELS },
    219    { GLX_VISUAL_ID,                    EGL_NATIVE_VISUAL_ID }
    220 };
    221 
    222 
    223 static EGLBoolean
    224 convert_fbconfig(struct GLX_egl_driver *GLX_drv,
    225                  struct GLX_egl_display *GLX_dpy, GLXFBConfig fbconfig,
    226                  struct GLX_egl_config *GLX_conf)
    227 {
    228    Display *dpy = GLX_dpy->dpy;
    229    int err, attr, val;
    230    unsigned i;
    231 
    232    /* must have rgba bit */
    233    err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &val);
    234    if (err || !(val & GLX_RGBA_BIT))
    235       return EGL_FALSE;
    236 
    237    /* must know whether it is double-buffered */
    238    err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &val);
    239    if (err)
    240       return EGL_FALSE;
    241    GLX_conf->double_buffered = val;
    242 
    243    GLX_conf->Base.RenderableType = EGL_OPENGL_BIT;
    244    GLX_conf->Base.Conformant = EGL_OPENGL_BIT;
    245 
    246    for (i = 0; i < ARRAY_SIZE(fbconfig_attributes); i++) {
    247       EGLint egl_attr, egl_val;
    248 
    249       attr = fbconfig_attributes[i].attr;
    250       egl_attr = fbconfig_attributes[i].egl_attr;
    251       if (!egl_attr)
    252          continue;
    253 
    254       err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, attr, &val);
    255       if (err) {
    256          if (err == GLX_BAD_ATTRIBUTE) {
    257             err = 0;
    258             continue;
    259          }
    260          break;
    261       }
    262 
    263       switch (egl_attr) {
    264       case EGL_SURFACE_TYPE:
    265          egl_val = 0;
    266          if (val & GLX_WINDOW_BIT)
    267             egl_val |= EGL_WINDOW_BIT;
    268          /* pixmap and pbuffer surfaces must be single-buffered in EGL */
    269          if (!GLX_conf->double_buffered) {
    270             if (val & GLX_PIXMAP_BIT)
    271                egl_val |= EGL_PIXMAP_BIT;
    272             if (val & GLX_PBUFFER_BIT)
    273                egl_val |= EGL_PBUFFER_BIT;
    274          }
    275          break;
    276       case EGL_NATIVE_VISUAL_TYPE:
    277          switch (val) {
    278          case GLX_TRUE_COLOR:
    279             egl_val = TrueColor;
    280             break;
    281          case GLX_DIRECT_COLOR:
    282             egl_val = DirectColor;
    283             break;
    284          case GLX_PSEUDO_COLOR:
    285             egl_val = PseudoColor;
    286             break;
    287          case GLX_STATIC_COLOR:
    288             egl_val = StaticColor;
    289             break;
    290          case GLX_GRAY_SCALE:
    291             egl_val = GrayScale;
    292             break;
    293          case GLX_STATIC_GRAY:
    294             egl_val = StaticGray;
    295             break;
    296          default:
    297             egl_val = EGL_NONE;
    298             break;
    299          }
    300          break;
    301       case EGL_CONFIG_CAVEAT:
    302          egl_val = EGL_NONE;
    303          if (val == GLX_SLOW_CONFIG) {
    304             egl_val = EGL_SLOW_CONFIG;
    305          }
    306          else if (val == GLX_NON_CONFORMANT_CONFIG) {
    307             GLX_conf->Base.Conformant &= ~EGL_OPENGL_BIT;
    308             egl_val = EGL_NONE;
    309          }
    310          break;
    311       case EGL_TRANSPARENT_TYPE:
    312          egl_val = (val == GLX_TRANSPARENT_RGB) ?
    313             EGL_TRANSPARENT_RGB : EGL_NONE;
    314          break;
    315       default:
    316          egl_val = val;
    317          break;
    318       }
    319 
    320       _eglSetConfigKey(&GLX_conf->Base, egl_attr, egl_val);
    321    }
    322    if (err)
    323       return EGL_FALSE;
    324 
    325    if (!GLX_conf->Base.SurfaceType)
    326       return EGL_FALSE;
    327 
    328    return EGL_TRUE;
    329 }
    330 
    331 static const struct {
    332    int attr;
    333    int egl_attr;
    334 } visual_attributes[] = {
    335    /* table 3.7 of GLX 1.4 */
    336    { GLX_USE_GL,              0 },
    337    { GLX_BUFFER_SIZE,         EGL_BUFFER_SIZE },
    338    { GLX_LEVEL,               EGL_LEVEL },
    339    { GLX_RGBA,                0 },
    340    { GLX_DOUBLEBUFFER,        0 },
    341    { GLX_STEREO,              0 },
    342    { GLX_AUX_BUFFERS,         0 },
    343    { GLX_RED_SIZE,            EGL_RED_SIZE },
    344    { GLX_GREEN_SIZE,          EGL_GREEN_SIZE },
    345    { GLX_BLUE_SIZE,           EGL_BLUE_SIZE },
    346    { GLX_ALPHA_SIZE,          EGL_ALPHA_SIZE },
    347    { GLX_DEPTH_SIZE,          EGL_DEPTH_SIZE },
    348    { GLX_STENCIL_SIZE,        EGL_STENCIL_SIZE },
    349    { GLX_ACCUM_RED_SIZE,      0 },
    350    { GLX_ACCUM_GREEN_SIZE,    0 },
    351    { GLX_ACCUM_BLUE_SIZE,     0 },
    352    { GLX_ACCUM_ALPHA_SIZE,    0 },
    353    { GLX_SAMPLE_BUFFERS,      EGL_SAMPLE_BUFFERS },
    354    { GLX_SAMPLES,             EGL_SAMPLES },
    355    { GLX_FBCONFIG_ID,         0 },
    356    /* GLX_EXT_visual_rating */
    357    { GLX_VISUAL_CAVEAT_EXT,   EGL_CONFIG_CAVEAT }
    358 };
    359 
    360 static EGLBoolean
    361 convert_visual(struct GLX_egl_driver *GLX_drv,
    362                struct GLX_egl_display *GLX_dpy, XVisualInfo *vinfo,
    363                struct GLX_egl_config *GLX_conf)
    364 {
    365    Display *dpy = GLX_dpy->dpy;
    366    int err, attr, val;
    367    unsigned i;
    368 
    369    /* the visual must support OpenGL and RGBA buffer */
    370    err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_USE_GL, &val);
    371    if (!err && val)
    372       err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_RGBA, &val);
    373    if (err || !val)
    374       return EGL_FALSE;
    375 
    376    /* must know whether it is double-buffered */
    377    err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_DOUBLEBUFFER, &val);
    378    if (err)
    379       return EGL_FALSE;
    380    GLX_conf->double_buffered = val;
    381 
    382    GLX_conf->Base.RenderableType = EGL_OPENGL_BIT;
    383    GLX_conf->Base.Conformant = EGL_OPENGL_BIT;
    384    GLX_conf->Base.SurfaceType = EGL_WINDOW_BIT;
    385    /* pixmap surfaces must be single-buffered in EGL */
    386    if (!GLX_conf->double_buffered)
    387       GLX_conf->Base.SurfaceType |= EGL_PIXMAP_BIT;
    388 
    389    GLX_conf->Base.NativeVisualID = vinfo->visualid;
    390    GLX_conf->Base.NativeVisualType = vinfo->class;
    391    GLX_conf->Base.NativeRenderable = EGL_TRUE;
    392 
    393    for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) {
    394       EGLint egl_attr, egl_val;
    395 
    396       attr = visual_attributes[i].attr;
    397       egl_attr = visual_attributes[i].egl_attr;
    398       if (!egl_attr)
    399          continue;
    400 
    401       err = GLX_drv->glXGetConfig(dpy, vinfo, attr, &val);
    402       if (err) {
    403          if (err == GLX_BAD_ATTRIBUTE) {
    404             err = 0;
    405             continue;
    406          }
    407          break;
    408       }
    409 
    410       switch (egl_attr) {
    411       case EGL_CONFIG_CAVEAT:
    412          egl_val = EGL_NONE;
    413          if (val == GLX_SLOW_VISUAL_EXT) {
    414             egl_val = EGL_SLOW_CONFIG;
    415          }
    416          else if (val == GLX_NON_CONFORMANT_VISUAL_EXT) {
    417             GLX_conf->Base.Conformant &= ~EGL_OPENGL_BIT;
    418             egl_val = EGL_NONE;
    419          }
    420          break;
    421          break;
    422       default:
    423          egl_val = val;
    424          break;
    425       }
    426       _eglSetConfigKey(&GLX_conf->Base, egl_attr, egl_val);
    427    }
    428 
    429    return (err) ? EGL_FALSE : EGL_TRUE;
    430 }
    431 
    432 
    433 static void
    434 fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf)
    435 {
    436    _EGLConfig *conf = &GLX_conf->Base;
    437 
    438    if (!GLX_conf->double_buffered && GLX_dpy->single_buffered_quirk) {
    439       /* some GLX impls do not like single-buffered window surface */
    440       conf->SurfaceType &= ~EGL_WINDOW_BIT;
    441       /* pbuffer bit is usually not set */
    442       if (GLX_dpy->have_pbuffer)
    443          conf->SurfaceType |= EGL_PBUFFER_BIT;
    444    }
    445 
    446    /* no visual attribs unless window bit is set */
    447    if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
    448       conf->NativeVisualID = 0;
    449       conf->NativeVisualType = EGL_NONE;
    450    }
    451 
    452    if (conf->TransparentType != EGL_TRANSPARENT_RGB) {
    453       /* some impls set them to -1 (GLX_DONT_CARE) */
    454       conf->TransparentRedValue = 0;
    455       conf->TransparentGreenValue = 0;
    456       conf->TransparentBlueValue = 0;
    457    }
    458 
    459    /* make sure buffer size is set correctly */
    460    conf->BufferSize =
    461       conf->RedSize + conf->GreenSize + conf->BlueSize + conf->AlphaSize;
    462 }
    463 
    464 
    465 static EGLBoolean
    466 create_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint screen)
    467 {
    468    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
    469    struct GLX_egl_display *GLX_dpy = GLX_egl_display(dpy);
    470    EGLint num_configs = 0, i;
    471    EGLint id = 1;
    472 
    473    if (GLX_dpy->have_fbconfig) {
    474       GLX_dpy->fbconfigs =
    475          GLX_drv->glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs);
    476    }
    477    else {
    478       XVisualInfo vinfo_template;
    479       long mask;
    480 
    481       vinfo_template.screen = screen;
    482       mask = VisualScreenMask;
    483       GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &vinfo_template,
    484                                         &num_configs);
    485    }
    486 
    487    if (!num_configs)
    488       return EGL_FALSE;
    489 
    490    for (i = 0; i < num_configs; i++) {
    491       struct GLX_egl_config *GLX_conf, template;
    492       EGLBoolean ok;
    493 
    494       memset(&template, 0, sizeof(template));
    495       _eglInitConfig(&template.Base, dpy, id);
    496       if (GLX_dpy->have_fbconfig) {
    497          ok = convert_fbconfig(GLX_drv, GLX_dpy,
    498                GLX_dpy->fbconfigs[i], &template);
    499       }
    500       else {
    501          ok = convert_visual(GLX_drv, GLX_dpy,
    502                &GLX_dpy->visuals[i], &template);
    503       }
    504       if (!ok)
    505         continue;
    506 
    507       fix_config(GLX_dpy, &template);
    508       if (!_eglValidateConfig(&template.Base, EGL_FALSE)) {
    509          _eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i);
    510          continue;
    511       }
    512 
    513       GLX_conf = CALLOC_STRUCT(GLX_egl_config);
    514       if (GLX_conf) {
    515          memcpy(GLX_conf, &template, sizeof(template));
    516          GLX_conf->index = i;
    517 
    518          _eglLinkConfig(&GLX_conf->Base);
    519          id++;
    520       }
    521    }
    522 
    523    return EGL_TRUE;
    524 }
    525 
    526 
    527 static void
    528 check_extensions(struct GLX_egl_driver *GLX_drv,
    529                  struct GLX_egl_display *GLX_dpy, EGLint screen)
    530 {
    531    GLX_dpy->extensions =
    532       GLX_drv->glXQueryExtensionsString(GLX_dpy->dpy, screen);
    533    if (GLX_dpy->extensions) {
    534       if (strstr(GLX_dpy->extensions, "GLX_SGI_make_current_read")) {
    535          /* GLX 1.3 entry points are used */
    536          GLX_dpy->have_make_current_read = EGL_TRUE;
    537       }
    538 
    539       if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) {
    540          /* GLX 1.3 entry points are used */
    541          GLX_dpy->have_fbconfig = EGL_TRUE;
    542       }
    543 
    544       if (strstr(GLX_dpy->extensions, "GLX_SGIX_pbuffer")) {
    545          if (GLX_drv->glXCreateGLXPbufferSGIX &&
    546              GLX_drv->glXDestroyGLXPbufferSGIX &&
    547              GLX_dpy->have_fbconfig)
    548             GLX_dpy->have_pbuffer = EGL_TRUE;
    549       }
    550    }
    551 
    552    if (GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3) {
    553       GLX_dpy->have_1_3 = EGL_TRUE;
    554       GLX_dpy->have_make_current_read = EGL_TRUE;
    555       GLX_dpy->have_fbconfig = EGL_TRUE;
    556       GLX_dpy->have_pbuffer = EGL_TRUE;
    557    }
    558 }
    559 
    560 
    561 static void
    562 check_quirks(struct GLX_egl_driver *GLX_drv,
    563              struct GLX_egl_display *GLX_dpy, EGLint screen)
    564 {
    565    const char *vendor;
    566 
    567    GLX_dpy->single_buffered_quirk = EGL_TRUE;
    568    GLX_dpy->glx_window_quirk = EGL_TRUE;
    569 
    570    vendor = GLX_drv->glXGetClientString(GLX_dpy->dpy, GLX_VENDOR);
    571    if (vendor && strstr(vendor, "NVIDIA")) {
    572       vendor = GLX_drv->glXQueryServerString(GLX_dpy->dpy, screen, GLX_VENDOR);
    573       if (vendor && strstr(vendor, "NVIDIA")) {
    574          _eglLog(_EGL_DEBUG, "disable quirks");
    575          GLX_dpy->single_buffered_quirk = EGL_FALSE;
    576          GLX_dpy->glx_window_quirk = EGL_FALSE;
    577       }
    578    }
    579 }
    580 
    581 
    582 /**
    583  * Called via eglInitialize(), GLX_drv->API.Initialize().
    584  */
    585 static EGLBoolean
    586 GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp)
    587 {
    588    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
    589    struct GLX_egl_display *GLX_dpy;
    590 
    591    if (disp->Platform != _EGL_PLATFORM_X11)
    592       return EGL_FALSE;
    593 
    594    /* this is a fallback driver */
    595    if (!disp->Options.UseFallback)
    596       return EGL_FALSE;
    597 
    598    if (disp->Options.TestOnly)
    599       return EGL_TRUE;
    600 
    601    GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
    602    if (!GLX_dpy)
    603       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
    604 
    605    GLX_dpy->dpy = (Display *) disp->PlatformDisplay;
    606    if (!GLX_dpy->dpy) {
    607       GLX_dpy->dpy = XOpenDisplay(NULL);
    608       if (!GLX_dpy->dpy) {
    609          _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed");
    610          free(GLX_dpy);
    611          return EGL_FALSE;
    612       }
    613    }
    614 
    615    if (!GLX_drv->glXQueryVersion(GLX_dpy->dpy,
    616             &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
    617       _eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
    618       if (!disp->PlatformDisplay)
    619          XCloseDisplay(GLX_dpy->dpy);
    620       free(GLX_dpy);
    621       return EGL_FALSE;
    622    }
    623 
    624    disp->DriverData = (void *) GLX_dpy;
    625    disp->ClientAPIs = EGL_OPENGL_BIT;
    626 
    627    check_extensions(GLX_drv, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
    628    check_quirks(GLX_drv, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
    629 
    630    create_configs(drv, disp, DefaultScreen(GLX_dpy->dpy));
    631    if (!_eglGetArraySize(disp->Configs)) {
    632       _eglLog(_EGL_WARNING, "GLX: failed to create any config");
    633       if (!disp->PlatformDisplay)
    634          XCloseDisplay(GLX_dpy->dpy);
    635       free(GLX_dpy);
    636       return EGL_FALSE;
    637    }
    638 
    639    /* we're supporting EGL 1.4 */
    640    disp->VersionMajor = 1;
    641    disp->VersionMinor = 4;
    642 
    643    return EGL_TRUE;
    644 }
    645 
    646 
    647 /**
    648  * Called via eglTerminate(), drv->API.Terminate().
    649  */
    650 static EGLBoolean
    651 GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
    652 {
    653    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    654 
    655    _eglReleaseDisplayResources(drv, disp);
    656    _eglCleanupDisplay(disp);
    657 
    658    if (GLX_dpy->visuals)
    659       XFree(GLX_dpy->visuals);
    660    if (GLX_dpy->fbconfigs)
    661       XFree(GLX_dpy->fbconfigs);
    662 
    663    if (!disp->PlatformDisplay)
    664       XCloseDisplay(GLX_dpy->dpy);
    665    free(GLX_dpy);
    666 
    667    disp->DriverData = NULL;
    668 
    669    return EGL_TRUE;
    670 }
    671 
    672 
    673 /**
    674  * Called via eglCreateContext(), drv->API.CreateContext().
    675  */
    676 static _EGLContext *
    677 GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
    678                       _EGLContext *share_list, const EGLint *attrib_list)
    679 {
    680    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
    681    struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
    682    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    683    struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list);
    684 
    685    if (!GLX_ctx) {
    686       _eglError(EGL_BAD_ALLOC, "eglCreateContext");
    687       return NULL;
    688    }
    689 
    690    if (!_eglInitContext(&GLX_ctx->Base, disp, conf, attrib_list)) {
    691       free(GLX_ctx);
    692       return NULL;
    693    }
    694 
    695    if (GLX_dpy->have_fbconfig) {
    696       GLX_ctx->context = GLX_drv->glXCreateNewContext(GLX_dpy->dpy,
    697             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
    698             GLX_RGBA_TYPE,
    699             GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
    700             GL_TRUE);
    701    }
    702    else {
    703       GLX_ctx->context = GLX_drv->glXCreateContext(GLX_dpy->dpy,
    704             &GLX_dpy->visuals[GLX_egl_config_index(conf)],
    705             GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
    706             GL_TRUE);
    707    }
    708    if (!GLX_ctx->context) {
    709       free(GLX_ctx);
    710       return NULL;
    711    }
    712 
    713    return &GLX_ctx->Base;
    714 }
    715 
    716 /**
    717  * Called via eglDestroyContext(), drv->API.DestroyContext().
    718  */
    719 static EGLBoolean
    720 GLX_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
    721 {
    722    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
    723    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    724    struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
    725 
    726    if (_eglPutContext(ctx)) {
    727       assert(GLX_ctx);
    728       GLX_drv->glXDestroyContext(GLX_dpy->dpy, GLX_ctx->context);
    729 
    730       free(GLX_ctx);
    731    }
    732 
    733    return EGL_TRUE;
    734 }
    735 
    736 /**
    737  * Destroy a surface.  The display is allowed to be uninitialized.
    738  */
    739 static void
    740 destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
    741 {
    742    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    743    struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
    744 
    745    if (GLX_surf->destroy)
    746       GLX_surf->destroy(GLX_dpy->dpy, GLX_surf->glx_drawable);
    747 
    748    free(GLX_surf);
    749 }
    750 
    751 
    752 /**
    753  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
    754  */
    755 static EGLBoolean
    756 GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
    757                    _EGLSurface *rsurf, _EGLContext *ctx)
    758 {
    759    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
    760    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    761    struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
    762    struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
    763    struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
    764    _EGLContext *old_ctx;
    765    _EGLSurface *old_dsurf, *old_rsurf;
    766    GLXDrawable ddraw, rdraw;
    767    GLXContext cctx;
    768    EGLBoolean ret = EGL_FALSE;
    769 
    770    /* make new bindings */
    771    if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
    772       return EGL_FALSE;
    773 
    774    ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None;
    775    rdraw = (GLX_rsurf) ? GLX_rsurf->glx_drawable : None;
    776    cctx = (GLX_ctx) ? GLX_ctx->context : NULL;
    777 
    778    if (GLX_dpy->have_make_current_read)
    779       ret = GLX_drv->glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx);
    780    else if (ddraw == rdraw)
    781       ret = GLX_drv->glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx);
    782 
    783    if (ret) {
    784       if (_eglPutSurface(old_dsurf))
    785          destroy_surface(disp, old_dsurf);
    786       if (_eglPutSurface(old_rsurf))
    787          destroy_surface(disp, old_rsurf);
    788       /* no destroy? */
    789       _eglPutContext(old_ctx);
    790    }
    791    else {
    792       /* undo the previous _eglBindContext */
    793       _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
    794       assert(&GLX_ctx->Base == ctx &&
    795              &GLX_dsurf->Base == dsurf &&
    796              &GLX_rsurf->Base == rsurf);
    797 
    798       _eglPutSurface(dsurf);
    799       _eglPutSurface(rsurf);
    800       _eglPutContext(ctx);
    801 
    802       _eglPutSurface(old_dsurf);
    803       _eglPutSurface(old_rsurf);
    804       _eglPutContext(old_ctx);
    805    }
    806 
    807    return ret;
    808 }
    809 
    810 /** Get size of given window */
    811 static Status
    812 get_drawable_size(Display *dpy, Drawable d, unsigned *width, unsigned *height)
    813 {
    814    Window root;
    815    Status stat;
    816    int xpos, ypos;
    817    unsigned int w, h, bw, depth;
    818    stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
    819    *width = w;
    820    *height = h;
    821    return stat;
    822 }
    823 
    824 /**
    825  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
    826  */
    827 static _EGLSurface *
    828 GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp,
    829                            _EGLConfig *conf, EGLNativeWindowType window,
    830                            const EGLint *attrib_list)
    831 {
    832    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
    833    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    834    struct GLX_egl_surface *GLX_surf;
    835    unsigned width, height;
    836 
    837    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
    838    if (!GLX_surf) {
    839       _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
    840       return NULL;
    841    }
    842 
    843    if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_WINDOW_BIT,
    844                         conf, attrib_list)) {
    845       free(GLX_surf);
    846       return NULL;
    847    }
    848 
    849    GLX_surf->drawable = window;
    850 
    851    if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk) {
    852       GLX_surf->glx_drawable = GLX_drv->glXCreateWindow(GLX_dpy->dpy,
    853             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
    854             GLX_surf->drawable, NULL);
    855    }
    856    else {
    857       GLX_surf->glx_drawable = GLX_surf->drawable;
    858    }
    859 
    860    if (!GLX_surf->glx_drawable) {
    861       free(GLX_surf);
    862       return NULL;
    863    }
    864 
    865    if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk)
    866       GLX_surf->destroy = GLX_drv->glXDestroyWindow;
    867 
    868    get_drawable_size(GLX_dpy->dpy, window, &width, &height);
    869    GLX_surf->Base.Width = width;
    870    GLX_surf->Base.Height = height;
    871 
    872    return &GLX_surf->Base;
    873 }
    874 
    875 static _EGLSurface *
    876 GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp,
    877                            _EGLConfig *conf, EGLNativePixmapType pixmap,
    878                            const EGLint *attrib_list)
    879 {
    880    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
    881    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    882    struct GLX_egl_surface *GLX_surf;
    883    unsigned width, height;
    884 
    885    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
    886    if (!GLX_surf) {
    887       _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
    888       return NULL;
    889    }
    890 
    891    if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PIXMAP_BIT,
    892                         conf, attrib_list)) {
    893       free(GLX_surf);
    894       return NULL;
    895    }
    896 
    897    GLX_surf->drawable = pixmap;
    898 
    899    if (GLX_dpy->have_1_3) {
    900       GLX_surf->glx_drawable = GLX_drv->glXCreatePixmap(GLX_dpy->dpy,
    901             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
    902             GLX_surf->drawable, NULL);
    903    }
    904    else if (GLX_dpy->have_fbconfig) {
    905       GLXFBConfig fbconfig = GLX_dpy->fbconfigs[GLX_egl_config_index(conf)];
    906       XVisualInfo *vinfo;
    907 
    908       vinfo = GLX_drv->glXGetVisualFromFBConfig(GLX_dpy->dpy, fbconfig);
    909       if (vinfo) {
    910          GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy,
    911                vinfo, GLX_surf->drawable);
    912          XFree(vinfo);
    913       }
    914    }
    915    else {
    916       GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy,
    917             &GLX_dpy->visuals[GLX_egl_config_index(conf)],
    918             GLX_surf->drawable);
    919    }
    920 
    921    if (!GLX_surf->glx_drawable) {
    922       free(GLX_surf);
    923       return NULL;
    924    }
    925 
    926    GLX_surf->destroy = (GLX_dpy->have_1_3) ?
    927       GLX_drv->glXDestroyPixmap : GLX_drv->glXDestroyGLXPixmap;
    928 
    929    get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height);
    930    GLX_surf->Base.Width = width;
    931    GLX_surf->Base.Height = height;
    932 
    933    return &GLX_surf->Base;
    934 }
    935 
    936 static _EGLSurface *
    937 GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
    938                             _EGLConfig *conf, const EGLint *attrib_list)
    939 {
    940    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
    941    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    942    struct GLX_egl_surface *GLX_surf;
    943    int attribs[5];
    944    int i;
    945 
    946    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
    947    if (!GLX_surf) {
    948       _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
    949       return NULL;
    950    }
    951 
    952    if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PBUFFER_BIT,
    953                         conf, attrib_list)) {
    954       free(GLX_surf);
    955       return NULL;
    956    }
    957 
    958    i = 0;
    959    attribs[i] = None;
    960 
    961    GLX_surf->drawable = None;
    962 
    963    if (GLX_dpy->have_1_3) {
    964       /* put geometry in attribs */
    965       if (GLX_surf->Base.Width) {
    966          attribs[i++] = GLX_PBUFFER_WIDTH;
    967          attribs[i++] = GLX_surf->Base.Width;
    968       }
    969       if (GLX_surf->Base.Height) {
    970          attribs[i++] = GLX_PBUFFER_HEIGHT;
    971          attribs[i++] = GLX_surf->Base.Height;
    972       }
    973       attribs[i] = None;
    974 
    975       GLX_surf->glx_drawable = GLX_drv->glXCreatePbuffer(GLX_dpy->dpy,
    976             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], attribs);
    977    }
    978    else if (GLX_dpy->have_pbuffer) {
    979       GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPbufferSGIX(GLX_dpy->dpy,
    980             GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
    981             GLX_surf->Base.Width,
    982             GLX_surf->Base.Height,
    983             attribs);
    984    }
    985 
    986    if (!GLX_surf->glx_drawable) {
    987       free(GLX_surf);
    988       return NULL;
    989    }
    990 
    991    GLX_surf->destroy = (GLX_dpy->have_1_3) ?
    992       GLX_drv->glXDestroyPbuffer : GLX_drv->glXDestroyGLXPbufferSGIX;
    993 
    994    return &GLX_surf->Base;
    995 }
    996 
    997 
    998 static EGLBoolean
    999 GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
   1000 {
   1001    (void) drv;
   1002 
   1003    if (_eglPutSurface(surf))
   1004       destroy_surface(disp, surf);
   1005 
   1006    return EGL_TRUE;
   1007 }
   1008 
   1009 
   1010 static EGLBoolean
   1011 GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
   1012 {
   1013    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
   1014    struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
   1015    struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
   1016 
   1017    GLX_drv->glXSwapBuffers(GLX_dpy->dpy, GLX_surf->glx_drawable);
   1018 
   1019    return EGL_TRUE;
   1020 }
   1021 
   1022 /*
   1023  * Called from eglGetProcAddress() via drv->API.GetProcAddress().
   1024  */
   1025 static _EGLProc
   1026 GLX_eglGetProcAddress(_EGLDriver *drv, const char *procname)
   1027 {
   1028    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
   1029 
   1030    return (_EGLProc) GLX_drv->glXGetProcAddress((const GLubyte *) procname);
   1031 }
   1032 
   1033 static EGLBoolean
   1034 GLX_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
   1035 {
   1036    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
   1037 
   1038    (void) dpy;
   1039    (void) ctx;
   1040 
   1041    GLX_drv->glXWaitGL();
   1042    return EGL_TRUE;
   1043 }
   1044 
   1045 static EGLBoolean
   1046 GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
   1047 {
   1048    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
   1049 
   1050    (void) dpy;
   1051 
   1052    if (engine != EGL_CORE_NATIVE_ENGINE)
   1053       return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
   1054    GLX_drv->glXWaitX();
   1055    return EGL_TRUE;
   1056 }
   1057 
   1058 static void
   1059 GLX_Unload(_EGLDriver *drv)
   1060 {
   1061    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
   1062 
   1063    if (GLX_drv->handle)
   1064       dlclose(GLX_drv->handle);
   1065    free(GLX_drv);
   1066 }
   1067 
   1068 
   1069 static EGLBoolean
   1070 GLX_Load(_EGLDriver *drv)
   1071 {
   1072    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
   1073    void *handle = NULL;
   1074 
   1075    GLX_drv->glXGetProcAddress = dlsym(RTLD_DEFAULT, "glXGetProcAddress");
   1076    if (!GLX_drv->glXGetProcAddress)
   1077       GLX_drv->glXGetProcAddress = dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
   1078    if (!GLX_drv->glXGetProcAddress) {
   1079       handle = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
   1080       if (!handle)
   1081          goto fail;
   1082 
   1083       GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddress");
   1084       if (!GLX_drv->glXGetProcAddress)
   1085          GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddressARB");
   1086       if (!GLX_drv->glXGetProcAddress)
   1087          goto fail;
   1088    }
   1089 
   1090 #define GET_PROC(proc_type, proc_name, check)                        \
   1091    do {                                                              \
   1092       GLX_drv->proc_name = (proc_type)                               \
   1093          GLX_drv->glXGetProcAddress((const GLubyte *) #proc_name);   \
   1094       if (check && !GLX_drv->proc_name) goto fail;                   \
   1095    } while (0)
   1096 
   1097    /* GLX 1.0 */
   1098    GET_PROC(GLXCREATECONTEXTPROC, glXCreateContext, EGL_TRUE);
   1099    GET_PROC(GLXDESTROYCONTEXTPROC, glXDestroyContext, EGL_TRUE);
   1100    GET_PROC(GLXMAKECURRENTPROC, glXMakeCurrent, EGL_TRUE);
   1101    GET_PROC(GLXSWAPBUFFERSPROC, glXSwapBuffers, EGL_TRUE);
   1102    GET_PROC(GLXCREATEGLXPIXMAPPROC, glXCreateGLXPixmap, EGL_TRUE);
   1103    GET_PROC(GLXDESTROYGLXPIXMAPPROC, glXDestroyGLXPixmap, EGL_TRUE);
   1104    GET_PROC(GLXQUERYVERSIONPROC, glXQueryVersion, EGL_TRUE);
   1105    GET_PROC(GLXGETCONFIGPROC, glXGetConfig, EGL_TRUE);
   1106    GET_PROC(GLXWAITGLPROC, glXWaitGL, EGL_TRUE);
   1107    GET_PROC(GLXWAITXPROC, glXWaitX, EGL_TRUE);
   1108 
   1109    /* GLX 1.1 */
   1110    GET_PROC(GLXQUERYEXTENSIONSSTRINGPROC, glXQueryExtensionsString, EGL_TRUE);
   1111    GET_PROC(GLXQUERYSERVERSTRINGPROC, glXQueryServerString, EGL_TRUE);
   1112    GET_PROC(GLXGETCLIENTSTRINGPROC, glXGetClientString, EGL_TRUE);
   1113 
   1114    /* GLX 1.3 */
   1115    GET_PROC(PFNGLXGETFBCONFIGSPROC, glXGetFBConfigs, EGL_FALSE);
   1116    GET_PROC(PFNGLXGETFBCONFIGATTRIBPROC, glXGetFBConfigAttrib, EGL_FALSE);
   1117    GET_PROC(PFNGLXGETVISUALFROMFBCONFIGPROC, glXGetVisualFromFBConfig, EGL_FALSE);
   1118    GET_PROC(PFNGLXCREATEWINDOWPROC, glXCreateWindow, EGL_FALSE);
   1119    GET_PROC(PFNGLXDESTROYWINDOWPROC, glXDestroyWindow, EGL_FALSE);
   1120    GET_PROC(PFNGLXCREATEPIXMAPPROC, glXCreatePixmap, EGL_FALSE);
   1121    GET_PROC(PFNGLXDESTROYPIXMAPPROC, glXDestroyPixmap, EGL_FALSE);
   1122    GET_PROC(PFNGLXCREATEPBUFFERPROC, glXCreatePbuffer, EGL_FALSE);
   1123    GET_PROC(PFNGLXDESTROYPBUFFERPROC, glXDestroyPbuffer, EGL_FALSE);
   1124    GET_PROC(PFNGLXCREATENEWCONTEXTPROC, glXCreateNewContext, EGL_FALSE);
   1125    GET_PROC(PFNGLXMAKECONTEXTCURRENTPROC, glXMakeContextCurrent, EGL_FALSE);
   1126 
   1127    /* GLX_SGIX_pbuffer */
   1128    GET_PROC(PFNGLXCREATEGLXPBUFFERSGIXPROC,
   1129          glXCreateGLXPbufferSGIX, EGL_FALSE);
   1130    GET_PROC(PFNGLXDESTROYGLXPBUFFERSGIXPROC,
   1131          glXDestroyGLXPbufferSGIX, EGL_FALSE);
   1132 #undef GET_PROC
   1133 
   1134    GLX_drv->handle = handle;
   1135 
   1136    return EGL_TRUE;
   1137 
   1138 fail:
   1139    if (handle)
   1140       dlclose(handle);
   1141    return EGL_FALSE;
   1142 }
   1143 
   1144 
   1145 /**
   1146  * This is the main entrypoint into the driver, called by libEGL.
   1147  * Create a new _EGLDriver object and init its dispatch table.
   1148  */
   1149 _EGLDriver *
   1150 _eglBuiltInDriverGLX(const char *args)
   1151 {
   1152    struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
   1153 
   1154    (void) args;
   1155 
   1156    if (!GLX_drv)
   1157       return NULL;
   1158 
   1159    if (!GLX_Load(&GLX_drv->Base)) {
   1160       _eglLog(_EGL_WARNING, "GLX: failed to load GLX");
   1161       free(GLX_drv);
   1162       return NULL;
   1163    }
   1164 
   1165    _eglInitDriverFallbacks(&GLX_drv->Base);
   1166    GLX_drv->Base.API.Initialize = GLX_eglInitialize;
   1167    GLX_drv->Base.API.Terminate = GLX_eglTerminate;
   1168    GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
   1169    GLX_drv->Base.API.DestroyContext = GLX_eglDestroyContext;
   1170    GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
   1171    GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
   1172    GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
   1173    GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
   1174    GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
   1175    GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
   1176    GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
   1177    GLX_drv->Base.API.WaitClient = GLX_eglWaitClient;
   1178    GLX_drv->Base.API.WaitNative = GLX_eglWaitNative;
   1179 
   1180    GLX_drv->Base.Name = "GLX";
   1181    GLX_drv->Base.Unload = GLX_Unload;
   1182 
   1183    return &GLX_drv->Base;
   1184 }
   1185