1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * This is an EGL driver that wraps GLX. This gives the benefit of being
31 * completely agnostic of the direct rendering implementation.
33 * Authors: Alan Hourihane <alanh@tungstengraphics.com>
41 #include "eglconfigutil.h"
42 #include "eglconfig.h"
43 #include "eglcontext.h"
44 #include "egldisplay.h"
45 #include "egldriver.h"
46 #include "eglglobals.h"
48 #include "eglsurface.h"
50 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
51 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
53 #ifndef GLX_VERSION_1_4
54 #error "GL/glx.h must be equal to or greater than GLX 1.4"
58 * report OpenGL ES bits because apps usually forget to specify
59 * EGL_RENDERABLE_TYPE when choosing configs
61 #define GLX_EGL_APIS (EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)
64 /** subclass of _EGLDriver */
67 _EGLDriver Base
; /**< base class */
71 /** driver data of _EGLDisplay */
72 struct GLX_egl_display
76 GLXFBConfig
*fbconfigs
;
80 const char *extensions
;
82 EGLBoolean have_make_current_read
;
83 EGLBoolean have_fbconfig
;
84 EGLBoolean have_pbuffer
;
86 /* GLX_SGIX_pbuffer */
87 PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX
;
88 PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX
;
90 /* workaround quirks of different GLX implementations */
91 EGLBoolean single_buffered_quirk
;
92 EGLBoolean glx_window_quirk
;
97 /** subclass of _EGLContext */
98 struct GLX_egl_context
100 _EGLContext Base
; /**< base class */
106 /** subclass of _EGLSurface */
107 struct GLX_egl_surface
109 _EGLSurface Base
; /**< base class */
112 GLXDrawable glx_drawable
;
116 /** subclass of _EGLConfig */
117 struct GLX_egl_config
119 _EGLConfig Base
; /**< base class */
120 EGLBoolean double_buffered
;
125 static struct GLX_egl_driver
*
126 GLX_egl_driver(_EGLDriver
*drv
)
128 return (struct GLX_egl_driver
*) drv
;
131 static struct GLX_egl_display
*
132 GLX_egl_display(_EGLDisplay
*dpy
)
134 return (struct GLX_egl_display
*) dpy
->DriverData
;
137 static struct GLX_egl_context
*
138 GLX_egl_context(_EGLContext
*ctx
)
140 return (struct GLX_egl_context
*) ctx
;
143 static struct GLX_egl_surface
*
144 GLX_egl_surface(_EGLSurface
*surf
)
146 return (struct GLX_egl_surface
*) surf
;
150 GLX_egl_config_index(_EGLConfig
*conf
)
152 return ((struct GLX_egl_config
*) conf
)->index
;
156 #define MAP_ATTRIB(attr, memb) \
157 { attr, offsetof(__GLcontextModes, memb) }
160 static const struct {
163 } fbconfig_attributes
[] = {
164 /* table 3.1 of GLX 1.4 */
165 MAP_ATTRIB(GLX_FBCONFIG_ID
, fbconfigID
),
166 MAP_ATTRIB(GLX_BUFFER_SIZE
, rgbBits
),
167 MAP_ATTRIB(GLX_LEVEL
, level
),
168 MAP_ATTRIB(GLX_DOUBLEBUFFER
, doubleBufferMode
),
169 MAP_ATTRIB(GLX_STEREO
, stereoMode
),
170 MAP_ATTRIB(GLX_AUX_BUFFERS
, numAuxBuffers
),
171 MAP_ATTRIB(GLX_RED_SIZE
, redBits
),
172 MAP_ATTRIB(GLX_GREEN_SIZE
, greenBits
),
173 MAP_ATTRIB(GLX_BLUE_SIZE
, blueBits
),
174 MAP_ATTRIB(GLX_ALPHA_SIZE
, alphaBits
),
175 MAP_ATTRIB(GLX_DEPTH_SIZE
, depthBits
),
176 MAP_ATTRIB(GLX_STENCIL_SIZE
, stencilBits
),
177 MAP_ATTRIB(GLX_ACCUM_RED_SIZE
, accumRedBits
),
178 MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE
, accumGreenBits
),
179 MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE
, accumBlueBits
),
180 MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE
, accumAlphaBits
),
181 MAP_ATTRIB(GLX_SAMPLE_BUFFERS
, sampleBuffers
),
182 MAP_ATTRIB(GLX_SAMPLES
, samples
),
183 MAP_ATTRIB(GLX_RENDER_TYPE
, renderType
),
184 MAP_ATTRIB(GLX_DRAWABLE_TYPE
, drawableType
),
185 MAP_ATTRIB(GLX_X_RENDERABLE
, xRenderable
),
186 MAP_ATTRIB(GLX_X_VISUAL_TYPE
, visualType
),
187 MAP_ATTRIB(GLX_CONFIG_CAVEAT
, visualRating
),
188 MAP_ATTRIB(GLX_TRANSPARENT_TYPE
, transparentPixel
),
189 MAP_ATTRIB(GLX_TRANSPARENT_INDEX_VALUE
, transparentIndex
),
190 MAP_ATTRIB(GLX_TRANSPARENT_RED_VALUE
, transparentRed
),
191 MAP_ATTRIB(GLX_TRANSPARENT_GREEN_VALUE
, transparentGreen
),
192 MAP_ATTRIB(GLX_TRANSPARENT_BLUE_VALUE
, transparentBlue
),
193 MAP_ATTRIB(GLX_TRANSPARENT_ALPHA_VALUE
, transparentAlpha
),
194 MAP_ATTRIB(GLX_MAX_PBUFFER_WIDTH
, maxPbufferWidth
),
195 MAP_ATTRIB(GLX_MAX_PBUFFER_HEIGHT
, maxPbufferHeight
),
196 MAP_ATTRIB(GLX_MAX_PBUFFER_PIXELS
, maxPbufferPixels
),
197 MAP_ATTRIB(GLX_VISUAL_ID
, visualID
),
202 convert_fbconfig(Display
*dpy
, GLXFBConfig fbconfig
,
203 struct GLX_egl_config
*GLX_conf
)
205 __GLcontextModes mode
;
206 int err
= 0, attr
, val
, i
;
208 memset(&mode
, 0, sizeof(mode
));
210 for (i
= 0; i
< ARRAY_SIZE(fbconfig_attributes
); i
++) {
211 int offset
= fbconfig_attributes
[i
].offset
;
212 attr
= fbconfig_attributes
[i
].attr
;
213 err
= glXGetFBConfigAttrib(dpy
, fbconfig
, attr
, &val
);
215 if (err
== GLX_BAD_ATTRIBUTE
) {
221 *((int *) ((char *) &mode
+ offset
)) = val
;
226 /* must have rgba bit */
227 if (!(mode
.renderType
& GLX_RGBA_BIT
))
230 /* pixmap and pbuffer surfaces must be single-buffered in EGL */
231 if (mode
.doubleBufferMode
) {
232 mode
.drawableType
&= ~(GLX_PIXMAP_BIT
| GLX_PBUFFER_BIT
);
233 if (!mode
.drawableType
)
237 mode
.rgbMode
= GL_TRUE
;
238 mode
.haveAccumBuffer
= (mode
.accumRedBits
+
239 mode
.accumGreenBits
+
241 mode
.accumAlphaBits
> 0);
242 mode
.haveDepthBuffer
= (mode
.depthBits
> 0);
243 mode
.haveStencilBuffer
= (mode
.stencilBits
> 0);
245 GLX_conf
->double_buffered
= (mode
.doubleBufferMode
!= 0);
246 return _eglConfigFromContextModesRec(&GLX_conf
->Base
, &mode
,
247 GLX_EGL_APIS
, GLX_EGL_APIS
);
251 static const struct {
254 } visual_attributes
[] = {
255 /* table 3.7 of GLX 1.4 */
257 MAP_ATTRIB(GLX_BUFFER_SIZE
, rgbBits
),
258 MAP_ATTRIB(GLX_LEVEL
, level
),
259 MAP_ATTRIB(GLX_RGBA
, rgbMode
),
260 MAP_ATTRIB(GLX_DOUBLEBUFFER
, doubleBufferMode
),
261 MAP_ATTRIB(GLX_STEREO
, stereoMode
),
262 MAP_ATTRIB(GLX_AUX_BUFFERS
, numAuxBuffers
),
263 MAP_ATTRIB(GLX_RED_SIZE
, redBits
),
264 MAP_ATTRIB(GLX_GREEN_SIZE
, greenBits
),
265 MAP_ATTRIB(GLX_BLUE_SIZE
, blueBits
),
266 MAP_ATTRIB(GLX_ALPHA_SIZE
, alphaBits
),
267 MAP_ATTRIB(GLX_DEPTH_SIZE
, depthBits
),
268 MAP_ATTRIB(GLX_STENCIL_SIZE
, stencilBits
),
269 MAP_ATTRIB(GLX_ACCUM_RED_SIZE
, accumRedBits
),
270 MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE
, accumGreenBits
),
271 MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE
, accumBlueBits
),
272 MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE
, accumAlphaBits
),
273 MAP_ATTRIB(GLX_SAMPLE_BUFFERS
, sampleBuffers
),
274 MAP_ATTRIB(GLX_SAMPLES
, samples
),
275 MAP_ATTRIB(GLX_FBCONFIG_ID
, fbconfigID
),
276 /* GLX_EXT_visual_rating */
277 MAP_ATTRIB(GLX_VISUAL_CAVEAT_EXT
, visualRating
),
282 get_visual_type(const XVisualInfo
*vis
)
286 #if defined(__cplusplus) || defined(c_plusplus)
287 klass
= vis
->c_class
;
294 return GLX_TRUE_COLOR
;
296 return GLX_DIRECT_COLOR
;
298 return GLX_PSEUDO_COLOR
;
300 return GLX_STATIC_COLOR
;
302 return GLX_GRAY_SCALE
;
304 return GLX_STATIC_GRAY
;
312 convert_visual(Display
*dpy
, XVisualInfo
*vinfo
,
313 struct GLX_egl_config
*GLX_conf
)
315 __GLcontextModes mode
;
316 int err
, attr
, val
, i
;
318 /* the visual must support OpenGL */
319 err
= glXGetConfig(dpy
, vinfo
, GLX_USE_GL
, &val
);
323 memset(&mode
, 0, sizeof(mode
));
325 for (i
= 0; i
< ARRAY_SIZE(visual_attributes
); i
++) {
326 int offset
= visual_attributes
[i
].offset
;
327 attr
= visual_attributes
[i
].attr
;
328 err
= glXGetConfig(dpy
, vinfo
, attr
, &val
);
330 if (err
== GLX_BAD_ATTRIBUTE
) {
336 *((int *) ((char *) &mode
+ offset
)) = val
;
341 /* must be RGB mode */
345 mode
.visualID
= vinfo
->visualid
;
346 mode
.visualType
= get_visual_type(vinfo
);
347 mode
.redMask
= vinfo
->red_mask
;
348 mode
.greenMask
= vinfo
->green_mask
;
349 mode
.blueMask
= vinfo
->blue_mask
;
351 mode
.drawableType
= GLX_WINDOW_BIT
;
352 /* pixmap surfaces must be single-buffered in EGL */
353 if (!mode
.doubleBufferMode
)
354 mode
.drawableType
|= GLX_PIXMAP_BIT
;
356 mode
.renderType
= GLX_RGBA_BIT
;
357 mode
.xRenderable
= GL_TRUE
;
358 mode
.haveAccumBuffer
= (mode
.accumRedBits
+
359 mode
.accumGreenBits
+
361 mode
.accumAlphaBits
> 0);
362 mode
.haveDepthBuffer
= (mode
.depthBits
> 0);
363 mode
.haveStencilBuffer
= (mode
.stencilBits
> 0);
365 GLX_conf
->double_buffered
= (mode
.doubleBufferMode
!= 0);
366 return _eglConfigFromContextModesRec(&GLX_conf
->Base
, &mode
,
367 GLX_EGL_APIS
, GLX_EGL_APIS
);
372 fix_config(struct GLX_egl_display
*GLX_dpy
, struct GLX_egl_config
*GLX_conf
)
374 _EGLConfig
*conf
= &GLX_conf
->Base
;
375 EGLint surface_type
, r
, g
, b
, a
;
377 surface_type
= GET_CONFIG_ATTRIB(conf
, EGL_SURFACE_TYPE
);
378 if (!GLX_conf
->double_buffered
&& GLX_dpy
->single_buffered_quirk
) {
379 /* some GLX impls do not like single-buffered window surface */
380 surface_type
&= ~EGL_WINDOW_BIT
;
381 /* pbuffer bit is usually not set */
382 if (GLX_dpy
->have_pbuffer
)
383 surface_type
|= EGL_PBUFFER_BIT
;
384 SET_CONFIG_ATTRIB(conf
, EGL_SURFACE_TYPE
, surface_type
);
387 /* no visual attribs unless window bit is set */
388 if (!(surface_type
& EGL_WINDOW_BIT
)) {
389 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_VISUAL_ID
, 0);
390 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_VISUAL_TYPE
, EGL_NONE
);
393 /* make sure buffer size is set correctly */
394 r
= GET_CONFIG_ATTRIB(conf
, EGL_RED_SIZE
);
395 g
= GET_CONFIG_ATTRIB(conf
, EGL_GREEN_SIZE
);
396 b
= GET_CONFIG_ATTRIB(conf
, EGL_BLUE_SIZE
);
397 a
= GET_CONFIG_ATTRIB(conf
, EGL_ALPHA_SIZE
);
398 SET_CONFIG_ATTRIB(conf
, EGL_BUFFER_SIZE
, r
+ g
+ b
+ a
);
403 create_configs(_EGLDisplay
*dpy
, struct GLX_egl_display
*GLX_dpy
,
406 EGLint num_configs
= 0, i
;
409 if (GLX_dpy
->have_fbconfig
) {
410 GLX_dpy
->fbconfigs
= glXGetFBConfigs(GLX_dpy
->dpy
, screen
, &num_configs
);
413 XVisualInfo vinfo_template
;
416 vinfo_template
.screen
= screen
;
417 mask
= VisualScreenMask
;
418 GLX_dpy
->visuals
= XGetVisualInfo(GLX_dpy
->dpy
, mask
, &vinfo_template
,
425 for (i
= 0; i
< num_configs
; i
++) {
426 struct GLX_egl_config
*GLX_conf
, template;
429 memset(&template, 0, sizeof(template));
430 _eglInitConfig(&template.Base
, id
);
431 if (GLX_dpy
->have_fbconfig
)
432 ok
= convert_fbconfig(GLX_dpy
->dpy
, GLX_dpy
->fbconfigs
[i
], &template);
434 ok
= convert_visual(GLX_dpy
->dpy
, &GLX_dpy
->visuals
[i
], &template);
438 fix_config(GLX_dpy
, &template);
439 if (!_eglValidateConfig(&template.Base
, EGL_FALSE
)) {
440 _eglLog(_EGL_DEBUG
, "GLX: failed to validate config %d", i
);
444 GLX_conf
= CALLOC_STRUCT(GLX_egl_config
);
446 memcpy(GLX_conf
, &template, sizeof(template));
449 _eglAddConfig(dpy
, &GLX_conf
->Base
);
459 check_extensions(struct GLX_egl_display
*GLX_dpy
, EGLint screen
)
461 GLX_dpy
->extensions
=
462 glXQueryExtensionsString(GLX_dpy
->dpy
, screen
);
463 if (GLX_dpy
->extensions
) {
464 /* glXGetProcAddress is assumed */
466 if (strstr(GLX_dpy
->extensions
, "GLX_SGI_make_current_read")) {
467 /* GLX 1.3 entry points are used */
468 GLX_dpy
->have_make_current_read
= EGL_TRUE
;
471 if (strstr(GLX_dpy
->extensions
, "GLX_SGIX_fbconfig")) {
472 /* GLX 1.3 entry points are used */
473 GLX_dpy
->have_fbconfig
= EGL_TRUE
;
476 if (strstr(GLX_dpy
->extensions
, "GLX_SGIX_pbuffer")) {
477 GLX_dpy
->glXCreateGLXPbufferSGIX
= (PFNGLXCREATEGLXPBUFFERSGIXPROC
)
478 glXGetProcAddress((const GLubyte
*) "glXCreateGLXPbufferSGIX");
479 GLX_dpy
->glXDestroyGLXPbufferSGIX
= (PFNGLXDESTROYGLXPBUFFERSGIXPROC
)
480 glXGetProcAddress((const GLubyte
*) "glXDestroyGLXPbufferSGIX");
482 if (GLX_dpy
->glXCreateGLXPbufferSGIX
&&
483 GLX_dpy
->glXDestroyGLXPbufferSGIX
&&
484 GLX_dpy
->have_fbconfig
)
485 GLX_dpy
->have_pbuffer
= EGL_TRUE
;
489 if (GLX_dpy
->glx_maj
== 1 && GLX_dpy
->glx_min
>= 3) {
490 GLX_dpy
->have_1_3
= EGL_TRUE
;
491 GLX_dpy
->have_make_current_read
= EGL_TRUE
;
492 GLX_dpy
->have_fbconfig
= EGL_TRUE
;
493 GLX_dpy
->have_pbuffer
= EGL_TRUE
;
499 check_quirks(struct GLX_egl_display
*GLX_dpy
, EGLint screen
)
503 GLX_dpy
->single_buffered_quirk
= EGL_TRUE
;
504 GLX_dpy
->glx_window_quirk
= EGL_TRUE
;
506 vendor
= glXGetClientString(GLX_dpy
->dpy
, GLX_VENDOR
);
507 if (vendor
&& strstr(vendor
, "NVIDIA")) {
508 vendor
= glXQueryServerString(GLX_dpy
->dpy
, screen
, GLX_VENDOR
);
509 if (vendor
&& strstr(vendor
, "NVIDIA")) {
510 _eglLog(_EGL_DEBUG
, "disable quirks");
511 GLX_dpy
->single_buffered_quirk
= EGL_FALSE
;
512 GLX_dpy
->glx_window_quirk
= EGL_FALSE
;
519 * Called via eglInitialize(), GLX_drv->API.Initialize().
522 GLX_eglInitialize(_EGLDriver
*drv
, _EGLDisplay
*disp
,
523 EGLint
*major
, EGLint
*minor
)
525 struct GLX_egl_display
*GLX_dpy
;
527 GLX_dpy
= CALLOC_STRUCT(GLX_egl_display
);
529 return _eglError(EGL_BAD_ALLOC
, "eglInitialize");
531 GLX_dpy
->dpy
= (Display
*) disp
->NativeDisplay
;
533 GLX_dpy
->dpy
= XOpenDisplay(NULL
);
535 _eglLog(_EGL_WARNING
, "GLX: XOpenDisplay failed");
541 if (!glXQueryVersion(GLX_dpy
->dpy
, &GLX_dpy
->glx_maj
, &GLX_dpy
->glx_min
)) {
542 _eglLog(_EGL_WARNING
, "GLX: glXQueryVersion failed");
543 if (!disp
->NativeDisplay
)
544 XCloseDisplay(GLX_dpy
->dpy
);
549 check_extensions(GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
550 check_quirks(GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
552 create_configs(disp
, GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
553 if (!disp
->NumConfigs
) {
554 _eglLog(_EGL_WARNING
, "GLX: failed to create any config");
555 if (!disp
->NativeDisplay
)
556 XCloseDisplay(GLX_dpy
->dpy
);
561 disp
->DriverData
= (void *) GLX_dpy
;
562 disp
->ClientAPIsMask
= GLX_EGL_APIS
;
564 /* we're supporting EGL 1.4 */
572 * Called via eglTerminate(), drv->API.Terminate().
575 GLX_eglTerminate(_EGLDriver
*drv
, _EGLDisplay
*disp
)
577 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
579 _eglReleaseDisplayResources(drv
, disp
);
580 _eglCleanupDisplay(disp
);
582 if (GLX_dpy
->visuals
)
583 XFree(GLX_dpy
->visuals
);
584 if (GLX_dpy
->fbconfigs
)
585 XFree(GLX_dpy
->fbconfigs
);
587 if (!disp
->NativeDisplay
)
588 XCloseDisplay(GLX_dpy
->dpy
);
591 disp
->DriverData
= NULL
;
598 * Called via eglCreateContext(), drv->API.CreateContext().
601 GLX_eglCreateContext(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLConfig
*conf
,
602 _EGLContext
*share_list
, const EGLint
*attrib_list
)
604 struct GLX_egl_context
*GLX_ctx
= CALLOC_STRUCT(GLX_egl_context
);
605 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
606 struct GLX_egl_context
*GLX_ctx_shared
= GLX_egl_context(share_list
);
609 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
613 if (!_eglInitContext(drv
, &GLX_ctx
->Base
, conf
, attrib_list
)) {
618 if (GLX_dpy
->have_fbconfig
)
620 glXCreateNewContext(GLX_dpy
->dpy
,
621 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
623 GLX_ctx_shared
? GLX_ctx_shared
->context
: NULL
,
627 glXCreateContext(GLX_dpy
->dpy
,
628 &GLX_dpy
->visuals
[GLX_egl_config_index(conf
)],
629 GLX_ctx_shared
? GLX_ctx_shared
->context
: NULL
,
631 if (!GLX_ctx
->context
) {
636 return &GLX_ctx
->Base
;
641 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
644 GLX_eglMakeCurrent(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*dsurf
,
645 _EGLSurface
*rsurf
, _EGLContext
*ctx
)
647 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
648 struct GLX_egl_surface
*GLX_dsurf
= GLX_egl_surface(dsurf
);
649 struct GLX_egl_surface
*GLX_rsurf
= GLX_egl_surface(rsurf
);
650 struct GLX_egl_context
*GLX_ctx
= GLX_egl_context(ctx
);
651 GLXDrawable ddraw
, rdraw
;
654 if (!_eglMakeCurrent(drv
, disp
, dsurf
, rsurf
, ctx
))
657 ddraw
= (GLX_dsurf
) ? GLX_dsurf
->glx_drawable
: None
;
658 rdraw
= (GLX_rsurf
) ? GLX_rsurf
->glx_drawable
: None
;
659 cctx
= (GLX_ctx
) ? GLX_ctx
->context
: NULL
;
661 if (GLX_dpy
->have_make_current_read
)
662 return glXMakeContextCurrent(GLX_dpy
->dpy
, ddraw
, rdraw
, cctx
);
663 else if (ddraw
== rdraw
)
664 return glXMakeCurrent(GLX_dpy
->dpy
, ddraw
, cctx
);
669 /** Get size of given window */
671 get_drawable_size(Display
*dpy
, Drawable d
, uint
*width
, uint
*height
)
676 unsigned int w
, h
, bw
, depth
;
677 stat
= XGetGeometry(dpy
, d
, &root
, &xpos
, &ypos
, &w
, &h
, &bw
, &depth
);
684 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
687 GLX_eglCreateWindowSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLConfig
*conf
,
688 NativeWindowType window
, const EGLint
*attrib_list
)
690 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
691 struct GLX_egl_surface
*GLX_surf
;
694 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
696 _eglError(EGL_BAD_ALLOC
, "eglCreateWindowSurface");
700 if (!_eglInitSurface(drv
, &GLX_surf
->Base
, EGL_WINDOW_BIT
,
701 conf
, attrib_list
)) {
706 GLX_surf
->drawable
= window
;
708 if (GLX_dpy
->have_1_3
&& !GLX_dpy
->glx_window_quirk
)
709 GLX_surf
->glx_drawable
=
710 glXCreateWindow(GLX_dpy
->dpy
,
711 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
712 GLX_surf
->drawable
, NULL
);
714 GLX_surf
->glx_drawable
= GLX_surf
->drawable
;
716 if (!GLX_surf
->glx_drawable
) {
721 get_drawable_size(GLX_dpy
->dpy
, window
, &width
, &height
);
722 GLX_surf
->Base
.Width
= width
;
723 GLX_surf
->Base
.Height
= height
;
725 return &GLX_surf
->Base
;
729 GLX_eglCreatePixmapSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLConfig
*conf
,
730 NativePixmapType pixmap
, const EGLint
*attrib_list
)
732 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
733 struct GLX_egl_surface
*GLX_surf
;
736 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
738 _eglError(EGL_BAD_ALLOC
, "eglCreatePixmapSurface");
742 if (!_eglInitSurface(drv
, &GLX_surf
->Base
, EGL_PIXMAP_BIT
,
743 conf
, attrib_list
)) {
748 GLX_surf
->drawable
= pixmap
;
750 if (GLX_dpy
->have_1_3
) {
751 GLX_surf
->glx_drawable
=
752 glXCreatePixmap(GLX_dpy
->dpy
,
753 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
754 GLX_surf
->drawable
, NULL
);
756 else if (GLX_dpy
->have_fbconfig
) {
757 GLXFBConfig fbconfig
= GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)];
758 XVisualInfo
*vinfo
= glXGetVisualFromFBConfig(GLX_dpy
->dpy
, fbconfig
);
760 GLX_surf
->glx_drawable
=
761 glXCreateGLXPixmap(GLX_dpy
->dpy
, vinfo
, GLX_surf
->drawable
);
766 GLX_surf
->glx_drawable
=
767 glXCreateGLXPixmap(GLX_dpy
->dpy
,
768 &GLX_dpy
->visuals
[GLX_egl_config_index(conf
)],
772 if (!GLX_surf
->glx_drawable
) {
777 get_drawable_size(GLX_dpy
->dpy
, pixmap
, &width
, &height
);
778 GLX_surf
->Base
.Width
= width
;
779 GLX_surf
->Base
.Height
= height
;
781 return &GLX_surf
->Base
;
785 GLX_eglCreatePbufferSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
786 _EGLConfig
*conf
, const EGLint
*attrib_list
)
788 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
789 struct GLX_egl_surface
*GLX_surf
;
793 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
795 _eglError(EGL_BAD_ALLOC
, "eglCreatePbufferSurface");
799 if (!_eglInitSurface(drv
, &GLX_surf
->Base
, EGL_PBUFFER_BIT
,
800 conf
, attrib_list
)) {
808 GLX_surf
->drawable
= None
;
810 if (GLX_dpy
->have_1_3
) {
811 /* put geometry in attribs */
812 if (GLX_surf
->Base
.Width
) {
813 attribs
[i
++] = GLX_PBUFFER_WIDTH
;
814 attribs
[i
++] = GLX_surf
->Base
.Width
;
816 if (GLX_surf
->Base
.Height
) {
817 attribs
[i
++] = GLX_PBUFFER_HEIGHT
;
818 attribs
[i
++] = GLX_surf
->Base
.Height
;
822 GLX_surf
->glx_drawable
=
823 glXCreatePbuffer(GLX_dpy
->dpy
,
824 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
827 else if (GLX_dpy
->have_pbuffer
) {
828 GLX_surf
->glx_drawable
= GLX_dpy
->glXCreateGLXPbufferSGIX(
830 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
831 GLX_surf
->Base
.Width
,
832 GLX_surf
->Base
.Height
,
836 if (!GLX_surf
->glx_drawable
) {
841 return &GLX_surf
->Base
;
845 GLX_eglDestroySurface(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*surf
)
847 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
848 if (!_eglIsSurfaceBound(surf
)) {
849 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(surf
);
851 if (GLX_dpy
->have_1_3
) {
852 switch (surf
->Type
) {
854 if (!GLX_dpy
->glx_window_quirk
)
855 glXDestroyWindow(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
857 case EGL_PBUFFER_BIT
:
858 glXDestroyPbuffer(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
861 glXDestroyPixmap(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
868 switch (surf
->Type
) {
869 case EGL_PBUFFER_BIT
:
870 GLX_dpy
->glXDestroyGLXPbufferSGIX(GLX_dpy
->dpy
,
871 GLX_surf
->glx_drawable
);
874 glXDestroyGLXPixmap(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
888 GLX_eglSwapBuffers(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*draw
)
890 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
891 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(draw
);
893 glXSwapBuffers(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
899 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
902 GLX_eglGetProcAddress(const char *procname
)
904 return (_EGLProc
) glXGetProcAddress((const GLubyte
*) procname
);
909 GLX_Unload(_EGLDriver
*drv
)
911 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
917 * This is the main entrypoint into the driver, called by libEGL.
918 * Create a new _EGLDriver object and init its dispatch table.
921 _eglMain(const char *args
)
923 struct GLX_egl_driver
*GLX_drv
= CALLOC_STRUCT(GLX_egl_driver
);
928 _eglInitDriverFallbacks(&GLX_drv
->Base
);
929 GLX_drv
->Base
.API
.Initialize
= GLX_eglInitialize
;
930 GLX_drv
->Base
.API
.Terminate
= GLX_eglTerminate
;
931 GLX_drv
->Base
.API
.CreateContext
= GLX_eglCreateContext
;
932 GLX_drv
->Base
.API
.MakeCurrent
= GLX_eglMakeCurrent
;
933 GLX_drv
->Base
.API
.CreateWindowSurface
= GLX_eglCreateWindowSurface
;
934 GLX_drv
->Base
.API
.CreatePixmapSurface
= GLX_eglCreatePixmapSurface
;
935 GLX_drv
->Base
.API
.CreatePbufferSurface
= GLX_eglCreatePbufferSurface
;
936 GLX_drv
->Base
.API
.DestroySurface
= GLX_eglDestroySurface
;
937 GLX_drv
->Base
.API
.SwapBuffers
= GLX_eglSwapBuffers
;
938 GLX_drv
->Base
.API
.GetProcAddress
= GLX_eglGetProcAddress
;
940 GLX_drv
->Base
.Name
= "GLX";
941 GLX_drv
->Base
.Unload
= GLX_Unload
;
943 return &GLX_drv
->Base
;