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