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