Merge commit 'origin/gallium-0.1'
[mesa.git] / src / egl / drivers / glx / egl_glx.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28
29 /**
30 * This is an EGL driver that wraps GLX. This gives the benefit of being
31 * completely agnostic of the direct rendering implementation.
32 *
33 * Authors: Alan Hourihane <alanh@tungstengraphics.com>
34 */
35
36 /*
37 * TODO:
38 *
39 * test eglBind/ReleaseTexImage
40 */
41
42
43 #include <assert.h>
44 #include <stdio.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include "dlfcn.h"
49 #include <X11/Xlib.h>
50 #include <GL/gl.h>
51 #include "glxclient.h"
52
53 #define _EGL_PLATFORM_X
54
55 #include "eglconfig.h"
56 #include "eglcontext.h"
57 #include "egldisplay.h"
58 #include "egldriver.h"
59 #include "eglglobals.h"
60 #include "eglhash.h"
61 #include "egllog.h"
62 #include "eglsurface.h"
63
64 #include <GL/gl.h>
65
66 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
67
68 static const EGLint all_apis = (EGL_OPENGL_ES_BIT
69 | EGL_OPENGL_ES2_BIT
70 | EGL_OPENVG_BIT
71 /* | EGL_OPENGL_BIT */); /* can't do */
72
73 struct visual_attribs
74 {
75 /* X visual attribs */
76 int id;
77 int klass;
78 int depth;
79 int redMask, greenMask, blueMask;
80 int colormapSize;
81 int bitsPerRGB;
82
83 /* GL visual attribs */
84 int supportsGL;
85 int transparentType;
86 int transparentRedValue;
87 int transparentGreenValue;
88 int transparentBlueValue;
89 int transparentAlphaValue;
90 int transparentIndexValue;
91 int bufferSize;
92 int level;
93 int render_type;
94 int doubleBuffer;
95 int stereo;
96 int auxBuffers;
97 int redSize, greenSize, blueSize, alphaSize;
98 int depthSize;
99 int stencilSize;
100 int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
101 int numSamples, numMultisample;
102 int visualCaveat;
103 };
104
105 /** subclass of _EGLDriver */
106 struct GLX_egl_driver
107 {
108 _EGLDriver Base; /**< base class */
109
110 XVisualInfo *visuals;
111 GLXFBConfig *fbconfigs;
112
113 int glx_maj, glx_min;
114 };
115
116
117 /** subclass of _EGLContext */
118 struct GLX_egl_context
119 {
120 _EGLContext Base; /**< base class */
121
122 GLXContext context;
123 };
124
125
126 /** subclass of _EGLSurface */
127 struct GLX_egl_surface
128 {
129 _EGLSurface Base; /**< base class */
130
131 GLXDrawable drawable;
132 };
133
134
135 /** subclass of _EGLConfig */
136 struct GLX_egl_config
137 {
138 _EGLConfig Base; /**< base class */
139 };
140
141 /** cast wrapper */
142 static struct GLX_egl_driver *
143 GLX_egl_driver(_EGLDriver *drv)
144 {
145 return (struct GLX_egl_driver *) drv;
146 }
147
148 static struct GLX_egl_context *
149 GLX_egl_context(_EGLContext *ctx)
150 {
151 return (struct GLX_egl_context *) ctx;
152 }
153
154 static struct GLX_egl_surface *
155 GLX_egl_surface(_EGLSurface *surf)
156 {
157 return (struct GLX_egl_surface *) surf;
158 }
159
160 static GLboolean
161 get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
162 struct visual_attribs *attribs)
163 {
164 const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
165 int rgba;
166
167 memset(attribs, 0, sizeof(struct visual_attribs));
168
169 attribs->id = vInfo->visualid;
170 #if defined(__cplusplus) || defined(c_plusplus)
171 attribs->klass = vInfo->c_class;
172 #else
173 attribs->klass = vInfo->class;
174 #endif
175 attribs->depth = vInfo->depth;
176 attribs->redMask = vInfo->red_mask;
177 attribs->greenMask = vInfo->green_mask;
178 attribs->blueMask = vInfo->blue_mask;
179 attribs->colormapSize = vInfo->colormap_size;
180 attribs->bitsPerRGB = vInfo->bits_per_rgb;
181
182 if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
183 !attribs->supportsGL)
184 return GL_FALSE;
185 glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
186 glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
187 glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
188 if (!rgba)
189 return GL_FALSE;
190 attribs->render_type = GLX_RGBA_BIT;
191
192 glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
193 if (!attribs->doubleBuffer)
194 return GL_FALSE;
195
196 glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
197 glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
198 glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
199 glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
200 glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
201 glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
202 glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
203 glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
204 glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
205 glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
206 glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
207 glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
208
209 /* get transparent pixel stuff */
210 glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
211 if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
212 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
213 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
214 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
215 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
216 }
217 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
218 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
219 }
220
221 /* multisample attribs */
222 #ifdef GLX_ARB_multisample
223 if (ext && strstr(ext, "GLX_ARB_multisample")) {
224 glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
225 glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
226 }
227 #endif
228 else {
229 attribs->numSamples = 0;
230 attribs->numMultisample = 0;
231 }
232
233 #if defined(GLX_EXT_visual_rating)
234 if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
235 glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
236 }
237 else {
238 attribs->visualCaveat = GLX_NONE_EXT;
239 }
240 #else
241 attribs->visualCaveat = 0;
242 #endif
243
244 return GL_TRUE;
245 }
246
247 #ifdef GLX_VERSION_1_3
248
249 static int
250 glx_token_to_visual_class(int visual_type)
251 {
252 switch (visual_type) {
253 case GLX_TRUE_COLOR:
254 return TrueColor;
255 case GLX_DIRECT_COLOR:
256 return DirectColor;
257 case GLX_PSEUDO_COLOR:
258 return PseudoColor;
259 case GLX_STATIC_COLOR:
260 return StaticColor;
261 case GLX_GRAY_SCALE:
262 return GrayScale;
263 case GLX_STATIC_GRAY:
264 return StaticGray;
265 case GLX_NONE:
266 default:
267 return None;
268 }
269 }
270 static int
271 get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
272 struct visual_attribs *attribs)
273 {
274 int visual_type;
275 int fbconfig_id;
276
277 memset(attribs, 0, sizeof(struct visual_attribs));
278
279 glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &fbconfig_id);
280
281 glXGetFBConfigAttrib(dpy, fbconfig, GLX_VISUAL_ID, &attribs->id);
282
283 #if 0
284 attribs->depth = vInfo->depth;
285 attribs->redMask = vInfo->red_mask;
286 attribs->greenMask = vInfo->green_mask;
287 attribs->blueMask = vInfo->blue_mask;
288 attribs->colormapSize = vInfo->colormap_size;
289 attribs->bitsPerRGB = vInfo->bits_per_rgb;
290 #endif
291
292 glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
293 attribs->klass = glx_token_to_visual_class(visual_type);
294
295 glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
296 glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
297 glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
298 if (!(attribs->render_type & GLX_RGBA_BIT))
299 return 0;
300
301 glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
302 if (!attribs->doubleBuffer)
303 return 0;
304
305 glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
306 glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
307
308 glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
309 glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
310 glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
311 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
312 glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
313 glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
314
315 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
316 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
317 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
318 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
319
320 /* get transparent pixel stuff */
321 glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
322 if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
323 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
324 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
325 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
326 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
327 }
328 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
329 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
330 }
331
332 glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
333 glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
334
335 glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
336
337 if (attribs->id == 0) {
338 attribs->id = fbconfig_id;
339 return EGL_PBUFFER_BIT | EGL_PIXMAP_BIT;
340 }
341
342 return EGL_WINDOW_BIT;
343 }
344
345 #endif
346
347 static EGLBoolean
348 create_configs(_EGLDisplay *disp, struct GLX_egl_driver *GLX_drv)
349 {
350 XVisualInfo theTemplate;
351 int numVisuals;
352 long mask;
353 int i;
354 int egl_configs = 1;
355 struct visual_attribs attribs;
356
357 GLX_drv->fbconfigs = NULL;
358
359 #ifdef GLX_VERSION_1_3
360 /* get list of all fbconfigs on this screen */
361 GLX_drv->fbconfigs = glXGetFBConfigs(disp->Xdpy, DefaultScreen(disp->Xdpy), &numVisuals);
362
363 if (numVisuals == 0) {
364 GLX_drv->fbconfigs = NULL;
365 goto xvisual;
366 }
367
368 for (i = 0; i < numVisuals; i++) {
369 struct GLX_egl_config *config;
370 int bit;
371
372 bit = get_fbconfig_attribs(disp->Xdpy, GLX_drv->fbconfigs[i], &attribs);
373 if (!bit)
374 continue;
375
376 config = CALLOC_STRUCT(GLX_egl_config);
377
378 _eglInitConfig(&config->Base, (i+1));
379 SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
380 SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
381 SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
382 SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
383 SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
384 SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
385 SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
386 SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
387 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
388 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
389 SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
390 SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
391 SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, bit);
392
393 /* XXX possibly other things to init... */
394
395 _eglAddConfig(disp, &config->Base);
396 }
397
398 goto end;
399 #endif
400
401 xvisual:
402 /* get list of all visuals on this screen */
403 theTemplate.screen = DefaultScreen(disp->Xdpy);
404 mask = VisualScreenMask;
405 GLX_drv->visuals = XGetVisualInfo(disp->Xdpy, mask, &theTemplate, &numVisuals);
406
407 for (i = 0; i < numVisuals; i++) {
408 struct GLX_egl_config *config;
409
410 if (!get_visual_attribs(disp->Xdpy, &GLX_drv->visuals[i], &attribs))
411 continue;
412
413 config = CALLOC_STRUCT(GLX_egl_config);
414
415 _eglInitConfig(&config->Base, (i+1));
416 SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
417 SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
418 SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
419 SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
420 SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
421 SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
422 SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
423 SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
424 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
425 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
426 SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
427 SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
428 SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE,
429 (EGL_WINDOW_BIT /*| EGL_PBUFFER_BIT | EGL_PIXMAP_BIT*/));
430
431 /* XXX possibly other things to init... */
432
433 _eglAddConfig(disp, &config->Base);
434 }
435
436 end:
437 return EGL_TRUE;
438 }
439
440 /**
441 * Called via eglInitialize(), GLX_drv->API.Initialize().
442 */
443 static EGLBoolean
444 GLX_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
445 EGLint *minor, EGLint *major)
446 {
447 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
448 _EGLDisplay *disp = _eglLookupDisplay(dpy);
449
450 _eglLog(_EGL_DEBUG, "GLX: eglInitialize");
451
452 if (!disp->Xdpy) {
453 disp->Xdpy = XOpenDisplay(NULL);
454 if (!disp->Xdpy) {
455 _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed");
456 return EGL_FALSE;
457 }
458 }
459
460 glXQueryVersion(disp->Xdpy, &GLX_drv->glx_maj, &GLX_drv->glx_min);
461
462 GLX_drv->Base.Initialized = EGL_TRUE;
463
464 GLX_drv->Base.Name = "GLX";
465
466 /* we're supporting EGL 1.4 */
467 *minor = 1;
468 *major = 4;
469
470 create_configs(disp, GLX_drv);
471
472 return EGL_TRUE;
473 }
474
475 /*
476 * Do some clean-up that normally occurs in XCloseDisplay().
477 * We do this here because we're about to unload a dynamic library
478 * that has added some per-display extension data and callbacks.
479 * If we don't do this here we'll crash in XCloseDisplay() because it'll
480 * try to call functions that went away when the driver library was unloaded.
481 */
482 static void
483 FreeDisplayExt(Display *dpy)
484 {
485 _XExtension *ext, *next;
486
487 for (ext = dpy->ext_procs; ext; ext = next) {
488 next = ext->next;
489 if (ext->close_display) {
490 ext->close_display(dpy, &ext->codes);
491 ext->close_display = NULL;
492 }
493 if (ext->name)
494 Xfree(ext->name);
495 Xfree(ext);
496 }
497 dpy->ext_procs = NULL;
498
499 _XFreeExtData (dpy->ext_data);
500 dpy->ext_data = NULL;
501 }
502
503 /**
504 * Called via eglTerminate(), drv->API.Terminate().
505 */
506 static EGLBoolean
507 GLX_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
508 {
509 _EGLDisplay *disp = _eglLookupDisplay(dpy);
510
511 _eglLog(_EGL_DEBUG, "GLX: eglTerminate");
512
513 FreeDisplayExt(disp->Xdpy);
514
515 return EGL_TRUE;
516 }
517
518
519 /**
520 * Called via eglCreateContext(), drv->API.CreateContext().
521 */
522 static EGLContext
523 GLX_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
524 EGLContext share_list, const EGLint *attrib_list)
525 {
526 _EGLDisplay *disp = _eglLookupDisplay(dpy);
527 struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
528 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
529 struct GLX_egl_context *GLX_ctx_shared = NULL;
530 _EGLConfig *conf;
531
532 if (!GLX_ctx)
533 return EGL_NO_CONTEXT;
534
535 if (!_eglInitContext(drv, dpy, &GLX_ctx->Base, config, attrib_list)) {
536 free(GLX_ctx);
537 return EGL_NO_CONTEXT;
538 }
539
540 if (share_list != EGL_NO_CONTEXT) {
541 _EGLContext *shareCtx = _eglLookupContext(share_list);
542 if (!shareCtx) {
543 _eglError(EGL_BAD_CONTEXT, "eglCreateContext(share_list)");
544 return EGL_FALSE;
545 }
546 GLX_ctx_shared = GLX_egl_context(shareCtx);
547 }
548
549 conf = _eglLookupConfig(drv, dpy, config);
550 assert(conf);
551
552 #ifdef GLX_VERSION_1_3
553 if (GLX_drv->fbconfigs)
554 GLX_ctx->context = glXCreateNewContext(disp->Xdpy, GLX_drv->fbconfigs[(int)config-1], GLX_RGBA_TYPE, GLX_ctx_shared ? GLX_ctx_shared->context : NULL, GL_TRUE);
555 else
556 #endif
557 GLX_ctx->context = glXCreateContext(disp->Xdpy, &GLX_drv->visuals[(int)config-1], GLX_ctx_shared ? GLX_ctx_shared->context : NULL, GL_TRUE);
558 if (!GLX_ctx->context)
559 return EGL_FALSE;
560
561 #if 1
562 /* (maybe?) need to have a direct rendering context */
563 if (!glXIsDirect(disp->Xdpy, GLX_ctx->context))
564 return EGL_FALSE;
565 #endif
566
567 return _eglGetContextHandle(&GLX_ctx->Base);
568 }
569
570
571 /**
572 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
573 */
574 static EGLBoolean
575 GLX_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
576 EGLSurface r, EGLContext context)
577 {
578 _EGLDisplay *disp = _eglLookupDisplay(dpy);
579 _EGLContext *ctx = _eglLookupContext(context);
580 _EGLSurface *dsurf = _eglLookupSurface(d);
581 _EGLSurface *rsurf = _eglLookupSurface(r);
582 struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
583 struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
584 struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
585
586 if (!_eglMakeCurrent(drv, dpy, d, r, context))
587 return EGL_FALSE;
588
589 #ifdef GLX_VERSION_1_3
590 if (!glXMakeContextCurrent(disp->Xdpy, GLX_dsurf ? GLX_dsurf->drawable : 0, GLX_rsurf ? GLX_rsurf->drawable : 0, GLX_ctx ? GLX_ctx->context : NULL))
591 #endif
592 if (!glXMakeCurrent(disp->Xdpy, GLX_dsurf ? GLX_dsurf->drawable : 0, GLX_ctx ? GLX_ctx->context : NULL))
593 return EGL_FALSE;
594
595 return EGL_TRUE;
596 }
597
598 /** Get size of given window */
599 static Status
600 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
601 {
602 Window root;
603 Status stat;
604 int xpos, ypos;
605 unsigned int w, h, bw, depth;
606 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
607 *width = w;
608 *height = h;
609 return stat;
610 }
611
612 /**
613 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
614 */
615 static EGLSurface
616 GLX_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
617 NativeWindowType window, const EGLint *attrib_list)
618 {
619 _EGLDisplay *disp = _eglLookupDisplay(dpy);
620 struct GLX_egl_surface *GLX_surf;
621 uint width, height;
622
623 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
624 if (!GLX_surf)
625 return EGL_NO_SURFACE;
626
627 if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_WINDOW_BIT,
628 config, attrib_list)) {
629 free(GLX_surf);
630 return EGL_FALSE;
631 }
632
633 _eglSaveSurface(&GLX_surf->Base);
634
635 GLX_surf->drawable = window;
636 get_drawable_size(disp->Xdpy, window, &width, &height);
637 GLX_surf->Base.Width = width;
638 GLX_surf->Base.Height = height;
639
640 return _eglGetSurfaceHandle(&GLX_surf->Base);
641 }
642
643 #ifdef GLX_VERSION_1_3
644 static EGLSurface
645 GLX_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
646 NativePixmapType pixmap, const EGLint *attrib_list)
647 {
648 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
649 _EGLDisplay *disp = _eglLookupDisplay(dpy);
650 struct GLX_egl_surface *GLX_surf;
651 int i;
652
653 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
654 if (!GLX_surf)
655 return EGL_NO_SURFACE;
656
657 if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_PIXMAP_BIT,
658 config, attrib_list)) {
659 free(GLX_surf);
660 return EGL_FALSE;
661 }
662
663 _eglSaveSurface(&GLX_surf->Base);
664
665 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
666 switch (attrib_list[i]) {
667 /* no attribs at this time */
668 default:
669 _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
670 return EGL_NO_SURFACE;
671 }
672 }
673
674 GLX_surf->drawable = glXCreatePixmap(disp->Xdpy, GLX_drv->fbconfigs[(int)config-1], pixmap, NULL);
675
676 return _eglGetSurfaceHandle(&GLX_surf->Base);
677 }
678
679 static EGLSurface
680 GLX_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
681 const EGLint *attrib_list)
682 {
683 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
684 _EGLDisplay *disp = _eglLookupDisplay(dpy);
685 struct GLX_egl_surface *GLX_surf;
686 int attribs[5];
687 int i = 0, j = 0;
688
689 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
690 if (!GLX_surf)
691 return EGL_NO_SURFACE;
692
693 if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_PBUFFER_BIT,
694 config, attrib_list)) {
695 free(GLX_surf);
696 return EGL_NO_SURFACE;
697 }
698
699 _eglSaveSurface(&GLX_surf->Base);
700
701 while(attrib_list[i] != EGL_NONE) {
702 switch (attrib_list[i]) {
703 case EGL_WIDTH:
704 attribs[j++] = GLX_PBUFFER_WIDTH;
705 attribs[j++] = attrib_list[i+1];
706 break;
707 case EGL_HEIGHT:
708 attribs[j++] = GLX_PBUFFER_HEIGHT;
709 attribs[j++] = attrib_list[i+1];
710 break;
711 }
712 i++;
713 }
714 attribs[j++] = 0;
715
716 GLX_surf->drawable = glXCreatePbuffer(disp->Xdpy, GLX_drv->fbconfigs[(int)config-1], attribs);
717
718 return _eglGetSurfaceHandle(&GLX_surf->Base);
719 }
720 #endif
721
722 static EGLBoolean
723 GLX_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
724 {
725 _EGLDisplay *disp = _eglLookupDisplay(dpy);
726 _EGLSurface *surf = _eglLookupSurface(surface);
727 return EGL_TRUE;
728 if (surf) {
729 _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
730 if (surf->IsBound) {
731 surf->DeletePending = EGL_TRUE;
732 }
733 else {
734 free(surf);
735 }
736
737 return EGL_TRUE;
738 }
739 else {
740 _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
741 return EGL_FALSE;
742 }
743 }
744
745
746 static EGLBoolean
747 GLX_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
748 EGLint buffer)
749 {
750 _EGLDisplay *disp = _eglLookupDisplay(dpy);
751 _EGLSurface *surf = _eglLookupSurface(surface);
752 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
753
754 /* buffer ?? */
755 glXBindTexImageEXT(disp->Xdpy, GLX_surf->drawable, GLX_FRONT_LEFT_EXT, NULL);
756
757 return EGL_TRUE;
758 }
759
760
761 static EGLBoolean
762 GLX_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
763 EGLint buffer)
764 {
765 _EGLDisplay *disp = _eglLookupDisplay(dpy);
766 _EGLSurface *surf = _eglLookupSurface(surface);
767 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
768
769 /* buffer ?? */
770 glXReleaseTexImageEXT(disp->Xdpy, GLX_surf->drawable, GLX_FRONT_LEFT_EXT);
771
772 return EGL_TRUE;
773 }
774
775
776 static EGLBoolean
777 GLX_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
778 {
779 _EGLDisplay *disp = _eglLookupDisplay(dpy);
780 _EGLSurface *surf = _eglLookupSurface(draw);
781 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
782
783 _eglLog(_EGL_DEBUG, "GLX: EGL SwapBuffers 0x%x",draw);
784
785 /* error checking step: */
786 if (!_eglSwapBuffers(drv, dpy, draw))
787 return EGL_FALSE;
788
789 glXSwapBuffers(disp->Xdpy, GLX_surf->drawable);
790
791 return EGL_TRUE;
792 }
793
794 /*
795 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
796 */
797 static _EGLProc
798 GLX_eglGetProcAddress(const char *procname)
799 {
800 return (_EGLProc)glXGetProcAddress((const GLubyte *)procname);
801 }
802
803
804 /**
805 * This is the main entrypoint into the driver, called by libEGL.
806 * Create a new _EGLDriver object and init its dispatch table.
807 */
808 _EGLDriver *
809 _eglMain(_EGLDisplay *disp, const char *args)
810 {
811 struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
812 char *env;
813 int maj = 0, min = 0;
814
815 if (!GLX_drv)
816 return NULL;
817
818 _eglInitDriverFallbacks(&GLX_drv->Base);
819 GLX_drv->Base.API.Initialize = GLX_eglInitialize;
820 GLX_drv->Base.API.Terminate = GLX_eglTerminate;
821 GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
822 GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
823 GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
824 #ifdef GLX_VERSION_1_3
825 if (GLX_drv->glx_maj == 1 && GLX_drv->glx_min >= 3) {
826 GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
827 GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
828 printf("GLX: Pbuffer and Pixmap support\n");
829 } else {
830 printf("GLX: No pbuffer or pixmap support\n");
831 }
832 #endif
833 GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
834 GLX_drv->Base.API.BindTexImage = GLX_eglBindTexImage;
835 GLX_drv->Base.API.ReleaseTexImage = GLX_eglReleaseTexImage;
836 GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
837 GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
838
839 GLX_drv->Base.ClientAPIsMask = all_apis;
840 GLX_drv->Base.Name = "GLX";
841
842 _eglLog(_EGL_DEBUG, "GLX: main(%s)", args);
843
844 /* set new DRI path to pick up EGL version (which doesn't contain any mesa
845 * code), but don't override if one is already set.
846 */
847 env = getenv("LIBGL_DRIVERS_PATH");
848 if (env) {
849 if (!strstr(env, "egl")) {
850 sprintf(env, "%s/egl", env);
851 setenv("LIBGL_DRIVERS_PATH", env, 1);
852 }
853 } else
854 setenv("LIBGL_DRIVERS_PATH", DEFAULT_DRIVER_DIR"/egl", 0);
855
856 return &GLX_drv->Base;
857 }