1 /**************************************************************************
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.
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:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
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.
28 **************************************************************************/
32 * This is an EGL driver that wraps GLX. This gives the benefit of being
33 * completely agnostic of the direct rendering implementation.
35 * Authors: Alan Hourihane <alanh@tungstengraphics.com>
44 #include "eglconfig.h"
45 #include "eglcontext.h"
46 #include "egldefines.h"
47 #include "egldisplay.h"
48 #include "egldriver.h"
49 #include "eglcurrent.h"
51 #include "eglsurface.h"
53 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
55 #ifndef GLX_VERSION_1_4
56 #error "GL/glx.h must be equal to or greater than GLX 1.4"
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 );
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
);
76 /** subclass of _EGLDriver */
79 _EGLDriver Base
; /**< base class */
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
;
96 GLXQUERYEXTENSIONSSTRINGPROC glXQueryExtensionsString
;
97 GLXQUERYSERVERSTRINGPROC glXQueryServerString
;
98 GLXGETCLIENTSTRINGPROC glXGetClientString
;
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
;
113 /* GLX 1.4 or GLX_ARB_get_proc_address */
114 PFNGLXGETPROCADDRESSPROC glXGetProcAddress
;
116 /* GLX_SGIX_pbuffer */
117 PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX
;
118 PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX
;
122 /** driver data of _EGLDisplay */
123 struct GLX_egl_display
126 XVisualInfo
*visuals
;
127 GLXFBConfig
*fbconfigs
;
129 int glx_maj
, glx_min
;
131 const char *extensions
;
133 EGLBoolean have_make_current_read
;
134 EGLBoolean have_fbconfig
;
135 EGLBoolean have_pbuffer
;
137 /* workaround quirks of different GLX implementations */
138 EGLBoolean single_buffered_quirk
;
139 EGLBoolean glx_window_quirk
;
143 /** subclass of _EGLContext */
144 struct GLX_egl_context
146 _EGLContext Base
; /**< base class */
152 /** subclass of _EGLSurface */
153 struct GLX_egl_surface
155 _EGLSurface Base
; /**< base class */
158 GLXDrawable glx_drawable
;
160 void (*destroy
)(Display
*, GLXDrawable
);
164 /** subclass of _EGLConfig */
165 struct GLX_egl_config
167 _EGLConfig Base
; /**< base class */
168 EGLBoolean double_buffered
;
172 /* standard typecasts */
173 _EGL_DRIVER_STANDARD_TYPECASTS(GLX_egl
)
176 GLX_egl_config_index(_EGLConfig
*conf
)
178 struct GLX_egl_config
*GLX_conf
= GLX_egl_config(conf
);
179 return GLX_conf
->index
;
183 static const struct {
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 },
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
}
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
)
228 Display
*dpy
= GLX_dpy
->dpy
;
232 /* must have rgba bit */
233 err
= GLX_drv
->glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_RENDER_TYPE
, &val
);
234 if (err
|| !(val
& GLX_RGBA_BIT
))
237 /* must know whether it is double-buffered */
238 err
= GLX_drv
->glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_DOUBLEBUFFER
, &val
);
241 GLX_conf
->double_buffered
= val
;
243 GLX_conf
->Base
.RenderableType
= EGL_OPENGL_BIT
;
244 GLX_conf
->Base
.Conformant
= EGL_OPENGL_BIT
;
246 for (i
= 0; i
< ARRAY_SIZE(fbconfig_attributes
); i
++) {
247 EGLint egl_attr
, egl_val
;
249 attr
= fbconfig_attributes
[i
].attr
;
250 egl_attr
= fbconfig_attributes
[i
].egl_attr
;
254 err
= GLX_drv
->glXGetFBConfigAttrib(dpy
, fbconfig
, attr
, &val
);
256 if (err
== GLX_BAD_ATTRIBUTE
) {
264 case EGL_SURFACE_TYPE
:
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
;
276 case EGL_NATIVE_VISUAL_TYPE
:
281 case GLX_DIRECT_COLOR
:
282 egl_val
= DirectColor
;
284 case GLX_PSEUDO_COLOR
:
285 egl_val
= PseudoColor
;
287 case GLX_STATIC_COLOR
:
288 egl_val
= StaticColor
;
293 case GLX_STATIC_GRAY
:
294 egl_val
= StaticGray
;
301 case EGL_CONFIG_CAVEAT
:
303 if (val
== GLX_SLOW_CONFIG
) {
304 egl_val
= EGL_SLOW_CONFIG
;
306 else if (val
== GLX_NON_CONFORMANT_CONFIG
) {
307 GLX_conf
->Base
.Conformant
&= ~EGL_OPENGL_BIT
;
311 case EGL_TRANSPARENT_TYPE
:
312 egl_val
= (val
== GLX_TRANSPARENT_RGB
) ?
313 EGL_TRANSPARENT_RGB
: EGL_NONE
;
320 _eglSetConfigKey(&GLX_conf
->Base
, egl_attr
, egl_val
);
325 if (!GLX_conf
->Base
.SurfaceType
)
331 static const struct {
334 } visual_attributes
[] = {
335 /* table 3.7 of GLX 1.4 */
337 { GLX_BUFFER_SIZE
, EGL_BUFFER_SIZE
},
338 { GLX_LEVEL
, EGL_LEVEL
},
340 { GLX_DOUBLEBUFFER
, 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
}
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
)
365 Display
*dpy
= GLX_dpy
->dpy
;
369 /* the visual must support OpenGL and RGBA buffer */
370 err
= GLX_drv
->glXGetConfig(dpy
, vinfo
, GLX_USE_GL
, &val
);
372 err
= GLX_drv
->glXGetConfig(dpy
, vinfo
, GLX_RGBA
, &val
);
376 /* must know whether it is double-buffered */
377 err
= GLX_drv
->glXGetConfig(dpy
, vinfo
, GLX_DOUBLEBUFFER
, &val
);
380 GLX_conf
->double_buffered
= val
;
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
;
389 GLX_conf
->Base
.NativeVisualID
= vinfo
->visualid
;
390 GLX_conf
->Base
.NativeVisualType
= vinfo
->class;
391 GLX_conf
->Base
.NativeRenderable
= EGL_TRUE
;
393 for (i
= 0; i
< ARRAY_SIZE(visual_attributes
); i
++) {
394 EGLint egl_attr
, egl_val
;
396 attr
= visual_attributes
[i
].attr
;
397 egl_attr
= visual_attributes
[i
].egl_attr
;
401 err
= GLX_drv
->glXGetConfig(dpy
, vinfo
, attr
, &val
);
403 if (err
== GLX_BAD_ATTRIBUTE
) {
411 case EGL_CONFIG_CAVEAT
:
413 if (val
== GLX_SLOW_VISUAL_EXT
) {
414 egl_val
= EGL_SLOW_CONFIG
;
416 else if (val
== GLX_NON_CONFORMANT_VISUAL_EXT
) {
417 GLX_conf
->Base
.Conformant
&= ~EGL_OPENGL_BIT
;
426 _eglSetConfigKey(&GLX_conf
->Base
, egl_attr
, egl_val
);
429 return (err
) ? EGL_FALSE
: EGL_TRUE
;
434 fix_config(struct GLX_egl_display
*GLX_dpy
, struct GLX_egl_config
*GLX_conf
)
436 _EGLConfig
*conf
= &GLX_conf
->Base
;
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
;
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
;
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;
459 /* make sure buffer size is set correctly */
461 conf
->RedSize
+ conf
->GreenSize
+ conf
->BlueSize
+ conf
->AlphaSize
;
466 create_configs(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint screen
)
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
;
473 if (GLX_dpy
->have_fbconfig
) {
475 GLX_drv
->glXGetFBConfigs(GLX_dpy
->dpy
, screen
, &num_configs
);
478 XVisualInfo vinfo_template
;
481 vinfo_template
.screen
= screen
;
482 mask
= VisualScreenMask
;
483 GLX_dpy
->visuals
= XGetVisualInfo(GLX_dpy
->dpy
, mask
, &vinfo_template
,
490 for (i
= 0; i
< num_configs
; i
++) {
491 struct GLX_egl_config
*GLX_conf
, template;
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);
501 ok
= convert_visual(GLX_drv
, GLX_dpy
,
502 &GLX_dpy
->visuals
[i
], &template);
507 fix_config(GLX_dpy
, &template);
508 if (!_eglValidateConfig(&template.Base
, EGL_FALSE
)) {
509 _eglLog(_EGL_DEBUG
, "GLX: failed to validate config %d", i
);
513 GLX_conf
= CALLOC_STRUCT(GLX_egl_config
);
515 memcpy(GLX_conf
, &template, sizeof(template));
518 _eglLinkConfig(&GLX_conf
->Base
);
528 check_extensions(struct GLX_egl_driver
*GLX_drv
,
529 struct GLX_egl_display
*GLX_dpy
, EGLint screen
)
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
;
539 if (strstr(GLX_dpy
->extensions
, "GLX_SGIX_fbconfig")) {
540 /* GLX 1.3 entry points are used */
541 GLX_dpy
->have_fbconfig
= EGL_TRUE
;
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
;
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
;
562 check_quirks(struct GLX_egl_driver
*GLX_drv
,
563 struct GLX_egl_display
*GLX_dpy
, EGLint screen
)
567 GLX_dpy
->single_buffered_quirk
= EGL_TRUE
;
568 GLX_dpy
->glx_window_quirk
= EGL_TRUE
;
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
;
583 * Called via eglInitialize(), GLX_drv->API.Initialize().
586 GLX_eglInitialize(_EGLDriver
*drv
, _EGLDisplay
*disp
)
588 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
589 struct GLX_egl_display
*GLX_dpy
;
591 if (disp
->Platform
!= _EGL_PLATFORM_X11
)
594 /* this is a fallback driver */
595 if (!disp
->Options
.UseFallback
)
598 if (disp
->Options
.TestOnly
)
601 GLX_dpy
= CALLOC_STRUCT(GLX_egl_display
);
603 return _eglError(EGL_BAD_ALLOC
, "eglInitialize");
605 GLX_dpy
->dpy
= (Display
*) disp
->PlatformDisplay
;
607 GLX_dpy
->dpy
= XOpenDisplay(NULL
);
609 _eglLog(_EGL_WARNING
, "GLX: XOpenDisplay failed");
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
);
624 disp
->DriverData
= (void *) GLX_dpy
;
625 disp
->ClientAPIs
= EGL_OPENGL_BIT
;
627 check_extensions(GLX_drv
, GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
628 check_quirks(GLX_drv
, GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
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
);
639 /* we're supporting EGL 1.4 */
640 disp
->VersionMajor
= 1;
641 disp
->VersionMinor
= 4;
648 * Called via eglTerminate(), drv->API.Terminate().
651 GLX_eglTerminate(_EGLDriver
*drv
, _EGLDisplay
*disp
)
653 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
655 _eglReleaseDisplayResources(drv
, disp
);
656 _eglCleanupDisplay(disp
);
658 if (GLX_dpy
->visuals
)
659 XFree(GLX_dpy
->visuals
);
660 if (GLX_dpy
->fbconfigs
)
661 XFree(GLX_dpy
->fbconfigs
);
663 if (!disp
->PlatformDisplay
)
664 XCloseDisplay(GLX_dpy
->dpy
);
667 disp
->DriverData
= NULL
;
674 * Called via eglCreateContext(), drv->API.CreateContext().
677 GLX_eglCreateContext(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLConfig
*conf
,
678 _EGLContext
*share_list
, const EGLint
*attrib_list
)
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
);
686 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
690 if (!_eglInitContext(&GLX_ctx
->Base
, disp
, conf
, attrib_list
)) {
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
)],
699 GLX_ctx_shared
? GLX_ctx_shared
->context
: NULL
,
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
,
708 if (!GLX_ctx
->context
) {
713 return &GLX_ctx
->Base
;
717 * Called via eglDestroyContext(), drv->API.DestroyContext().
720 GLX_eglDestroyContext(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLContext
*ctx
)
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
);
726 if (_eglPutContext(ctx
)) {
728 GLX_drv
->glXDestroyContext(GLX_dpy
->dpy
, GLX_ctx
->context
);
737 * Destroy a surface. The display is allowed to be uninitialized.
740 destroy_surface(_EGLDisplay
*disp
, _EGLSurface
*surf
)
742 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
743 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(surf
);
745 if (GLX_surf
->destroy
)
746 GLX_surf
->destroy(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
753 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
756 GLX_eglMakeCurrent(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*dsurf
,
757 _EGLSurface
*rsurf
, _EGLContext
*ctx
)
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
;
768 EGLBoolean ret
= EGL_FALSE
;
770 /* make new bindings */
771 if (!_eglBindContext(ctx
, dsurf
, rsurf
, &old_ctx
, &old_dsurf
, &old_rsurf
))
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
;
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
);
784 if (_eglPutSurface(old_dsurf
))
785 destroy_surface(disp
, old_dsurf
);
786 if (_eglPutSurface(old_rsurf
))
787 destroy_surface(disp
, old_rsurf
);
789 _eglPutContext(old_ctx
);
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
);
798 _eglPutSurface(dsurf
);
799 _eglPutSurface(rsurf
);
802 _eglPutSurface(old_dsurf
);
803 _eglPutSurface(old_rsurf
);
804 _eglPutContext(old_ctx
);
810 /** Get size of given window */
812 get_drawable_size(Display
*dpy
, Drawable d
, unsigned *width
, unsigned *height
)
817 unsigned int w
, h
, bw
, depth
;
818 stat
= XGetGeometry(dpy
, d
, &root
, &xpos
, &ypos
, &w
, &h
, &bw
, &depth
);
825 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
828 GLX_eglCreateWindowSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
829 _EGLConfig
*conf
, EGLNativeWindowType window
,
830 const EGLint
*attrib_list
)
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
;
837 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
839 _eglError(EGL_BAD_ALLOC
, "eglCreateWindowSurface");
843 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_WINDOW_BIT
,
844 conf
, attrib_list
)) {
849 GLX_surf
->drawable
= window
;
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
);
857 GLX_surf
->glx_drawable
= GLX_surf
->drawable
;
860 if (!GLX_surf
->glx_drawable
) {
865 if (GLX_dpy
->have_1_3
&& !GLX_dpy
->glx_window_quirk
)
866 GLX_surf
->destroy
= GLX_drv
->glXDestroyWindow
;
868 get_drawable_size(GLX_dpy
->dpy
, window
, &width
, &height
);
869 GLX_surf
->Base
.Width
= width
;
870 GLX_surf
->Base
.Height
= height
;
872 return &GLX_surf
->Base
;
876 GLX_eglCreatePixmapSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
877 _EGLConfig
*conf
, EGLNativePixmapType pixmap
,
878 const EGLint
*attrib_list
)
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
;
885 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
887 _eglError(EGL_BAD_ALLOC
, "eglCreatePixmapSurface");
891 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_PIXMAP_BIT
,
892 conf
, attrib_list
)) {
897 GLX_surf
->drawable
= pixmap
;
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
);
904 else if (GLX_dpy
->have_fbconfig
) {
905 GLXFBConfig fbconfig
= GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)];
908 vinfo
= GLX_drv
->glXGetVisualFromFBConfig(GLX_dpy
->dpy
, fbconfig
);
910 GLX_surf
->glx_drawable
= GLX_drv
->glXCreateGLXPixmap(GLX_dpy
->dpy
,
911 vinfo
, GLX_surf
->drawable
);
916 GLX_surf
->glx_drawable
= GLX_drv
->glXCreateGLXPixmap(GLX_dpy
->dpy
,
917 &GLX_dpy
->visuals
[GLX_egl_config_index(conf
)],
921 if (!GLX_surf
->glx_drawable
) {
926 GLX_surf
->destroy
= (GLX_dpy
->have_1_3
) ?
927 GLX_drv
->glXDestroyPixmap
: GLX_drv
->glXDestroyGLXPixmap
;
929 get_drawable_size(GLX_dpy
->dpy
, pixmap
, &width
, &height
);
930 GLX_surf
->Base
.Width
= width
;
931 GLX_surf
->Base
.Height
= height
;
933 return &GLX_surf
->Base
;
937 GLX_eglCreatePbufferSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
938 _EGLConfig
*conf
, const EGLint
*attrib_list
)
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
;
946 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
948 _eglError(EGL_BAD_ALLOC
, "eglCreatePbufferSurface");
952 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_PBUFFER_BIT
,
953 conf
, attrib_list
)) {
961 GLX_surf
->drawable
= None
;
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
;
969 if (GLX_surf
->Base
.Height
) {
970 attribs
[i
++] = GLX_PBUFFER_HEIGHT
;
971 attribs
[i
++] = GLX_surf
->Base
.Height
;
975 GLX_surf
->glx_drawable
= GLX_drv
->glXCreatePbuffer(GLX_dpy
->dpy
,
976 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)], attribs
);
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
,
986 if (!GLX_surf
->glx_drawable
) {
991 GLX_surf
->destroy
= (GLX_dpy
->have_1_3
) ?
992 GLX_drv
->glXDestroyPbuffer
: GLX_drv
->glXDestroyGLXPbufferSGIX
;
994 return &GLX_surf
->Base
;
999 GLX_eglDestroySurface(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*surf
)
1003 if (_eglPutSurface(surf
))
1004 destroy_surface(disp
, surf
);
1011 GLX_eglSwapBuffers(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*draw
)
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
);
1017 GLX_drv
->glXSwapBuffers(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
1023 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
1026 GLX_eglGetProcAddress(_EGLDriver
*drv
, const char *procname
)
1028 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
1030 return (_EGLProc
) GLX_drv
->glXGetProcAddress((const GLubyte
*) procname
);
1034 GLX_eglWaitClient(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
1036 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
1041 GLX_drv
->glXWaitGL();
1046 GLX_eglWaitNative(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint engine
)
1048 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
1052 if (engine
!= EGL_CORE_NATIVE_ENGINE
)
1053 return _eglError(EGL_BAD_PARAMETER
, "eglWaitNative");
1054 GLX_drv
->glXWaitX();
1059 GLX_Unload(_EGLDriver
*drv
)
1061 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
1063 if (GLX_drv
->handle
)
1064 dlclose(GLX_drv
->handle
);
1070 GLX_Load(_EGLDriver
*drv
)
1072 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
1073 void *handle
= NULL
;
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
);
1083 GLX_drv
->glXGetProcAddress
= dlsym(handle
, "glXGetProcAddress");
1084 if (!GLX_drv
->glXGetProcAddress
)
1085 GLX_drv
->glXGetProcAddress
= dlsym(handle
, "glXGetProcAddressARB");
1086 if (!GLX_drv
->glXGetProcAddress
)
1090 #define GET_PROC(proc_type, proc_name, check) \
1092 GLX_drv->proc_name = (proc_type) \
1093 GLX_drv->glXGetProcAddress((const GLubyte *) #proc_name); \
1094 if (check && !GLX_drv->proc_name) goto fail; \
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
);
1110 GET_PROC(GLXQUERYEXTENSIONSSTRINGPROC
, glXQueryExtensionsString
, EGL_TRUE
);
1111 GET_PROC(GLXQUERYSERVERSTRINGPROC
, glXQueryServerString
, EGL_TRUE
);
1112 GET_PROC(GLXGETCLIENTSTRINGPROC
, glXGetClientString
, EGL_TRUE
);
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
);
1127 /* GLX_SGIX_pbuffer */
1128 GET_PROC(PFNGLXCREATEGLXPBUFFERSGIXPROC
,
1129 glXCreateGLXPbufferSGIX
, EGL_FALSE
);
1130 GET_PROC(PFNGLXDESTROYGLXPBUFFERSGIXPROC
,
1131 glXDestroyGLXPbufferSGIX
, EGL_FALSE
);
1134 GLX_drv
->handle
= handle
;
1146 * This is the main entrypoint into the driver, called by libEGL.
1147 * Create a new _EGLDriver object and init its dispatch table.
1150 _eglBuiltInDriverGLX(const char *args
)
1152 struct GLX_egl_driver
*GLX_drv
= CALLOC_STRUCT(GLX_egl_driver
);
1159 if (!GLX_Load(&GLX_drv
->Base
)) {
1160 _eglLog(_EGL_WARNING
, "GLX: failed to load GLX");
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
;
1180 GLX_drv
->Base
.Name
= "GLX";
1181 GLX_drv
->Base
.Unload
= GLX_Unload
;
1183 return &GLX_drv
->Base
;