1 /**************************************************************************
2  *
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * Copyright 2009-2010 Chia-I Wu <olvaffe@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@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 */
_EGL_DRIVER_STANDARD_TYPECASTS(GLX_egl)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
convert_fbconfig(struct GLX_egl_driver * GLX_drv,struct GLX_egl_display * GLX_dpy,GLXFBConfig fbconfig,struct GLX_egl_config * GLX_conf)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
convert_visual(struct GLX_egl_driver * GLX_drv,struct GLX_egl_display * GLX_dpy,XVisualInfo * vinfo,struct GLX_egl_config * GLX_conf)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
fix_config(struct GLX_egl_display * GLX_dpy,struct GLX_egl_config * GLX_conf)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
create_configs(_EGLDriver * drv,_EGLDisplay * dpy,EGLint screen)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
check_extensions(struct GLX_egl_driver * GLX_drv,struct GLX_egl_display * GLX_dpy,EGLint screen)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
check_quirks(struct GLX_egl_driver * GLX_drv,struct GLX_egl_display * GLX_dpy,EGLint screen)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
GLX_eglInitialize(_EGLDriver * drv,_EGLDisplay * disp)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
GLX_eglTerminate(_EGLDriver * drv,_EGLDisplay * disp)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 *
GLX_eglCreateContext(_EGLDriver * drv,_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)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
GLX_eglDestroyContext(_EGLDriver * drv,_EGLDisplay * disp,_EGLContext * ctx)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
destroy_surface(_EGLDisplay * disp,_EGLSurface * surf)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
GLX_eglMakeCurrent(_EGLDriver * drv,_EGLDisplay * disp,_EGLSurface * dsurf,_EGLSurface * rsurf,_EGLContext * ctx)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
get_drawable_size(Display * dpy,Drawable d,unsigned * width,unsigned * height)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 *
GLX_eglCreateWindowSurface(_EGLDriver * drv,_EGLDisplay * disp,_EGLConfig * conf,EGLNativeWindowType window,const EGLint * attrib_list)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 *
GLX_eglCreatePixmapSurface(_EGLDriver * drv,_EGLDisplay * disp,_EGLConfig * conf,EGLNativePixmapType pixmap,const EGLint * attrib_list)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 *
GLX_eglCreatePbufferSurface(_EGLDriver * drv,_EGLDisplay * disp,_EGLConfig * conf,const EGLint * attrib_list)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
GLX_eglDestroySurface(_EGLDriver * drv,_EGLDisplay * disp,_EGLSurface * surf)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
GLX_eglSwapBuffers(_EGLDriver * drv,_EGLDisplay * disp,_EGLSurface * draw)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
GLX_eglGetProcAddress(_EGLDriver * drv,const char * procname)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
GLX_eglWaitClient(_EGLDriver * drv,_EGLDisplay * dpy,_EGLContext * ctx)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
GLX_eglWaitNative(_EGLDriver * drv,_EGLDisplay * dpy,EGLint engine)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
GLX_Unload(_EGLDriver * drv)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
GLX_Load(_EGLDriver * drv)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 *
_eglBuiltInDriverGLX(const char * args)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