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>
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 static const struct {
133 } fbconfig_attributes
[] = {
134 /* table 3.1 of GLX 1.4 */
135 { GLX_FBCONFIG_ID
, 0 },
136 { GLX_BUFFER_SIZE
, EGL_BUFFER_SIZE
},
137 { GLX_LEVEL
, EGL_LEVEL
},
138 { GLX_DOUBLEBUFFER
, 0 },
140 { GLX_AUX_BUFFERS
, 0 },
141 { GLX_RED_SIZE
, EGL_RED_SIZE
},
142 { GLX_GREEN_SIZE
, EGL_GREEN_SIZE
},
143 { GLX_BLUE_SIZE
, EGL_BLUE_SIZE
},
144 { GLX_ALPHA_SIZE
, EGL_ALPHA_SIZE
},
145 { GLX_DEPTH_SIZE
, EGL_DEPTH_SIZE
},
146 { GLX_STENCIL_SIZE
, EGL_STENCIL_SIZE
},
147 { GLX_ACCUM_RED_SIZE
, 0 },
148 { GLX_ACCUM_GREEN_SIZE
, 0 },
149 { GLX_ACCUM_BLUE_SIZE
, 0 },
150 { GLX_ACCUM_ALPHA_SIZE
, 0 },
151 { GLX_SAMPLE_BUFFERS
, EGL_SAMPLE_BUFFERS
},
152 { GLX_SAMPLES
, EGL_SAMPLES
},
153 { GLX_RENDER_TYPE
, 0 },
154 { GLX_DRAWABLE_TYPE
, EGL_SURFACE_TYPE
},
155 { GLX_X_RENDERABLE
, EGL_NATIVE_RENDERABLE
},
156 { GLX_X_VISUAL_TYPE
, EGL_NATIVE_VISUAL_TYPE
},
157 { GLX_CONFIG_CAVEAT
, EGL_CONFIG_CAVEAT
},
158 { GLX_TRANSPARENT_TYPE
, EGL_TRANSPARENT_TYPE
},
159 { GLX_TRANSPARENT_INDEX_VALUE
, 0 },
160 { GLX_TRANSPARENT_RED_VALUE
, EGL_TRANSPARENT_RED_VALUE
},
161 { GLX_TRANSPARENT_GREEN_VALUE
, EGL_TRANSPARENT_GREEN_VALUE
},
162 { GLX_TRANSPARENT_BLUE_VALUE
, EGL_TRANSPARENT_BLUE_VALUE
},
163 { GLX_MAX_PBUFFER_WIDTH
, EGL_MAX_PBUFFER_WIDTH
},
164 { GLX_MAX_PBUFFER_HEIGHT
, EGL_MAX_PBUFFER_HEIGHT
},
165 { GLX_MAX_PBUFFER_PIXELS
, EGL_MAX_PBUFFER_PIXELS
},
166 { GLX_VISUAL_ID
, EGL_NATIVE_VISUAL_ID
}
171 convert_fbconfig(Display
*dpy
, GLXFBConfig fbconfig
,
172 struct GLX_egl_config
*GLX_conf
)
177 /* must have rgba bit */
178 err
= glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_RENDER_TYPE
, &val
);
179 if (err
|| !(val
& GLX_RGBA_BIT
))
182 /* must know whether it is double-buffered */
183 err
= glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_DOUBLEBUFFER
, &val
);
186 GLX_conf
->double_buffered
= val
;
188 GLX_conf
->Base
.RenderableType
= EGL_OPENGL_BIT
;
189 GLX_conf
->Base
.Conformant
= EGL_OPENGL_BIT
;
191 for (i
= 0; i
< ARRAY_SIZE(fbconfig_attributes
); i
++) {
192 EGLint egl_attr
, egl_val
;
194 attr
= fbconfig_attributes
[i
].attr
;
195 egl_attr
= fbconfig_attributes
[i
].egl_attr
;
199 err
= glXGetFBConfigAttrib(dpy
, fbconfig
, attr
, &val
);
201 if (err
== GLX_BAD_ATTRIBUTE
) {
209 case EGL_SURFACE_TYPE
:
211 if (val
& GLX_WINDOW_BIT
)
212 egl_val
|= EGL_WINDOW_BIT
;
213 /* pixmap and pbuffer surfaces must be single-buffered in EGL */
214 if (!GLX_conf
->double_buffered
) {
215 if (val
& GLX_PIXMAP_BIT
)
216 egl_val
|= EGL_PIXMAP_BIT
;
217 if (val
& GLX_PBUFFER_BIT
)
218 egl_val
|= EGL_PBUFFER_BIT
;
221 case EGL_NATIVE_VISUAL_TYPE
:
226 case GLX_DIRECT_COLOR
:
227 egl_val
= DirectColor
;
229 case GLX_PSEUDO_COLOR
:
230 egl_val
= PseudoColor
;
232 case GLX_STATIC_COLOR
:
233 egl_val
= StaticColor
;
238 case GLX_STATIC_GRAY
:
239 egl_val
= StaticGray
;
246 case EGL_CONFIG_CAVEAT
:
248 if (val
== GLX_SLOW_CONFIG
) {
249 egl_val
= EGL_SLOW_CONFIG
;
251 else if (val
== GLX_NON_CONFORMANT_CONFIG
) {
252 GLX_conf
->Base
.Conformant
&= ~EGL_OPENGL_BIT
;
256 case EGL_TRANSPARENT_TYPE
:
257 egl_val
= (val
== GLX_TRANSPARENT_RGB
) ?
258 EGL_TRANSPARENT_RGB
: EGL_NONE
;
265 _eglSetConfigKey(&GLX_conf
->Base
, egl_attr
, egl_val
);
270 if (!GLX_conf
->Base
.SurfaceType
)
276 static const struct {
279 } visual_attributes
[] = {
280 /* table 3.7 of GLX 1.4 */
282 { GLX_BUFFER_SIZE
, EGL_BUFFER_SIZE
},
283 { GLX_LEVEL
, EGL_LEVEL
},
285 { GLX_DOUBLEBUFFER
, 0 },
287 { GLX_AUX_BUFFERS
, 0 },
288 { GLX_RED_SIZE
, EGL_RED_SIZE
},
289 { GLX_GREEN_SIZE
, EGL_GREEN_SIZE
},
290 { GLX_BLUE_SIZE
, EGL_BLUE_SIZE
},
291 { GLX_ALPHA_SIZE
, EGL_ALPHA_SIZE
},
292 { GLX_DEPTH_SIZE
, EGL_DEPTH_SIZE
},
293 { GLX_STENCIL_SIZE
, EGL_STENCIL_SIZE
},
294 { GLX_ACCUM_RED_SIZE
, 0 },
295 { GLX_ACCUM_GREEN_SIZE
, 0 },
296 { GLX_ACCUM_BLUE_SIZE
, 0 },
297 { GLX_ACCUM_ALPHA_SIZE
, 0 },
298 { GLX_SAMPLE_BUFFERS
, EGL_SAMPLE_BUFFERS
},
299 { GLX_SAMPLES
, EGL_SAMPLES
},
300 { GLX_FBCONFIG_ID
, 0 },
301 /* GLX_EXT_visual_rating */
302 { GLX_VISUAL_CAVEAT_EXT
, EGL_CONFIG_CAVEAT
}
306 convert_visual(Display
*dpy
, XVisualInfo
*vinfo
,
307 struct GLX_egl_config
*GLX_conf
)
312 /* the visual must support OpenGL and RGBA buffer */
313 err
= glXGetConfig(dpy
, vinfo
, GLX_USE_GL
, &val
);
315 err
= glXGetConfig(dpy
, vinfo
, GLX_RGBA
, &val
);
319 /* must know whether it is double-buffered */
320 err
= glXGetConfig(dpy
, vinfo
, GLX_DOUBLEBUFFER
, &val
);
323 GLX_conf
->double_buffered
= val
;
325 GLX_conf
->Base
.RenderableType
= EGL_OPENGL_BIT
;
326 GLX_conf
->Base
.Conformant
= EGL_OPENGL_BIT
;
327 GLX_conf
->Base
.SurfaceType
= EGL_WINDOW_BIT
;
328 /* pixmap surfaces must be single-buffered in EGL */
329 if (!GLX_conf
->double_buffered
)
330 GLX_conf
->Base
.SurfaceType
|= EGL_PIXMAP_BIT
;
332 GLX_conf
->Base
.NativeVisualID
= vinfo
->visualid
;
333 GLX_conf
->Base
.NativeVisualType
= vinfo
->class;
334 GLX_conf
->Base
.NativeRenderable
= EGL_TRUE
;
336 for (i
= 0; i
< ARRAY_SIZE(visual_attributes
); i
++) {
337 EGLint egl_attr
, egl_val
;
339 attr
= visual_attributes
[i
].attr
;
340 egl_attr
= visual_attributes
[i
].egl_attr
;
344 err
= glXGetConfig(dpy
, vinfo
, attr
, &val
);
346 if (err
== GLX_BAD_ATTRIBUTE
) {
354 case EGL_CONFIG_CAVEAT
:
356 if (val
== GLX_SLOW_VISUAL_EXT
) {
357 egl_val
= EGL_SLOW_CONFIG
;
359 else if (val
== GLX_NON_CONFORMANT_VISUAL_EXT
) {
360 GLX_conf
->Base
.Conformant
&= ~EGL_OPENGL_BIT
;
369 _eglSetConfigKey(&GLX_conf
->Base
, egl_attr
, egl_val
);
372 return (err
) ? EGL_FALSE
: EGL_TRUE
;
377 fix_config(struct GLX_egl_display
*GLX_dpy
, struct GLX_egl_config
*GLX_conf
)
379 _EGLConfig
*conf
= &GLX_conf
->Base
;
381 if (!GLX_conf
->double_buffered
&& GLX_dpy
->single_buffered_quirk
) {
382 /* some GLX impls do not like single-buffered window surface */
383 conf
->SurfaceType
&= ~EGL_WINDOW_BIT
;
384 /* pbuffer bit is usually not set */
385 if (GLX_dpy
->have_pbuffer
)
386 conf
->SurfaceType
|= EGL_PBUFFER_BIT
;
389 /* no visual attribs unless window bit is set */
390 if (!(conf
->SurfaceType
& EGL_WINDOW_BIT
)) {
391 conf
->NativeVisualID
= 0;
392 conf
->NativeVisualType
= EGL_NONE
;
395 if (conf
->TransparentType
!= EGL_TRANSPARENT_RGB
) {
396 /* some impls set them to -1 (GLX_DONT_CARE) */
397 conf
->TransparentRedValue
= 0;
398 conf
->TransparentGreenValue
= 0;
399 conf
->TransparentBlueValue
= 0;
402 /* make sure buffer size is set correctly */
404 conf
->RedSize
+ conf
->GreenSize
+ conf
->BlueSize
+ conf
->AlphaSize
;
409 create_configs(_EGLDisplay
*dpy
, struct GLX_egl_display
*GLX_dpy
,
412 EGLint num_configs
= 0, i
;
415 if (GLX_dpy
->have_fbconfig
) {
416 GLX_dpy
->fbconfigs
= glXGetFBConfigs(GLX_dpy
->dpy
, screen
, &num_configs
);
419 XVisualInfo vinfo_template
;
422 vinfo_template
.screen
= screen
;
423 mask
= VisualScreenMask
;
424 GLX_dpy
->visuals
= XGetVisualInfo(GLX_dpy
->dpy
, mask
, &vinfo_template
,
431 for (i
= 0; i
< num_configs
; i
++) {
432 struct GLX_egl_config
*GLX_conf
, template;
435 memset(&template, 0, sizeof(template));
436 _eglInitConfig(&template.Base
, dpy
, id
);
437 if (GLX_dpy
->have_fbconfig
)
438 ok
= convert_fbconfig(GLX_dpy
->dpy
, GLX_dpy
->fbconfigs
[i
], &template);
440 ok
= convert_visual(GLX_dpy
->dpy
, &GLX_dpy
->visuals
[i
], &template);
444 fix_config(GLX_dpy
, &template);
445 if (!_eglValidateConfig(&template.Base
, EGL_FALSE
)) {
446 _eglLog(_EGL_DEBUG
, "GLX: failed to validate config %d", i
);
450 GLX_conf
= CALLOC_STRUCT(GLX_egl_config
);
452 memcpy(GLX_conf
, &template, sizeof(template));
455 _eglAddConfig(dpy
, &GLX_conf
->Base
);
465 check_extensions(struct GLX_egl_display
*GLX_dpy
, EGLint screen
)
467 GLX_dpy
->extensions
=
468 glXQueryExtensionsString(GLX_dpy
->dpy
, screen
);
469 if (GLX_dpy
->extensions
) {
470 /* glXGetProcAddress is assumed */
472 if (strstr(GLX_dpy
->extensions
, "GLX_SGI_make_current_read")) {
473 /* GLX 1.3 entry points are used */
474 GLX_dpy
->have_make_current_read
= EGL_TRUE
;
477 if (strstr(GLX_dpy
->extensions
, "GLX_SGIX_fbconfig")) {
478 /* GLX 1.3 entry points are used */
479 GLX_dpy
->have_fbconfig
= EGL_TRUE
;
482 if (strstr(GLX_dpy
->extensions
, "GLX_SGIX_pbuffer")) {
483 GLX_dpy
->glXCreateGLXPbufferSGIX
= (PFNGLXCREATEGLXPBUFFERSGIXPROC
)
484 glXGetProcAddress((const GLubyte
*) "glXCreateGLXPbufferSGIX");
485 GLX_dpy
->glXDestroyGLXPbufferSGIX
= (PFNGLXDESTROYGLXPBUFFERSGIXPROC
)
486 glXGetProcAddress((const GLubyte
*) "glXDestroyGLXPbufferSGIX");
488 if (GLX_dpy
->glXCreateGLXPbufferSGIX
&&
489 GLX_dpy
->glXDestroyGLXPbufferSGIX
&&
490 GLX_dpy
->have_fbconfig
)
491 GLX_dpy
->have_pbuffer
= EGL_TRUE
;
495 if (GLX_dpy
->glx_maj
== 1 && GLX_dpy
->glx_min
>= 3) {
496 GLX_dpy
->have_1_3
= EGL_TRUE
;
497 GLX_dpy
->have_make_current_read
= EGL_TRUE
;
498 GLX_dpy
->have_fbconfig
= EGL_TRUE
;
499 GLX_dpy
->have_pbuffer
= EGL_TRUE
;
505 check_quirks(struct GLX_egl_display
*GLX_dpy
, EGLint screen
)
509 GLX_dpy
->single_buffered_quirk
= EGL_TRUE
;
510 GLX_dpy
->glx_window_quirk
= EGL_TRUE
;
512 vendor
= glXGetClientString(GLX_dpy
->dpy
, GLX_VENDOR
);
513 if (vendor
&& strstr(vendor
, "NVIDIA")) {
514 vendor
= glXQueryServerString(GLX_dpy
->dpy
, screen
, GLX_VENDOR
);
515 if (vendor
&& strstr(vendor
, "NVIDIA")) {
516 _eglLog(_EGL_DEBUG
, "disable quirks");
517 GLX_dpy
->single_buffered_quirk
= EGL_FALSE
;
518 GLX_dpy
->glx_window_quirk
= EGL_FALSE
;
525 * Called via eglInitialize(), GLX_drv->API.Initialize().
528 GLX_eglInitialize(_EGLDriver
*drv
, _EGLDisplay
*disp
,
529 EGLint
*major
, EGLint
*minor
)
531 struct GLX_egl_display
*GLX_dpy
;
535 if (disp
->Platform
!= _EGL_PLATFORM_X11
)
538 GLX_dpy
= CALLOC_STRUCT(GLX_egl_display
);
540 return _eglError(EGL_BAD_ALLOC
, "eglInitialize");
542 GLX_dpy
->dpy
= (Display
*) disp
->PlatformDisplay
;
544 GLX_dpy
->dpy
= XOpenDisplay(NULL
);
546 _eglLog(_EGL_WARNING
, "GLX: XOpenDisplay failed");
552 if (!glXQueryVersion(GLX_dpy
->dpy
, &GLX_dpy
->glx_maj
, &GLX_dpy
->glx_min
)) {
553 _eglLog(_EGL_WARNING
, "GLX: glXQueryVersion failed");
554 if (!disp
->PlatformDisplay
)
555 XCloseDisplay(GLX_dpy
->dpy
);
560 check_extensions(GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
561 check_quirks(GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
563 create_configs(disp
, GLX_dpy
, DefaultScreen(GLX_dpy
->dpy
));
564 if (!_eglGetArraySize(disp
->Configs
)) {
565 _eglLog(_EGL_WARNING
, "GLX: failed to create any config");
566 if (!disp
->PlatformDisplay
)
567 XCloseDisplay(GLX_dpy
->dpy
);
572 disp
->DriverData
= (void *) GLX_dpy
;
573 disp
->ClientAPIsMask
= EGL_OPENGL_BIT
;
575 /* we're supporting EGL 1.4 */
583 * Called via eglTerminate(), drv->API.Terminate().
586 GLX_eglTerminate(_EGLDriver
*drv
, _EGLDisplay
*disp
)
588 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
590 _eglReleaseDisplayResources(drv
, disp
);
591 _eglCleanupDisplay(disp
);
593 if (GLX_dpy
->visuals
)
594 XFree(GLX_dpy
->visuals
);
595 if (GLX_dpy
->fbconfigs
)
596 XFree(GLX_dpy
->fbconfigs
);
598 if (!disp
->PlatformDisplay
)
599 XCloseDisplay(GLX_dpy
->dpy
);
602 disp
->DriverData
= NULL
;
609 * Called via eglCreateContext(), drv->API.CreateContext().
612 GLX_eglCreateContext(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLConfig
*conf
,
613 _EGLContext
*share_list
, const EGLint
*attrib_list
)
615 struct GLX_egl_context
*GLX_ctx
= CALLOC_STRUCT(GLX_egl_context
);
616 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
617 struct GLX_egl_context
*GLX_ctx_shared
= GLX_egl_context(share_list
);
622 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
626 if (!_eglInitContext(&GLX_ctx
->Base
, disp
, conf
, attrib_list
)) {
631 if (GLX_dpy
->have_fbconfig
)
633 glXCreateNewContext(GLX_dpy
->dpy
,
634 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
636 GLX_ctx_shared
? GLX_ctx_shared
->context
: NULL
,
640 glXCreateContext(GLX_dpy
->dpy
,
641 &GLX_dpy
->visuals
[GLX_egl_config_index(conf
)],
642 GLX_ctx_shared
? GLX_ctx_shared
->context
: NULL
,
644 if (!GLX_ctx
->context
) {
649 return &GLX_ctx
->Base
;
654 * Destroy a surface. The display is allowed to be uninitialized.
657 destroy_surface(_EGLDisplay
*disp
, _EGLSurface
*surf
)
659 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
660 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(surf
);
662 if (GLX_surf
->destroy
)
663 GLX_surf
->destroy(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
670 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
673 GLX_eglMakeCurrent(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*dsurf
,
674 _EGLSurface
*rsurf
, _EGLContext
*ctx
)
676 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
677 struct GLX_egl_surface
*GLX_dsurf
= GLX_egl_surface(dsurf
);
678 struct GLX_egl_surface
*GLX_rsurf
= GLX_egl_surface(rsurf
);
679 struct GLX_egl_context
*GLX_ctx
= GLX_egl_context(ctx
);
680 GLXDrawable ddraw
, rdraw
;
682 EGLBoolean ret
= EGL_FALSE
;
686 /* bind the new context and return the "orphaned" one */
687 if (!_eglBindContext(&ctx
, &dsurf
, &rsurf
))
690 ddraw
= (GLX_dsurf
) ? GLX_dsurf
->glx_drawable
: None
;
691 rdraw
= (GLX_rsurf
) ? GLX_rsurf
->glx_drawable
: None
;
692 cctx
= (GLX_ctx
) ? GLX_ctx
->context
: NULL
;
694 if (GLX_dpy
->have_make_current_read
)
695 ret
= glXMakeContextCurrent(GLX_dpy
->dpy
, ddraw
, rdraw
, cctx
);
696 else if (ddraw
== rdraw
)
697 ret
= glXMakeCurrent(GLX_dpy
->dpy
, ddraw
, cctx
);
700 if (dsurf
&& !_eglIsSurfaceLinked(dsurf
))
701 destroy_surface(disp
, dsurf
);
702 if (rsurf
&& rsurf
!= dsurf
&& !_eglIsSurfaceLinked(rsurf
))
703 destroy_surface(disp
, rsurf
);
706 _eglBindContext(&ctx
, &dsurf
, &rsurf
);
712 /** Get size of given window */
714 get_drawable_size(Display
*dpy
, Drawable d
, uint
*width
, uint
*height
)
719 unsigned int w
, h
, bw
, depth
;
720 stat
= XGetGeometry(dpy
, d
, &root
, &xpos
, &ypos
, &w
, &h
, &bw
, &depth
);
727 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
730 GLX_eglCreateWindowSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
731 _EGLConfig
*conf
, EGLNativeWindowType window
,
732 const EGLint
*attrib_list
)
734 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
735 struct GLX_egl_surface
*GLX_surf
;
740 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
742 _eglError(EGL_BAD_ALLOC
, "eglCreateWindowSurface");
746 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_WINDOW_BIT
,
747 conf
, attrib_list
)) {
752 GLX_surf
->drawable
= window
;
754 if (GLX_dpy
->have_1_3
&& !GLX_dpy
->glx_window_quirk
)
755 GLX_surf
->glx_drawable
=
756 glXCreateWindow(GLX_dpy
->dpy
,
757 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
758 GLX_surf
->drawable
, NULL
);
760 GLX_surf
->glx_drawable
= GLX_surf
->drawable
;
762 if (!GLX_surf
->glx_drawable
) {
767 if (GLX_dpy
->have_1_3
&& !GLX_dpy
->glx_window_quirk
)
768 GLX_surf
->destroy
= glXDestroyWindow
;
770 get_drawable_size(GLX_dpy
->dpy
, window
, &width
, &height
);
771 GLX_surf
->Base
.Width
= width
;
772 GLX_surf
->Base
.Height
= height
;
774 return &GLX_surf
->Base
;
778 GLX_eglCreatePixmapSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
779 _EGLConfig
*conf
, EGLNativePixmapType pixmap
,
780 const EGLint
*attrib_list
)
782 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
783 struct GLX_egl_surface
*GLX_surf
;
788 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
790 _eglError(EGL_BAD_ALLOC
, "eglCreatePixmapSurface");
794 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_PIXMAP_BIT
,
795 conf
, attrib_list
)) {
800 GLX_surf
->drawable
= pixmap
;
802 if (GLX_dpy
->have_1_3
) {
803 GLX_surf
->glx_drawable
=
804 glXCreatePixmap(GLX_dpy
->dpy
,
805 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
806 GLX_surf
->drawable
, NULL
);
808 else if (GLX_dpy
->have_fbconfig
) {
809 GLXFBConfig fbconfig
= GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)];
810 XVisualInfo
*vinfo
= glXGetVisualFromFBConfig(GLX_dpy
->dpy
, fbconfig
);
812 GLX_surf
->glx_drawable
=
813 glXCreateGLXPixmap(GLX_dpy
->dpy
, vinfo
, GLX_surf
->drawable
);
818 GLX_surf
->glx_drawable
=
819 glXCreateGLXPixmap(GLX_dpy
->dpy
,
820 &GLX_dpy
->visuals
[GLX_egl_config_index(conf
)],
824 if (!GLX_surf
->glx_drawable
) {
829 GLX_surf
->destroy
= (GLX_dpy
->have_1_3
) ?
830 glXDestroyPixmap
: glXDestroyGLXPixmap
;
832 get_drawable_size(GLX_dpy
->dpy
, pixmap
, &width
, &height
);
833 GLX_surf
->Base
.Width
= width
;
834 GLX_surf
->Base
.Height
= height
;
836 return &GLX_surf
->Base
;
840 GLX_eglCreatePbufferSurface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
841 _EGLConfig
*conf
, const EGLint
*attrib_list
)
843 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
844 struct GLX_egl_surface
*GLX_surf
;
850 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
852 _eglError(EGL_BAD_ALLOC
, "eglCreatePbufferSurface");
856 if (!_eglInitSurface(&GLX_surf
->Base
, disp
, EGL_PBUFFER_BIT
,
857 conf
, attrib_list
)) {
865 GLX_surf
->drawable
= None
;
867 if (GLX_dpy
->have_1_3
) {
868 /* put geometry in attribs */
869 if (GLX_surf
->Base
.Width
) {
870 attribs
[i
++] = GLX_PBUFFER_WIDTH
;
871 attribs
[i
++] = GLX_surf
->Base
.Width
;
873 if (GLX_surf
->Base
.Height
) {
874 attribs
[i
++] = GLX_PBUFFER_HEIGHT
;
875 attribs
[i
++] = GLX_surf
->Base
.Height
;
879 GLX_surf
->glx_drawable
=
880 glXCreatePbuffer(GLX_dpy
->dpy
,
881 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
884 else if (GLX_dpy
->have_pbuffer
) {
885 GLX_surf
->glx_drawable
= GLX_dpy
->glXCreateGLXPbufferSGIX(
887 GLX_dpy
->fbconfigs
[GLX_egl_config_index(conf
)],
888 GLX_surf
->Base
.Width
,
889 GLX_surf
->Base
.Height
,
893 if (!GLX_surf
->glx_drawable
) {
898 GLX_surf
->destroy
= (GLX_dpy
->have_1_3
) ?
899 glXDestroyPbuffer
: GLX_dpy
->glXDestroyGLXPbufferSGIX
;
901 return &GLX_surf
->Base
;
906 GLX_eglDestroySurface(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*surf
)
910 if (!_eglIsSurfaceBound(surf
))
911 destroy_surface(disp
, surf
);
918 GLX_eglSwapBuffers(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*draw
)
920 struct GLX_egl_display
*GLX_dpy
= GLX_egl_display(disp
);
921 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(draw
);
925 glXSwapBuffers(GLX_dpy
->dpy
, GLX_surf
->glx_drawable
);
931 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
934 GLX_eglGetProcAddress(_EGLDriver
*drv
, const char *procname
)
938 return (_EGLProc
) glXGetProcAddress((const GLubyte
*) procname
);
942 GLX_eglWaitClient(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
953 GLX_eglWaitNative(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint engine
)
958 if (engine
!= EGL_CORE_NATIVE_ENGINE
)
959 return _eglError(EGL_BAD_PARAMETER
, "eglWaitNative");
965 GLX_Unload(_EGLDriver
*drv
)
967 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
973 * This is the main entrypoint into the driver, called by libEGL.
974 * Create a new _EGLDriver object and init its dispatch table.
977 _eglMain(const char *args
)
979 struct GLX_egl_driver
*GLX_drv
= CALLOC_STRUCT(GLX_egl_driver
);
986 _eglInitDriverFallbacks(&GLX_drv
->Base
);
987 GLX_drv
->Base
.API
.Initialize
= GLX_eglInitialize
;
988 GLX_drv
->Base
.API
.Terminate
= GLX_eglTerminate
;
989 GLX_drv
->Base
.API
.CreateContext
= GLX_eglCreateContext
;
990 GLX_drv
->Base
.API
.MakeCurrent
= GLX_eglMakeCurrent
;
991 GLX_drv
->Base
.API
.CreateWindowSurface
= GLX_eglCreateWindowSurface
;
992 GLX_drv
->Base
.API
.CreatePixmapSurface
= GLX_eglCreatePixmapSurface
;
993 GLX_drv
->Base
.API
.CreatePbufferSurface
= GLX_eglCreatePbufferSurface
;
994 GLX_drv
->Base
.API
.DestroySurface
= GLX_eglDestroySurface
;
995 GLX_drv
->Base
.API
.SwapBuffers
= GLX_eglSwapBuffers
;
996 GLX_drv
->Base
.API
.GetProcAddress
= GLX_eglGetProcAddress
;
997 GLX_drv
->Base
.API
.WaitClient
= GLX_eglWaitClient
;
998 GLX_drv
->Base
.API
.WaitNative
= GLX_eglWaitNative
;
1000 GLX_drv
->Base
.Name
= "GLX";
1001 GLX_drv
->Base
.Unload
= GLX_Unload
;
1003 return &GLX_drv
->Base
;