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 "egldefines.h"
45 #include "egldisplay.h"
46 #include "egldriver.h"
47 #include "eglcurrent.h"
49 #include "eglsurface.h"
51 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
53 #ifndef GLX_VERSION_1_4
54 #error "GL/glx.h must be equal to or greater than GLX 1.4"
57 /** subclass of _EGLDriver */
60 _EGLDriver Base
; /**< base class */
64 /** driver data of _EGLDisplay */
65 struct GLX_egl_display
69 GLXFBConfig
*fbconfigs
;
73 const char *extensions
;
75 EGLBoolean have_make_current_read
;
76 EGLBoolean have_fbconfig
;
77 EGLBoolean have_pbuffer
;
79 /* GLX_SGIX_pbuffer */
80 PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX
;
81 PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX
;
83 /* workaround quirks of different GLX implementations */
84 EGLBoolean single_buffered_quirk
;
85 EGLBoolean glx_window_quirk
;
90 /** subclass of _EGLContext */
91 struct GLX_egl_context
93 _EGLContext Base
; /**< base class */
99 /** subclass of _EGLSurface */
100 struct GLX_egl_surface
102 _EGLSurface Base
; /**< base class */
105 GLXDrawable glx_drawable
;
107 void (*destroy
)(Display
*, GLXDrawable
);
111 /** subclass of _EGLConfig */
112 struct GLX_egl_config
114 _EGLConfig Base
; /**< base class */
115 EGLBoolean double_buffered
;
119 /* standard typecasts */
120 _EGL_DRIVER_STANDARD_TYPECASTS(GLX_egl
)
123 GLX_egl_config_index(_EGLConfig
*conf
)
125 struct GLX_egl_config
*GLX_conf
= GLX_egl_config(conf
);
126 return GLX_conf
->index
;
130 #define MAP_ATTRIB(attr, memb) \
131 { attr, offsetof(__GLcontextModes, memb) }
134 static const struct {
137 } fbconfig_attributes
[] = {
138 /* table 3.1 of GLX 1.4 */
139 MAP_ATTRIB(GLX_FBCONFIG_ID
, fbconfigID
),
140 MAP_ATTRIB(GLX_BUFFER_SIZE
, rgbBits
),
141 MAP_ATTRIB(GLX_LEVEL
, level
),
142 MAP_ATTRIB(GLX_DOUBLEBUFFER
, doubleBufferMode
),
143 MAP_ATTRIB(GLX_STEREO
, stereoMode
),
144 MAP_ATTRIB(GLX_AUX_BUFFERS
, numAuxBuffers
),
145 MAP_ATTRIB(GLX_RED_SIZE
, redBits
),
146 MAP_ATTRIB(GLX_GREEN_SIZE
, greenBits
),
147 MAP_ATTRIB(GLX_BLUE_SIZE
, blueBits
),
148 MAP_ATTRIB(GLX_ALPHA_SIZE
, alphaBits
),
149 MAP_ATTRIB(GLX_DEPTH_SIZE
, depthBits
),
150 MAP_ATTRIB(GLX_STENCIL_SIZE
, stencilBits
),
151 MAP_ATTRIB(GLX_ACCUM_RED_SIZE
, accumRedBits
),
152 MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE
, accumGreenBits
),
153 MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE
, accumBlueBits
),
154 MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE
, accumAlphaBits
),
155 MAP_ATTRIB(GLX_SAMPLE_BUFFERS
, sampleBuffers
),
156 MAP_ATTRIB(GLX_SAMPLES
, samples
),
157 MAP_ATTRIB(GLX_RENDER_TYPE
, renderType
),
158 MAP_ATTRIB(GLX_DRAWABLE_TYPE
, drawableType
),
159 MAP_ATTRIB(GLX_X_RENDERABLE
, xRenderable
),
160 MAP_ATTRIB(GLX_X_VISUAL_TYPE
, visualType
),
161 MAP_ATTRIB(GLX_CONFIG_CAVEAT
, visualRating
),
162 MAP_ATTRIB(GLX_TRANSPARENT_TYPE
, transparentPixel
),
163 MAP_ATTRIB(GLX_TRANSPARENT_INDEX_VALUE
, transparentIndex
),
164 MAP_ATTRIB(GLX_TRANSPARENT_RED_VALUE
, transparentRed
),
165 MAP_ATTRIB(GLX_TRANSPARENT_GREEN_VALUE
, transparentGreen
),
166 MAP_ATTRIB(GLX_TRANSPARENT_BLUE_VALUE
, transparentBlue
),
167 MAP_ATTRIB(GLX_TRANSPARENT_ALPHA_VALUE
, transparentAlpha
),
168 MAP_ATTRIB(GLX_MAX_PBUFFER_WIDTH
, maxPbufferWidth
),
169 MAP_ATTRIB(GLX_MAX_PBUFFER_HEIGHT
, maxPbufferHeight
),
170 MAP_ATTRIB(GLX_MAX_PBUFFER_PIXELS
, maxPbufferPixels
),
171 MAP_ATTRIB(GLX_VISUAL_ID
, visualID
),
176 convert_fbconfig(Display
*dpy
, GLXFBConfig fbconfig
,
177 struct GLX_egl_config
*GLX_conf
)
179 __GLcontextModes mode
;
180 int err
= 0, attr
, val
, i
;
182 memset(&mode
, 0, sizeof(mode
));
184 for (i
= 0; i
< ARRAY_SIZE(fbconfig_attributes
); i
++) {
185 int offset
= fbconfig_attributes
[i
].offset
;
186 attr
= fbconfig_attributes
[i
].attr
;
187 err
= glXGetFBConfigAttrib(dpy
, fbconfig
, attr
, &val
);
189 if (err
== GLX_BAD_ATTRIBUTE
) {
195 *((int *) ((char *) &mode
+ offset
)) = val
;
200 /* must have rgba bit */
201 if (!(mode
.renderType
& GLX_RGBA_BIT
))
204 /* pixmap and pbuffer surfaces must be single-buffered in EGL */
205 if (mode
.doubleBufferMode
) {
206 mode
.drawableType
&= ~(GLX_PIXMAP_BIT
| GLX_PBUFFER_BIT
);
207 if (!mode
.drawableType
)
211 mode
.rgbMode
= GL_TRUE
;
212 mode
.haveAccumBuffer
= (mode
.accumRedBits
+
213 mode
.accumGreenBits
+
215 mode
.accumAlphaBits
> 0);
216 mode
.haveDepthBuffer
= (mode
.depthBits
> 0);
217 mode
.haveStencilBuffer
= (mode
.stencilBits
> 0);
219 GLX_conf
->double_buffered
= (mode
.doubleBufferMode
!= 0);
220 return _eglConfigFromContextModesRec(&GLX_conf
->Base
, &mode
,
221 EGL_OPENGL_BIT
, EGL_OPENGL_BIT
);
225 static const struct {
228 } visual_attributes
[] = {
229 /* table 3.7 of GLX 1.4 */
231 MAP_ATTRIB(GLX_BUFFER_SIZE
, rgbBits
),
232 MAP_ATTRIB(GLX_LEVEL
, level
),
233 MAP_ATTRIB(GLX_RGBA
, rgbMode
),
234 MAP_ATTRIB(GLX_DOUBLEBUFFER
, doubleBufferMode
),
235 MAP_ATTRIB(GLX_STEREO
, stereoMode
),
236 MAP_ATTRIB(GLX_AUX_BUFFERS
, numAuxBuffers
),
237 MAP_ATTRIB(GLX_RED_SIZE
, redBits
),
238 MAP_ATTRIB(GLX_GREEN_SIZE
, greenBits
),
239 MAP_ATTRIB(GLX_BLUE_SIZE
, blueBits
),
240 MAP_ATTRIB(GLX_ALPHA_SIZE
, alphaBits
),
241 MAP_ATTRIB(GLX_DEPTH_SIZE
, depthBits
),
242 MAP_ATTRIB(GLX_STENCIL_SIZE
, stencilBits
),
243 MAP_ATTRIB(GLX_ACCUM_RED_SIZE
, accumRedBits
),
244 MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE
, accumGreenBits
),
245 MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE
, accumBlueBits
),
246 MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE
, accumAlphaBits
),
247 MAP_ATTRIB(GLX_SAMPLE_BUFFERS
, sampleBuffers
),
248 MAP_ATTRIB(GLX_SAMPLES
, samples
),
249 MAP_ATTRIB(GLX_FBCONFIG_ID
, fbconfigID
),
250 /* GLX_EXT_visual_rating */
251 MAP_ATTRIB(GLX_VISUAL_CAVEAT_EXT
, visualRating
),
256 get_visual_type(const XVisualInfo
*vis
)
260 #if defined(__cplusplus) || defined(c_plusplus)
261 klass
= vis
->c_class
;
268 return GLX_TRUE_COLOR
;
270 return GLX_DIRECT_COLOR
;
272 return GLX_PSEUDO_COLOR
;
274 return GLX_STATIC_COLOR
;
276 return GLX_GRAY_SCALE
;
278 return GLX_STATIC_GRAY
;
286 convert_visual(Display
*dpy
, XVisualInfo
*vinfo
,
287 struct GLX_egl_config
*GLX_conf
)
289 __GLcontextModes mode
;
290 int err
, attr
, val
, i
;
292 /* the visual must support OpenGL */
293 err
= glXGetConfig(dpy
, vinfo
, GLX_USE_GL
, &val
);
297 memset(&mode
, 0, sizeof(mode
));
299 for (i
= 0; i
< ARRAY_SIZE(visual_attributes
); i
++) {
300 int offset
= visual_attributes
[i
].offset
;
301 attr
= visual_attributes
[i
].attr
;
302 err
= glXGetConfig(dpy
, vinfo
, attr
, &val
);
304 if (err
== GLX_BAD_ATTRIBUTE
) {
310 *((int *) ((char *) &mode
+ offset
)) = val
;
315 /* must be RGB mode */
319 mode
.visualID
= vinfo
->visualid
;
320 mode
.visualType
= get_visual_type(vinfo
);
321 mode
.redMask
= vinfo
->red_mask
;
322 mode
.greenMask
= vinfo
->green_mask
;
323 mode
.blueMask
= vinfo
->blue_mask
;
325 mode
.drawableType
= GLX_WINDOW_BIT
;
326 /* pixmap surfaces must be single-buffered in EGL */
327 if (!mode
.doubleBufferMode
)
328 mode
.drawableType
|= GLX_PIXMAP_BIT
;
330 mode
.renderType
= GLX_RGBA_BIT
;
331 mode
.xRenderable
= GL_TRUE
;
332 mode
.haveAccumBuffer
= (mode
.accumRedBits
+
333 mode
.accumGreenBits
+
335 mode
.accumAlphaBits
> 0);
336 mode
.haveDepthBuffer
= (mode
.depthBits
> 0);
337 mode
.haveStencilBuffer
= (mode
.stencilBits
> 0);
339 GLX_conf
->double_buffered
= (mode
.doubleBufferMode
!= 0);
340 return _eglConfigFromContextModesRec(&GLX_conf
->Base
, &mode
,
341 EGL_OPENGL_BIT
, EGL_OPENGL_BIT
);
346 fix_config(struct GLX_egl_display
*GLX_dpy
, struct GLX_egl_config
*GLX_conf
)
348 _EGLConfig
*conf
= &GLX_conf
->Base
;
349 EGLint surface_type
, r
, g
, b
, a
;
351 surface_type
= GET_CONFIG_ATTRIB(conf
, EGL_SURFACE_TYPE
);
352 if (!GLX_conf
->double_buffered
&& GLX_dpy
->single_buffered_quirk
) {
353 /* some GLX impls do not like single-buffered window surface */
354 surface_type
&= ~EGL_WINDOW_BIT
;
355 /* pbuffer bit is usually not set */
356 if (GLX_dpy
->have_pbuffer
)
357 surface_type
|= EGL_PBUFFER_BIT
;
358 SET_CONFIG_ATTRIB(conf
, EGL_SURFACE_TYPE
, surface_type
);
361 /* no visual attribs unless window bit is set */
362 if (!(surface_type
& EGL_WINDOW_BIT
)) {
363 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_VISUAL_ID
, 0);
364 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_VISUAL_TYPE
, EGL_NONE
);
367 /* make sure buffer size is set correctly */
368 r
= GET_CONFIG_ATTRIB(conf
, EGL_RED_SIZE
);
369 g
= GET_CONFIG_ATTRIB(conf
, EGL_GREEN_SIZE
);
370 b
= GET_CONFIG_ATTRIB(conf
, EGL_BLUE_SIZE
);
371 a
= GET_CONFIG_ATTRIB(conf
, EGL_ALPHA_SIZE
);
372 SET_CONFIG_ATTRIB(conf
, EGL_BUFFER_SIZE
, r
+ g
+ b
+ a
);
377 create_configs(_EGLDisplay
*dpy
, struct GLX_egl_display
*GLX_dpy
,
380 EGLint num_configs
= 0, i
;
383 if (GLX_dpy
->have_fbconfig
) {
384 GLX_dpy
->fbconfigs
= glXGetFBConfigs(GLX_dpy
->dpy
, screen
, &num_configs
);
387 XVisualInfo vinfo_template
;
390 vinfo_template
.screen
= screen
;
391 mask
= VisualScreenMask
;
392 GLX_dpy
->visuals
= XGetVisualInfo(GLX_dpy
->dpy
, mask
, &vinfo_template
,
399 for (i
= 0; i
< num_configs
; i
++) {
400 struct GLX_egl_config
*GLX_conf
, template;
403 memset(&template, 0, sizeof(template));
404 _eglInitConfig(&template.Base
, dpy
, id
);
405 if (GLX_dpy
->have_fbconfig
)
406 ok
= convert_fbconfig(GLX_dpy
->dpy
, GLX_dpy
->fbconfigs
[i
], &template);
408 ok
= convert_visual(GLX_dpy
->dpy
, &GLX_dpy
->visuals
[i
], &template);
412 fix_config(GLX_dpy
, &template);
413 if (!_eglValidateConfig(&template.Base
, EGL_FALSE
)) {
414 _eglLog(_EGL_DEBUG
, "GLX: failed to validate config %d", i
);
418 GLX_conf
= CALLOC_STRUCT(GLX_egl_config
);
420 memcpy(GLX_conf
, &template, sizeof(template));
423 _eglAddConfig(dpy
, &GLX_conf
->Base
);
433 check_extensions(struct GLX_egl_display
*GLX_dpy
, EGLint screen
)
435 GLX_dpy
->extensions
=
436 glXQueryExtensionsString(GLX_dpy
->dpy
, screen
);
437 if (GLX_dpy
->extensions
) {
438 /* glXGetProcAddress is assumed */
440 if (strstr(GLX_dpy
->extensions
, "GLX_SGI_make_current_read")) {
441 /* GLX 1.3 entry points are used */
442 GLX_dpy
->have_make_current_read
= EGL_TRUE
;
445 if (strstr(GLX_dpy
->extensions
, "GLX_SGIX_fbconfig")) {
446 /* GLX 1.3 entry points are used */
447 GLX_dpy
->have_fbconfig
= EGL_TRUE
;
450 if (strstr(GLX_dpy
->extensions
, "GLX_SGIX_pbuffer")) {
451 GLX_dpy
->glXCreateGLXPbufferSGIX
= (PFNGLXCREATEGLXPBUFFERSGIXPROC
)
452 glXGetProcAddress((const GLubyte
*) "glXCreateGLXPbufferSGIX");
453 GLX_dpy
->glXDestroyGLXPbufferSGIX
= (PFNGLXDESTROYGLXPBUFFERSGIXPROC
)
454 glXGetProcAddress((const GLubyte
*) "glXDestroyGLXPbufferSGIX");
456 if (GLX_dpy
->glXCreateGLXPbufferSGIX
&&
457 GLX_dpy
->glXDestroyGLXPbufferSGIX
&&
458 GLX_dpy
->have_fbconfig
)
459 GLX_dpy
->have_pbuffer
= EGL_TRUE
;
463 if (GLX_dpy
->glx_maj
== 1 && GLX_dpy
->glx_min
>= 3) {
464 GLX_dpy
->have_1_3
= EGL_TRUE
;
465 GLX_dpy
->have_make_current_read
= EGL_TRUE
;
466 GLX_dpy
->have_fbconfig
= EGL_TRUE
;
467 GLX_dpy
->have_pbuffer
= EGL_TRUE
;
473 check_quirks(struct GLX_egl_display
*GLX_dpy
, EGLint screen
)
477 GLX_dpy
->single_buffered_quirk
= EGL_TRUE
;
478 GLX_dpy
->glx_window_quirk
= EGL_TRUE
;
480 vendor
= glXGetClientString(GLX_dpy
->dpy
, GLX_VENDOR
);
481 if (vendor
&& strstr(vendor
, "NVIDIA")) {
482 vendor
= glXQueryServerString(GLX_dpy
->dpy
, screen
, GLX_VENDOR
);
483 if (vendor
&& strstr(vendor
, "NVIDIA")) {
484 _eglLog(_EGL_DEBUG
, "disable quirks");
485 GLX_dpy
->single_buffered_quirk
= EGL_FALSE
;
486 GLX_dpy
->glx_window_quirk
= EGL_FALSE
;
493 * Called via eglInitialize(), GLX_drv->API.Initialize().
496 GLX_eglInitialize(_EGLDriver
*drv
, _EGLDisplay
*disp
,
497 EGLint
*major
, EGLint
*minor
)
499 struct GLX_egl_display
*GLX_dpy
;
501 if (disp
->Platform
!= _EGL_PLATFORM_X11
)
504 GLX_dpy
= CALLOC_STRUCT(GLX_egl_display
);
506 return _eglError(EGL_BAD_ALLOC
, "eglInitialize");
508 GLX_dpy
->dpy
= (Display
*) disp
->PlatformDisplay
;
510 GLX_dpy
->dpy
= XOpenDisplay(NULL
);
512 _eglLog(_EGL_WARNING
, "GLX: XOpenDisplay failed");
518 if (!glXQueryVersion(GLX_dpy
->dpy
, &GLX_dpy
->glx_maj
, &GLX_dpy
->glx_min
)) {
519 _eglLog(_EGL_WARNING
, "GLX: glXQueryVersion failed");
520 if (!disp
->PlatformDisplay
)
521 XCloseDisplay(GLX_dpy
->dpy
);
526 check_extensions(GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
527 check_quirks(GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
529 create_configs(disp
, GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
530 if (!_eglGetArraySize(disp
->Configs
)) {
531 _eglLog(_EGL_WARNING
, "GLX: failed to create any config");
532 if (!disp
->PlatformDisplay
)
533 XCloseDisplay(GLX_dpy
->dpy
);
538 disp
->DriverData
= (void *) GLX_dpy
;
539 disp
->ClientAPIsMask
= EGL_OPENGL_BIT
;
541 /* we're supporting EGL 1.4 */
549 * Called via eglTerminate(), drv->API.Terminate().
552 GLX_eglTerminate(_EGLDriver
*drv
, _EGLDisplay
*disp
)
554 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
556 _eglReleaseDisplayResources(drv
, disp
);
557 _eglCleanupDisplay(disp
);
559 if (GLX_dpy
->visuals
)
560 XFree(GLX_dpy
->visuals
);
561 if (GLX_dpy
->fbconfigs
)
562 XFree(GLX_dpy
->fbconfigs
);
564 if (!disp
->PlatformDisplay
)
565 XCloseDisplay(GLX_dpy
->dpy
);
568 disp
->DriverData
= NULL
;
575 * Called via eglCreateContext(), drv->API.CreateContext().
578 GLX_eglCreateContext(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLConfig
*conf
,
579 _EGLContext
*share_list
, const EGLint
*attrib_list
)
581 struct GLX_egl_context
*GLX_ctx
= CALLOC_STRUCT(GLX_egl_context
);
582 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
583 struct GLX_egl_context
*GLX_ctx_shared
= GLX_egl_context(share_list
);
586 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
590 if (!_eglInitContext(&GLX_ctx
->Base
, disp
, conf
, attrib_list
)) {
595 if (GLX_dpy
->have_fbconfig
)
597 glXCreateNewContext(GLX_dpy
->dpy
,
598 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
600 GLX_ctx_shared
? GLX_ctx_shared
->context
: NULL
,
604 glXCreateContext(GLX_dpy
->dpy
,
605 &GLX_dpy
->visuals
[GLX_egl_config_index(conf
)],
606 GLX_ctx_shared
? GLX_ctx_shared
->context
: NULL
,
608 if (!GLX_ctx
->context
) {
613 return &GLX_ctx
->Base
;
618 * Destroy a surface. The display is allowed to be uninitialized.
621 destroy_surface(_EGLDisplay
*disp
, _EGLSurface
*surf
)
623 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
624 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(surf
);
626 if (GLX_surf
->destroy
)
627 GLX_surf
->destroy(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
634 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
637 GLX_eglMakeCurrent(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*dsurf
,
638 _EGLSurface
*rsurf
, _EGLContext
*ctx
)
640 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
641 struct GLX_egl_surface
*GLX_dsurf
= GLX_egl_surface(dsurf
);
642 struct GLX_egl_surface
*GLX_rsurf
= GLX_egl_surface(rsurf
);
643 struct GLX_egl_context
*GLX_ctx
= GLX_egl_context(ctx
);
644 GLXDrawable ddraw
, rdraw
;
646 EGLBoolean ret
= EGL_FALSE
;
648 /* bind the new context and return the "orphaned" one */
649 if (!_eglBindContext(&ctx
, &dsurf
, &rsurf
))
652 ddraw
= (GLX_dsurf
) ? GLX_dsurf
->glx_drawable
: None
;
653 rdraw
= (GLX_rsurf
) ? GLX_rsurf
->glx_drawable
: None
;
654 cctx
= (GLX_ctx
) ? GLX_ctx
->context
: NULL
;
656 if (GLX_dpy
->have_make_current_read
)
657 ret
= glXMakeContextCurrent(GLX_dpy
->dpy
, ddraw
, rdraw
, cctx
);
658 else if (ddraw
== rdraw
)
659 ret
= glXMakeCurrent(GLX_dpy
->dpy
, ddraw
, cctx
);
662 if (dsurf
&& !_eglIsSurfaceLinked(dsurf
))
663 destroy_surface(disp
, dsurf
);
664 if (rsurf
&& rsurf
!= dsurf
&& !_eglIsSurfaceLinked(rsurf
))
665 destroy_surface(disp
, rsurf
);
668 _eglBindContext(&ctx
, &dsurf
, &rsurf
);
674 /** Get size of given window */
676 get_drawable_size(Display
*dpy
, Drawable d
, uint
*width
, uint
*height
)
681 unsigned int w
, h
, bw
, depth
;
682 stat
= XGetGeometry(dpy
, d
, &root
, &xpos
, &ypos
, &w
, &h
, &bw
, &depth
);
689 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
692 GLX_eglCreateWindowSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
693 _EGLConfig
*conf
, EGLNativeWindowType window
,
694 const EGLint
*attrib_list
)
696 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
697 struct GLX_egl_surface
*GLX_surf
;
700 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
702 _eglError(EGL_BAD_ALLOC
, "eglCreateWindowSurface");
706 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_WINDOW_BIT
,
707 conf
, attrib_list
)) {
712 GLX_surf
->drawable
= window
;
714 if (GLX_dpy
->have_1_3
&& !GLX_dpy
->glx_window_quirk
)
715 GLX_surf
->glx_drawable
=
716 glXCreateWindow(GLX_dpy
->dpy
,
717 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
718 GLX_surf
->drawable
, NULL
);
720 GLX_surf
->glx_drawable
= GLX_surf
->drawable
;
722 if (!GLX_surf
->glx_drawable
) {
727 if (GLX_dpy
->have_1_3
&& !GLX_dpy
->glx_window_quirk
)
728 GLX_surf
->destroy
= glXDestroyWindow
;
730 get_drawable_size(GLX_dpy
->dpy
, window
, &width
, &height
);
731 GLX_surf
->Base
.Width
= width
;
732 GLX_surf
->Base
.Height
= height
;
734 return &GLX_surf
->Base
;
738 GLX_eglCreatePixmapSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
739 _EGLConfig
*conf
, EGLNativePixmapType pixmap
,
740 const EGLint
*attrib_list
)
742 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
743 struct GLX_egl_surface
*GLX_surf
;
746 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
748 _eglError(EGL_BAD_ALLOC
, "eglCreatePixmapSurface");
752 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_PIXMAP_BIT
,
753 conf
, attrib_list
)) {
758 GLX_surf
->drawable
= pixmap
;
760 if (GLX_dpy
->have_1_3
) {
761 GLX_surf
->glx_drawable
=
762 glXCreatePixmap(GLX_dpy
->dpy
,
763 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
764 GLX_surf
->drawable
, NULL
);
766 else if (GLX_dpy
->have_fbconfig
) {
767 GLXFBConfig fbconfig
= GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)];
768 XVisualInfo
*vinfo
= glXGetVisualFromFBConfig(GLX_dpy
->dpy
, fbconfig
);
770 GLX_surf
->glx_drawable
=
771 glXCreateGLXPixmap(GLX_dpy
->dpy
, vinfo
, GLX_surf
->drawable
);
776 GLX_surf
->glx_drawable
=
777 glXCreateGLXPixmap(GLX_dpy
->dpy
,
778 &GLX_dpy
->visuals
[GLX_egl_config_index(conf
)],
782 if (!GLX_surf
->glx_drawable
) {
787 GLX_surf
->destroy
= (GLX_dpy
->have_1_3
) ?
788 glXDestroyPixmap
: glXDestroyGLXPixmap
;
790 get_drawable_size(GLX_dpy
->dpy
, pixmap
, &width
, &height
);
791 GLX_surf
->Base
.Width
= width
;
792 GLX_surf
->Base
.Height
= height
;
794 return &GLX_surf
->Base
;
798 GLX_eglCreatePbufferSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
799 _EGLConfig
*conf
, const EGLint
*attrib_list
)
801 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
802 struct GLX_egl_surface
*GLX_surf
;
806 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
808 _eglError(EGL_BAD_ALLOC
, "eglCreatePbufferSurface");
812 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_PBUFFER_BIT
,
813 conf
, attrib_list
)) {
821 GLX_surf
->drawable
= None
;
823 if (GLX_dpy
->have_1_3
) {
824 /* put geometry in attribs */
825 if (GLX_surf
->Base
.Width
) {
826 attribs
[i
++] = GLX_PBUFFER_WIDTH
;
827 attribs
[i
++] = GLX_surf
->Base
.Width
;
829 if (GLX_surf
->Base
.Height
) {
830 attribs
[i
++] = GLX_PBUFFER_HEIGHT
;
831 attribs
[i
++] = GLX_surf
->Base
.Height
;
835 GLX_surf
->glx_drawable
=
836 glXCreatePbuffer(GLX_dpy
->dpy
,
837 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
840 else if (GLX_dpy
->have_pbuffer
) {
841 GLX_surf
->glx_drawable
= GLX_dpy
->glXCreateGLXPbufferSGIX(
843 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
844 GLX_surf
->Base
.Width
,
845 GLX_surf
->Base
.Height
,
849 if (!GLX_surf
->glx_drawable
) {
854 GLX_surf
->destroy
= (GLX_dpy
->have_1_3
) ?
855 glXDestroyPbuffer
: GLX_dpy
->glXDestroyGLXPbufferSGIX
;
857 return &GLX_surf
->Base
;
862 GLX_eglDestroySurface(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*surf
)
864 if (!_eglIsSurfaceBound(surf
))
865 destroy_surface(disp
, surf
);
872 GLX_eglSwapBuffers(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*draw
)
874 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
875 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(draw
);
877 glXSwapBuffers(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
883 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
886 GLX_eglGetProcAddress(_EGLDriver
*drv
, const char *procname
)
888 return (_EGLProc
) glXGetProcAddress((const GLubyte
*) procname
);
892 GLX_eglWaitClient(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
899 GLX_eglWaitNative(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint engine
)
901 if (engine
!= EGL_CORE_NATIVE_ENGINE
)
902 return _eglError(EGL_BAD_PARAMETER
, "eglWaitNative");
908 GLX_Unload(_EGLDriver
*drv
)
910 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
916 * This is the main entrypoint into the driver, called by libEGL.
917 * Create a new _EGLDriver object and init its dispatch table.
920 _eglMain(const char *args
)
922 struct GLX_egl_driver
*GLX_drv
= CALLOC_STRUCT(GLX_egl_driver
);
927 _eglInitDriverFallbacks(&GLX_drv
->Base
);
928 GLX_drv
->Base
.API
.Initialize
= GLX_eglInitialize
;
929 GLX_drv
->Base
.API
.Terminate
= GLX_eglTerminate
;
930 GLX_drv
->Base
.API
.CreateContext
= GLX_eglCreateContext
;
931 GLX_drv
->Base
.API
.MakeCurrent
= GLX_eglMakeCurrent
;
932 GLX_drv
->Base
.API
.CreateWindowSurface
= GLX_eglCreateWindowSurface
;
933 GLX_drv
->Base
.API
.CreatePixmapSurface
= GLX_eglCreatePixmapSurface
;
934 GLX_drv
->Base
.API
.CreatePbufferSurface
= GLX_eglCreatePbufferSurface
;
935 GLX_drv
->Base
.API
.DestroySurface
= GLX_eglDestroySurface
;
936 GLX_drv
->Base
.API
.SwapBuffers
= GLX_eglSwapBuffers
;
937 GLX_drv
->Base
.API
.GetProcAddress
= GLX_eglGetProcAddress
;
938 GLX_drv
->Base
.API
.WaitClient
= GLX_eglWaitClient
;
939 GLX_drv
->Base
.API
.WaitNative
= GLX_eglWaitNative
;
941 GLX_drv
->Base
.Name
= "GLX";
942 GLX_drv
->Base
.Unload
= GLX_Unload
;
944 return &GLX_drv
->Base
;