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>
39 * Add GLXFBConfig support
40 * Pbuffer & Pixmap support
41 * test eglBind/ReleaseTexImage
47 #include <sys/types.h>
53 #include "glxclient.h"
55 #define _EGL_PLATFORM_X
57 #include "eglconfig.h"
58 #include "eglcontext.h"
59 #include "egldisplay.h"
60 #include "egldriver.h"
61 #include "eglglobals.h"
64 #include "eglsurface.h"
68 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
70 static const EGLint all_apis
= (EGL_OPENGL_ES_BIT
|
77 /* X visual attribs */
81 int redMask
, greenMask
, blueMask
;
85 /* GL visual attribs */
88 int transparentRedValue
;
89 int transparentGreenValue
;
90 int transparentBlueValue
;
91 int transparentAlphaValue
;
92 int transparentIndexValue
;
99 int redSize
, greenSize
, blueSize
, alphaSize
;
102 int accumRedSize
, accumGreenSize
, accumBlueSize
, accumAlphaSize
;
103 int numSamples
, numMultisample
;
107 /** subclass of _EGLDriver */
108 struct GLX_egl_driver
110 _EGLDriver Base
; /**< base class */
112 XVisualInfo
*visuals
;
114 /* GLXFBConfig *fbconfigs - todo */
118 /** subclass of _EGLContext */
119 struct GLX_egl_context
121 _EGLContext Base
; /**< base class */
127 /** subclass of _EGLSurface */
128 struct GLX_egl_surface
130 _EGLSurface Base
; /**< base class */
132 GLXDrawable drawable
;
136 /** subclass of _EGLConfig */
137 struct GLX_egl_config
139 _EGLConfig Base
; /**< base class */
143 static struct GLX_egl_driver
*
144 GLX_egl_driver(_EGLDriver
*drv
)
146 return (struct GLX_egl_driver
*) drv
;
149 static struct GLX_egl_context
*
150 GLX_egl_context(_EGLContext
*ctx
)
152 return (struct GLX_egl_context
*) ctx
;
155 static struct GLX_egl_surface
*
156 GLX_egl_surface(_EGLSurface
*surf
)
158 return (struct GLX_egl_surface
*) surf
;
162 get_visual_attribs(Display
*dpy
, XVisualInfo
*vInfo
,
163 struct visual_attribs
*attribs
)
165 const char *ext
= glXQueryExtensionsString(dpy
, vInfo
->screen
);
168 memset(attribs
, 0, sizeof(struct visual_attribs
));
170 attribs
->id
= vInfo
->visualid
;
171 #if defined(__cplusplus) || defined(c_plusplus)
172 attribs
->klass
= vInfo
->c_class
;
174 attribs
->klass
= vInfo
->class;
176 attribs
->depth
= vInfo
->depth
;
177 attribs
->redMask
= vInfo
->red_mask
;
178 attribs
->greenMask
= vInfo
->green_mask
;
179 attribs
->blueMask
= vInfo
->blue_mask
;
180 attribs
->colormapSize
= vInfo
->colormap_size
;
181 attribs
->bitsPerRGB
= vInfo
->bits_per_rgb
;
183 if (glXGetConfig(dpy
, vInfo
, GLX_USE_GL
, &attribs
->supportsGL
) != 0 ||
184 !attribs
->supportsGL
)
186 glXGetConfig(dpy
, vInfo
, GLX_BUFFER_SIZE
, &attribs
->bufferSize
);
187 glXGetConfig(dpy
, vInfo
, GLX_LEVEL
, &attribs
->level
);
188 glXGetConfig(dpy
, vInfo
, GLX_RGBA
, &rgba
);
191 attribs
->render_type
= GLX_RGBA_BIT
;
193 glXGetConfig(dpy
, vInfo
, GLX_DOUBLEBUFFER
, &attribs
->doubleBuffer
);
194 glXGetConfig(dpy
, vInfo
, GLX_STEREO
, &attribs
->stereo
);
195 glXGetConfig(dpy
, vInfo
, GLX_AUX_BUFFERS
, &attribs
->auxBuffers
);
196 glXGetConfig(dpy
, vInfo
, GLX_RED_SIZE
, &attribs
->redSize
);
197 glXGetConfig(dpy
, vInfo
, GLX_GREEN_SIZE
, &attribs
->greenSize
);
198 glXGetConfig(dpy
, vInfo
, GLX_BLUE_SIZE
, &attribs
->blueSize
);
199 glXGetConfig(dpy
, vInfo
, GLX_ALPHA_SIZE
, &attribs
->alphaSize
);
200 glXGetConfig(dpy
, vInfo
, GLX_DEPTH_SIZE
, &attribs
->depthSize
);
201 glXGetConfig(dpy
, vInfo
, GLX_STENCIL_SIZE
, &attribs
->stencilSize
);
202 glXGetConfig(dpy
, vInfo
, GLX_ACCUM_RED_SIZE
, &attribs
->accumRedSize
);
203 glXGetConfig(dpy
, vInfo
, GLX_ACCUM_GREEN_SIZE
, &attribs
->accumGreenSize
);
204 glXGetConfig(dpy
, vInfo
, GLX_ACCUM_BLUE_SIZE
, &attribs
->accumBlueSize
);
205 glXGetConfig(dpy
, vInfo
, GLX_ACCUM_ALPHA_SIZE
, &attribs
->accumAlphaSize
);
207 /* get transparent pixel stuff */
208 glXGetConfig(dpy
, vInfo
,GLX_TRANSPARENT_TYPE
, &attribs
->transparentType
);
209 if (attribs
->transparentType
== GLX_TRANSPARENT_RGB
) {
210 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_RED_VALUE
, &attribs
->transparentRedValue
);
211 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_GREEN_VALUE
, &attribs
->transparentGreenValue
);
212 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_BLUE_VALUE
, &attribs
->transparentBlueValue
);
213 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_ALPHA_VALUE
, &attribs
->transparentAlphaValue
);
215 else if (attribs
->transparentType
== GLX_TRANSPARENT_INDEX
) {
216 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_INDEX_VALUE
, &attribs
->transparentIndexValue
);
219 /* multisample attribs */
220 #ifdef GLX_ARB_multisample
221 if (ext
&& strstr(ext
, "GLX_ARB_multisample")) {
222 glXGetConfig(dpy
, vInfo
, GLX_SAMPLE_BUFFERS_ARB
, &attribs
->numMultisample
);
223 glXGetConfig(dpy
, vInfo
, GLX_SAMPLES_ARB
, &attribs
->numSamples
);
227 attribs
->numSamples
= 0;
228 attribs
->numMultisample
= 0;
231 #if defined(GLX_EXT_visual_rating)
232 if (ext
&& strstr(ext
, "GLX_EXT_visual_rating")) {
233 glXGetConfig(dpy
, vInfo
, GLX_VISUAL_CAVEAT_EXT
, &attribs
->visualCaveat
);
236 attribs
->visualCaveat
= GLX_NONE_EXT
;
239 attribs
->visualCaveat
= 0;
246 create_configs(_EGLDisplay
*disp
, struct GLX_egl_driver
*GLX_drv
)
248 XVisualInfo theTemplate
;
252 struct visual_attribs attribs
;
254 /* get list of all visuals on this screen */
255 theTemplate
.screen
= DefaultScreen(disp
->Xdpy
);
256 mask
= VisualScreenMask
;
257 GLX_drv
->visuals
= XGetVisualInfo(disp
->Xdpy
, mask
, &theTemplate
, &numVisuals
);
259 for (i
= 0; i
< numVisuals
; i
++) {
260 struct GLX_egl_config
*config
;
262 if (!get_visual_attribs(disp
->Xdpy
, &GLX_drv
->visuals
[i
], &attribs
))
265 if (attribs
.doubleBuffer
) {
266 config
= CALLOC_STRUCT(GLX_egl_config
);
268 _eglInitConfig(&config
->Base
, i
+1);
269 SET_CONFIG_ATTRIB(&config
->Base
, EGL_NATIVE_VISUAL_ID
, attribs
.id
);
270 SET_CONFIG_ATTRIB(&config
->Base
, EGL_BUFFER_SIZE
, attribs
.bufferSize
);
271 SET_CONFIG_ATTRIB(&config
->Base
, EGL_RED_SIZE
, attribs
.redSize
);
272 SET_CONFIG_ATTRIB(&config
->Base
, EGL_GREEN_SIZE
, attribs
.greenSize
);
273 SET_CONFIG_ATTRIB(&config
->Base
, EGL_BLUE_SIZE
, attribs
.blueSize
);
274 SET_CONFIG_ATTRIB(&config
->Base
, EGL_ALPHA_SIZE
, attribs
.alphaSize
);
275 SET_CONFIG_ATTRIB(&config
->Base
, EGL_DEPTH_SIZE
, attribs
.depthSize
);
276 SET_CONFIG_ATTRIB(&config
->Base
, EGL_STENCIL_SIZE
, attribs
.stencilSize
);
277 SET_CONFIG_ATTRIB(&config
->Base
, EGL_SAMPLES
, attribs
.numSamples
);
278 SET_CONFIG_ATTRIB(&config
->Base
, EGL_SAMPLE_BUFFERS
, attribs
.numMultisample
);
279 SET_CONFIG_ATTRIB(&config
->Base
, EGL_CONFORMANT
, all_apis
);
280 SET_CONFIG_ATTRIB(&config
->Base
, EGL_RENDERABLE_TYPE
, all_apis
);
281 SET_CONFIG_ATTRIB(&config
->Base
, EGL_SURFACE_TYPE
,
282 (EGL_WINDOW_BIT
/*| EGL_PBUFFER_BIT | EGL_PIXMAP_BIT*/));
284 /* XXX possibly other things to init... */
286 _eglAddConfig(disp
, &config
->Base
);
294 * Called via eglInitialize(), GLX_drv->API.Initialize().
297 GLX_eglInitialize(_EGLDriver
*drv
, EGLDisplay dpy
,
298 EGLint
*minor
, EGLint
*major
)
300 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
301 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
303 _eglLog(_EGL_DEBUG
, "XDRI: eglInitialize");
306 disp
->Xdpy
= XOpenDisplay(NULL
);
308 _eglLog(_EGL_WARNING
, "XDRI: XOpenDisplay failed");
313 GLX_drv
->Base
.Initialized
= EGL_TRUE
;
315 GLX_drv
->Base
.Name
= "GLX";
317 /* we're supporting EGL 1.4 */
321 create_configs(disp
, GLX_drv
);
328 * Called via eglTerminate(), drv->API.Terminate().
331 GLX_eglTerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
333 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
335 _eglLog(_EGL_DEBUG
, "XDRI: eglTerminate");
337 // XCloseDisplay(disp->Xdpy);
344 * Called via eglCreateContext(), drv->API.CreateContext().
347 GLX_eglCreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
348 EGLContext share_list
, const EGLint
*attrib_list
)
350 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
351 struct GLX_egl_context
*GLX_ctx
= CALLOC_STRUCT(GLX_egl_context
);
352 struct GLX_egl_driver
*GLX_drv
= GLX_egl_driver(drv
);
353 struct GLX_egl_context
*GLX_ctx_shared
= NULL
;
357 return EGL_NO_CONTEXT
;
359 if (!_eglInitContext(drv
, dpy
, &GLX_ctx
->Base
, config
, attrib_list
)) {
361 return EGL_NO_CONTEXT
;
364 if (share_list
!= EGL_NO_CONTEXT
) {
365 _EGLContext
*shareCtx
= _eglLookupContext(share_list
);
367 _eglError(EGL_BAD_CONTEXT
, "eglCreateContext(share_list)");
370 GLX_ctx_shared
= GLX_egl_context(shareCtx
);
373 conf
= _eglLookupConfig(drv
, dpy
, config
);
376 GLX_ctx
->context
= glXCreateContext(disp
->Xdpy
, &GLX_drv
->visuals
[(int)config
-1], GLX_ctx_shared
? GLX_ctx_shared
->context
: NULL
, GL_TRUE
);
377 if (!GLX_ctx
->context
)
380 /* need to have a direct rendering context */
381 if (!glXIsDirect(disp
->Xdpy
, GLX_ctx
->context
))
384 return _eglGetContextHandle(&GLX_ctx
->Base
);
389 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
392 GLX_eglMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface d
,
393 EGLSurface r
, EGLContext context
)
395 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
396 _EGLContext
*ctx
= _eglLookupContext(context
);
397 _EGLSurface
*dsurf
= _eglLookupSurface(d
);
398 _EGLSurface
*rsurf
= _eglLookupSurface(r
);
399 struct GLX_egl_surface
*GLX_dsurf
= GLX_egl_surface(dsurf
);
400 struct GLX_egl_surface
*GLX_rsurf
= GLX_egl_surface(rsurf
);
401 struct GLX_egl_context
*GLX_ctx
= GLX_egl_context(ctx
);
403 if (!_eglMakeCurrent(drv
, dpy
, d
, r
, context
))
406 // if (!glXMakeContextCurrent(disp->Xdpy, GLX_dsurf->drawable, GLX_rsurf->drawable, GLX_ctx->context))
407 if (!glXMakeCurrent(disp
->Xdpy
, GLX_dsurf
? GLX_dsurf
->drawable
: 0, GLX_ctx
? GLX_ctx
->context
: NULL
))
413 /** Get size of given window */
415 get_drawable_size(Display
*dpy
, Drawable d
, uint
*width
, uint
*height
)
420 unsigned int w
, h
, bw
, depth
;
421 stat
= XGetGeometry(dpy
, d
, &root
, &xpos
, &ypos
, &w
, &h
, &bw
, &depth
);
428 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
431 GLX_eglCreateWindowSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
432 NativeWindowType window
, const EGLint
*attrib_list
)
434 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
435 struct GLX_egl_surface
*GLX_surf
;
438 GLX_surf
= CALLOC_STRUCT(GLX_egl_surface
);
440 return EGL_NO_SURFACE
;
442 if (!_eglInitSurface(drv
, dpy
, &GLX_surf
->Base
, EGL_WINDOW_BIT
,
443 config
, attrib_list
)) {
448 _eglSaveSurface(&GLX_surf
->Base
);
450 GLX_surf
->drawable
= window
;
451 get_drawable_size(disp
->Xdpy
, window
, &width
, &height
);
452 GLX_surf
->Base
.Width
= width
;
453 GLX_surf
->Base
.Height
= height
;
455 return _eglGetSurfaceHandle(&GLX_surf
->Base
);
459 GLX_eglDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
461 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
462 _EGLSurface
*surf
= _eglLookupSurface(surface
);
465 _eglHashRemove(_eglGlobal
.Surfaces
, (EGLuint
) surface
);
467 surf
->DeletePending
= EGL_TRUE
;
476 _eglError(EGL_BAD_SURFACE
, "eglDestroySurface");
483 GLX_eglBindTexImage(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
,
486 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
487 _EGLSurface
*surf
= _eglLookupSurface(surface
);
488 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(surf
);
491 glXBindTexImageEXT(disp
->Xdpy
, GLX_surf
->drawable
, GLX_FRONT_LEFT_EXT
, NULL
);
498 GLX_eglReleaseTexImage(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
,
501 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
502 _EGLSurface
*surf
= _eglLookupSurface(surface
);
503 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(surf
);
506 glXReleaseTexImageEXT(disp
->Xdpy
, GLX_surf
->drawable
, GLX_FRONT_LEFT_EXT
);
513 GLX_eglSwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
515 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
516 _EGLSurface
*surf
= _eglLookupSurface(draw
);
517 struct GLX_egl_surface
*GLX_surf
= GLX_egl_surface(surf
);
519 _eglLog(_EGL_DEBUG
, "XDRI: EGL SwapBuffers 0x%x",draw
);
521 /* error checking step: */
522 if (!_eglSwapBuffers(drv
, dpy
, draw
))
525 glXSwapBuffers(disp
->Xdpy
, GLX_surf
->drawable
);
531 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
534 GLX_eglGetProcAddress(const char *procname
)
536 return (_EGLProc
)glXGetProcAddress((const GLubyte
*)procname
);
541 * This is the main entrypoint into the driver, called by libEGL.
542 * Create a new _EGLDriver object and init its dispatch table.
545 _eglMain(_EGLDisplay
*disp
, const char *args
)
547 struct GLX_egl_driver
*GLX_drv
= CALLOC_STRUCT(GLX_egl_driver
);
551 _eglInitDriverFallbacks(&GLX_drv
->Base
);
552 GLX_drv
->Base
.API
.Initialize
= GLX_eglInitialize
;
553 GLX_drv
->Base
.API
.Terminate
= GLX_eglTerminate
;
554 GLX_drv
->Base
.API
.CreateContext
= GLX_eglCreateContext
;
555 GLX_drv
->Base
.API
.MakeCurrent
= GLX_eglMakeCurrent
;
556 GLX_drv
->Base
.API
.CreateWindowSurface
= GLX_eglCreateWindowSurface
;
557 GLX_drv
->Base
.API
.DestroySurface
= GLX_eglDestroySurface
;
558 GLX_drv
->Base
.API
.BindTexImage
= GLX_eglBindTexImage
;
559 GLX_drv
->Base
.API
.ReleaseTexImage
= GLX_eglReleaseTexImage
;
560 GLX_drv
->Base
.API
.SwapBuffers
= GLX_eglSwapBuffers
;
561 GLX_drv
->Base
.API
.GetProcAddress
= GLX_eglGetProcAddress
;
563 GLX_drv
->Base
.ClientAPIsMask
= all_apis
;
564 GLX_drv
->Base
.Name
= "GLX";
566 _eglLog(_EGL_DEBUG
, "GLX: main(%s)", args
);
568 /* set new DRI path to pick up EGL version (no mesa code), but don't
569 * override if one is already set.
571 setenv("LIBGL_DRIVERS_PATH", DEFAULT_DRIVER_DIR
"/egl", 0);
573 return &GLX_drv
->Base
;