Merge branch 'mesa_7_6_branch' into mesa_7_7_branch
[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 #include <stdlib.h>
37 #include <string.h>
38 #include <X11/Xlib.h>
39 #include <GL/glx.h>
40
41 #include "eglconfigutil.h"
42 #include "eglconfig.h"
43 #include "eglcontext.h"
44 #include "egldisplay.h"
45 #include "egldriver.h"
46 #include "eglglobals.h"
47 #include "egllog.h"
48 #include "eglsurface.h"
49
50 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
51 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
52
53 #ifndef GLX_VERSION_1_4
54 #error "GL/glx.h must be equal to or greater than GLX 1.4"
55 #endif
56
57 /*
58 * report OpenGL ES bits because apps usually forget to specify
59 * EGL_RENDERABLE_TYPE when choosing configs
60 */
61 #define GLX_EGL_APIS (EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)
62
63
64 /** subclass of _EGLDriver */
65 struct GLX_egl_driver
66 {
67 _EGLDriver Base; /**< base class */
68 };
69
70
71 /** driver data of _EGLDisplay */
72 struct GLX_egl_display
73 {
74 Display *dpy;
75 XVisualInfo *visuals;
76 GLXFBConfig *fbconfigs;
77
78 int glx_maj, glx_min;
79
80 const char *extensions;
81 EGLBoolean have_1_3;
82 EGLBoolean have_make_current_read;
83 EGLBoolean have_fbconfig;
84 EGLBoolean have_pbuffer;
85
86 /* GLX_SGIX_pbuffer */
87 PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
88 PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
89
90 /* workaround quirks of different GLX implementations */
91 EGLBoolean single_buffered_quirk;
92 EGLBoolean glx_window_quirk;
93
94 };
95
96
97 /** subclass of _EGLContext */
98 struct GLX_egl_context
99 {
100 _EGLContext Base; /**< base class */
101
102 GLXContext context;
103 };
104
105
106 /** subclass of _EGLSurface */
107 struct GLX_egl_surface
108 {
109 _EGLSurface Base; /**< base class */
110
111 Drawable drawable;
112 GLXDrawable glx_drawable;
113 };
114
115
116 /** subclass of _EGLConfig */
117 struct GLX_egl_config
118 {
119 _EGLConfig Base; /**< base class */
120 EGLBoolean double_buffered;
121 int index;
122 };
123
124 /** cast wrapper */
125 static struct GLX_egl_driver *
126 GLX_egl_driver(_EGLDriver *drv)
127 {
128 return (struct GLX_egl_driver *) drv;
129 }
130
131 static struct GLX_egl_display *
132 GLX_egl_display(_EGLDisplay *dpy)
133 {
134 return (struct GLX_egl_display *) dpy->DriverData;
135 }
136
137 static struct GLX_egl_context *
138 GLX_egl_context(_EGLContext *ctx)
139 {
140 return (struct GLX_egl_context *) ctx;
141 }
142
143 static struct GLX_egl_surface *
144 GLX_egl_surface(_EGLSurface *surf)
145 {
146 return (struct GLX_egl_surface *) surf;
147 }
148
149 static int
150 GLX_egl_config_index(_EGLConfig *conf)
151 {
152 return ((struct GLX_egl_config *) conf)->index;
153 }
154
155
156 #define MAP_ATTRIB(attr, memb) \
157 { attr, offsetof(__GLcontextModes, memb) }
158
159
160 static const struct {
161 int attr;
162 int offset;
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),
198 };
199
200
201 static EGLBoolean
202 convert_fbconfig(Display *dpy, GLXFBConfig fbconfig,
203 struct GLX_egl_config *GLX_conf)
204 {
205 __GLcontextModes mode;
206 int err = 0, attr, val, i;
207
208 memset(&mode, 0, sizeof(mode));
209
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);
214 if (err) {
215 if (err == GLX_BAD_ATTRIBUTE) {
216 err = 0;
217 continue;
218 }
219 break;
220 }
221 *((int *) ((char *) &mode + offset)) = val;
222 }
223 if (err)
224 return EGL_FALSE;
225
226 /* must have rgba bit */
227 if (!(mode.renderType & GLX_RGBA_BIT))
228 return EGL_FALSE;
229
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)
234 return EGL_FALSE;
235 }
236
237 mode.rgbMode = GL_TRUE;
238 mode.haveAccumBuffer = (mode.accumRedBits +
239 mode.accumGreenBits +
240 mode.accumBlueBits +
241 mode.accumAlphaBits > 0);
242 mode.haveDepthBuffer = (mode.depthBits > 0);
243 mode.haveStencilBuffer = (mode.stencilBits > 0);
244
245 GLX_conf->double_buffered = (mode.doubleBufferMode != 0);
246 return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode,
247 GLX_EGL_APIS, GLX_EGL_APIS);
248 }
249
250
251 static const struct {
252 int attr;
253 int offset;
254 } visual_attributes[] = {
255 /* table 3.7 of GLX 1.4 */
256 /* no GLX_USE_GL */
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),
278 };
279
280
281 static int
282 get_visual_type(const XVisualInfo *vis)
283 {
284 int klass;
285
286 #if defined(__cplusplus) || defined(c_plusplus)
287 klass = vis->c_class;
288 #else
289 klass = vis->class;
290 #endif
291
292 switch (klass) {
293 case TrueColor:
294 return GLX_TRUE_COLOR;
295 case DirectColor:
296 return GLX_DIRECT_COLOR;
297 case PseudoColor:
298 return GLX_PSEUDO_COLOR;
299 case StaticColor:
300 return GLX_STATIC_COLOR;
301 case GrayScale:
302 return GLX_GRAY_SCALE;
303 case StaticGray:
304 return GLX_STATIC_GRAY;
305 default:
306 return GLX_NONE;
307 }
308 }
309
310
311 static EGLBoolean
312 convert_visual(Display *dpy, XVisualInfo *vinfo,
313 struct GLX_egl_config *GLX_conf)
314 {
315 __GLcontextModes mode;
316 int err, attr, val, i;
317
318 /* the visual must support OpenGL */
319 err = glXGetConfig(dpy, vinfo, GLX_USE_GL, &val);
320 if (err || !val)
321 return EGL_FALSE;
322
323 memset(&mode, 0, sizeof(mode));
324
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);
329 if (err) {
330 if (err == GLX_BAD_ATTRIBUTE) {
331 err = 0;
332 continue;
333 }
334 break;
335 }
336 *((int *) ((char *) &mode + offset)) = val;
337 }
338 if (err)
339 return EGL_FALSE;
340
341 /* must be RGB mode */
342 if (!mode.rgbMode)
343 return EGL_FALSE;
344
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;
350
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;
355
356 mode.renderType = GLX_RGBA_BIT;
357 mode.xRenderable = GL_TRUE;
358 mode.haveAccumBuffer = (mode.accumRedBits +
359 mode.accumGreenBits +
360 mode.accumBlueBits +
361 mode.accumAlphaBits > 0);
362 mode.haveDepthBuffer = (mode.depthBits > 0);
363 mode.haveStencilBuffer = (mode.stencilBits > 0);
364
365 GLX_conf->double_buffered = (mode.doubleBufferMode != 0);
366 return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode,
367 GLX_EGL_APIS, GLX_EGL_APIS);
368 }
369
370
371 static void
372 fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf)
373 {
374 _EGLConfig *conf = &GLX_conf->Base;
375 EGLint surface_type, r, g, b, a;
376
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);
385 }
386
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);
391 }
392
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);
399 }
400
401
402 static EGLBoolean
403 create_configs(_EGLDisplay *dpy, struct GLX_egl_display *GLX_dpy,
404 EGLint screen)
405 {
406 EGLint num_configs = 0, i;
407 EGLint id = 1;
408
409 if (GLX_dpy->have_fbconfig) {
410 GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs);
411 }
412 else {
413 XVisualInfo vinfo_template;
414 long mask;
415
416 vinfo_template.screen = screen;
417 mask = VisualScreenMask;
418 GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &vinfo_template,
419 &num_configs);
420 }
421
422 if (!num_configs)
423 return EGL_FALSE;
424
425 for (i = 0; i < num_configs; i++) {
426 struct GLX_egl_config *GLX_conf, template;
427 EGLBoolean ok;
428
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);
433 else
434 ok = convert_visual(GLX_dpy->dpy, &GLX_dpy->visuals[i], &template);
435 if (!ok)
436 continue;
437
438 fix_config(GLX_dpy, &template);
439 if (!_eglValidateConfig(&template.Base, EGL_FALSE)) {
440 _eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i);
441 continue;
442 }
443
444 GLX_conf = CALLOC_STRUCT(GLX_egl_config);
445 if (GLX_conf) {
446 memcpy(GLX_conf, &template, sizeof(template));
447 GLX_conf->index = i;
448
449 _eglAddConfig(dpy, &GLX_conf->Base);
450 id++;
451 }
452 }
453
454 return EGL_TRUE;
455 }
456
457
458 static void
459 check_extensions(struct GLX_egl_display *GLX_dpy, EGLint screen)
460 {
461 GLX_dpy->extensions =
462 glXQueryExtensionsString(GLX_dpy->dpy, screen);
463 if (GLX_dpy->extensions) {
464 /* glXGetProcAddress is assumed */
465
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;
469 }
470
471 if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) {
472 /* GLX 1.3 entry points are used */
473 GLX_dpy->have_fbconfig = EGL_TRUE;
474 }
475
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");
481
482 if (GLX_dpy->glXCreateGLXPbufferSGIX &&
483 GLX_dpy->glXDestroyGLXPbufferSGIX &&
484 GLX_dpy->have_fbconfig)
485 GLX_dpy->have_pbuffer = EGL_TRUE;
486 }
487 }
488
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;
494 }
495 }
496
497
498 static void
499 check_quirks(struct GLX_egl_display *GLX_dpy, EGLint screen)
500 {
501 const char *vendor;
502
503 GLX_dpy->single_buffered_quirk = EGL_TRUE;
504 GLX_dpy->glx_window_quirk = EGL_TRUE;
505
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;
513 }
514 }
515 }
516
517
518 /**
519 * Called via eglInitialize(), GLX_drv->API.Initialize().
520 */
521 static EGLBoolean
522 GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
523 EGLint *major, EGLint *minor)
524 {
525 struct GLX_egl_display *GLX_dpy;
526
527 GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
528 if (!GLX_dpy)
529 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
530
531 GLX_dpy->dpy = (Display *) disp->NativeDisplay;
532 if (!GLX_dpy->dpy) {
533 GLX_dpy->dpy = XOpenDisplay(NULL);
534 if (!GLX_dpy->dpy) {
535 _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed");
536 free(GLX_dpy);
537 return EGL_FALSE;
538 }
539 }
540
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);
545 free(GLX_dpy);
546 return EGL_FALSE;
547 }
548
549 check_extensions(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
550 check_quirks(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
551
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);
557 free(GLX_dpy);
558 return EGL_FALSE;
559 }
560
561 disp->DriverData = (void *) GLX_dpy;
562 disp->ClientAPIsMask = GLX_EGL_APIS;
563
564 /* we're supporting EGL 1.4 */
565 *major = 1;
566 *minor = 4;
567
568 return EGL_TRUE;
569 }
570
571 /**
572 * Called via eglTerminate(), drv->API.Terminate().
573 */
574 static EGLBoolean
575 GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
576 {
577 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
578
579 _eglReleaseDisplayResources(drv, disp);
580 _eglCleanupDisplay(disp);
581
582 if (GLX_dpy->visuals)
583 XFree(GLX_dpy->visuals);
584 if (GLX_dpy->fbconfigs)
585 XFree(GLX_dpy->fbconfigs);
586
587 if (!disp->NativeDisplay)
588 XCloseDisplay(GLX_dpy->dpy);
589 free(GLX_dpy);
590
591 disp->DriverData = NULL;
592
593 return EGL_TRUE;
594 }
595
596
597 /**
598 * Called via eglCreateContext(), drv->API.CreateContext().
599 */
600 static _EGLContext *
601 GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
602 _EGLContext *share_list, const EGLint *attrib_list)
603 {
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);
607
608 if (!GLX_ctx) {
609 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
610 return NULL;
611 }
612
613 if (!_eglInitContext(drv, &GLX_ctx->Base, conf, attrib_list)) {
614 free(GLX_ctx);
615 return NULL;
616 }
617
618 if (GLX_dpy->have_fbconfig)
619 GLX_ctx->context =
620 glXCreateNewContext(GLX_dpy->dpy,
621 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
622 GLX_RGBA_TYPE,
623 GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
624 GL_TRUE);
625 else
626 GLX_ctx->context =
627 glXCreateContext(GLX_dpy->dpy,
628 &GLX_dpy->visuals[GLX_egl_config_index(conf)],
629 GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
630 GL_TRUE);
631 if (!GLX_ctx->context) {
632 free(GLX_ctx);
633 return NULL;
634 }
635
636 return &GLX_ctx->Base;
637 }
638
639
640 /**
641 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
642 */
643 static EGLBoolean
644 GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
645 _EGLSurface *rsurf, _EGLContext *ctx)
646 {
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;
652 GLXContext cctx;
653
654 if (!_eglMakeCurrent(drv, disp, dsurf, rsurf, ctx))
655 return EGL_FALSE;
656
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;
660
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);
665
666 return EGL_FALSE;
667 }
668
669 /** Get size of given window */
670 static Status
671 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
672 {
673 Window root;
674 Status stat;
675 int xpos, ypos;
676 unsigned int w, h, bw, depth;
677 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
678 *width = w;
679 *height = h;
680 return stat;
681 }
682
683 /**
684 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
685 */
686 static _EGLSurface *
687 GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
688 NativeWindowType window, const EGLint *attrib_list)
689 {
690 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
691 struct GLX_egl_surface *GLX_surf;
692 uint width, height;
693
694 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
695 if (!GLX_surf) {
696 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
697 return NULL;
698 }
699
700 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_WINDOW_BIT,
701 conf, attrib_list)) {
702 free(GLX_surf);
703 return NULL;
704 }
705
706 GLX_surf->drawable = window;
707
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);
713 else
714 GLX_surf->glx_drawable = GLX_surf->drawable;
715
716 if (!GLX_surf->glx_drawable) {
717 free(GLX_surf);
718 return NULL;
719 }
720
721 get_drawable_size(GLX_dpy->dpy, window, &width, &height);
722 GLX_surf->Base.Width = width;
723 GLX_surf->Base.Height = height;
724
725 return &GLX_surf->Base;
726 }
727
728 static _EGLSurface *
729 GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
730 NativePixmapType pixmap, const EGLint *attrib_list)
731 {
732 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
733 struct GLX_egl_surface *GLX_surf;
734 uint width, height;
735
736 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
737 if (!GLX_surf) {
738 _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
739 return NULL;
740 }
741
742 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PIXMAP_BIT,
743 conf, attrib_list)) {
744 free(GLX_surf);
745 return NULL;
746 }
747
748 GLX_surf->drawable = pixmap;
749
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);
755 }
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);
759 if (vinfo) {
760 GLX_surf->glx_drawable =
761 glXCreateGLXPixmap(GLX_dpy->dpy, vinfo, GLX_surf->drawable);
762 XFree(vinfo);
763 }
764 }
765 else {
766 GLX_surf->glx_drawable =
767 glXCreateGLXPixmap(GLX_dpy->dpy,
768 &GLX_dpy->visuals[GLX_egl_config_index(conf)],
769 GLX_surf->drawable);
770 }
771
772 if (!GLX_surf->glx_drawable) {
773 free(GLX_surf);
774 return NULL;
775 }
776
777 get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height);
778 GLX_surf->Base.Width = width;
779 GLX_surf->Base.Height = height;
780
781 return &GLX_surf->Base;
782 }
783
784 static _EGLSurface *
785 GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
786 _EGLConfig *conf, const EGLint *attrib_list)
787 {
788 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
789 struct GLX_egl_surface *GLX_surf;
790 int attribs[5];
791 int i;
792
793 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
794 if (!GLX_surf) {
795 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
796 return NULL;
797 }
798
799 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PBUFFER_BIT,
800 conf, attrib_list)) {
801 free(GLX_surf);
802 return NULL;
803 }
804
805 i = 0;
806 attribs[i] = None;
807
808 GLX_surf->drawable = None;
809
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;
815 }
816 if (GLX_surf->Base.Height) {
817 attribs[i++] = GLX_PBUFFER_HEIGHT;
818 attribs[i++] = GLX_surf->Base.Height;
819 }
820 attribs[i] = None;
821
822 GLX_surf->glx_drawable =
823 glXCreatePbuffer(GLX_dpy->dpy,
824 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
825 attribs);
826 }
827 else if (GLX_dpy->have_pbuffer) {
828 GLX_surf->glx_drawable = GLX_dpy->glXCreateGLXPbufferSGIX(
829 GLX_dpy->dpy,
830 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
831 GLX_surf->Base.Width,
832 GLX_surf->Base.Height,
833 attribs);
834 }
835
836 if (!GLX_surf->glx_drawable) {
837 free(GLX_surf);
838 return NULL;
839 }
840
841 return &GLX_surf->Base;
842 }
843
844 static EGLBoolean
845 GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
846 {
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);
850
851 if (GLX_dpy->have_1_3) {
852 switch (surf->Type) {
853 case EGL_WINDOW_BIT:
854 if (!GLX_dpy->glx_window_quirk)
855 glXDestroyWindow(GLX_dpy->dpy, GLX_surf->glx_drawable);
856 break;
857 case EGL_PBUFFER_BIT:
858 glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->glx_drawable);
859 break;
860 case EGL_PIXMAP_BIT:
861 glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable);
862 break;
863 default:
864 break;
865 }
866 }
867 else {
868 switch (surf->Type) {
869 case EGL_PBUFFER_BIT:
870 GLX_dpy->glXDestroyGLXPbufferSGIX(GLX_dpy->dpy,
871 GLX_surf->glx_drawable);
872 break;
873 case EGL_PIXMAP_BIT:
874 glXDestroyGLXPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable);
875 break;
876 default:
877 break;
878 }
879 }
880 free(surf);
881 }
882
883 return EGL_TRUE;
884 }
885
886
887 static EGLBoolean
888 GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
889 {
890 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
891 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
892
893 glXSwapBuffers(GLX_dpy->dpy, GLX_surf->glx_drawable);
894
895 return EGL_TRUE;
896 }
897
898 /*
899 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
900 */
901 static _EGLProc
902 GLX_eglGetProcAddress(const char *procname)
903 {
904 return (_EGLProc) glXGetProcAddress((const GLubyte *) procname);
905 }
906
907 static EGLBoolean
908 GLX_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
909 {
910 glXWaitGL();
911 return EGL_TRUE;
912 }
913
914 static EGLBoolean
915 GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
916 {
917 if (engine != EGL_CORE_NATIVE_ENGINE)
918 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
919 glXWaitX();
920 return EGL_TRUE;
921 }
922
923 static void
924 GLX_Unload(_EGLDriver *drv)
925 {
926 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
927 free(GLX_drv);
928 }
929
930
931 /**
932 * This is the main entrypoint into the driver, called by libEGL.
933 * Create a new _EGLDriver object and init its dispatch table.
934 */
935 _EGLDriver *
936 _eglMain(const char *args)
937 {
938 struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
939
940 if (!GLX_drv)
941 return NULL;
942
943 _eglInitDriverFallbacks(&GLX_drv->Base);
944 GLX_drv->Base.API.Initialize = GLX_eglInitialize;
945 GLX_drv->Base.API.Terminate = GLX_eglTerminate;
946 GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
947 GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
948 GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
949 GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
950 GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
951 GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
952 GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
953 GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
954 GLX_drv->Base.API.WaitClient = GLX_eglWaitClient;
955 GLX_drv->Base.API.WaitNative = GLX_eglWaitNative;
956
957 GLX_drv->Base.Name = "GLX";
958 GLX_drv->Base.Unload = GLX_Unload;
959
960 return &GLX_drv->Base;
961 }