Merge branch '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 /** subclass of _EGLDriver */
58 struct GLX_egl_driver
59 {
60 _EGLDriver Base; /**< base class */
61 };
62
63
64 /** driver data of _EGLDisplay */
65 struct GLX_egl_display
66 {
67 Display *dpy;
68 XVisualInfo *visuals;
69 GLXFBConfig *fbconfigs;
70
71 int glx_maj, glx_min;
72
73 const char *extensions;
74 EGLBoolean have_1_3;
75 EGLBoolean have_make_current_read;
76 EGLBoolean have_fbconfig;
77 EGLBoolean have_pbuffer;
78
79 /* GLX_SGIX_pbuffer */
80 PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
81 PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
82
83 /* workaround quirks of different GLX implementations */
84 EGLBoolean single_buffered_quirk;
85 EGLBoolean glx_window_quirk;
86
87 };
88
89
90 /** subclass of _EGLContext */
91 struct GLX_egl_context
92 {
93 _EGLContext Base; /**< base class */
94
95 GLXContext context;
96 };
97
98
99 /** subclass of _EGLSurface */
100 struct GLX_egl_surface
101 {
102 _EGLSurface Base; /**< base class */
103
104 Drawable drawable;
105 GLXDrawable glx_drawable;
106 };
107
108
109 /** subclass of _EGLConfig */
110 struct GLX_egl_config
111 {
112 _EGLConfig Base; /**< base class */
113 EGLBoolean double_buffered;
114 int index;
115 };
116
117 /** cast wrapper */
118 static struct GLX_egl_driver *
119 GLX_egl_driver(_EGLDriver *drv)
120 {
121 return (struct GLX_egl_driver *) drv;
122 }
123
124 static struct GLX_egl_display *
125 GLX_egl_display(_EGLDisplay *dpy)
126 {
127 return (struct GLX_egl_display *) dpy->DriverData;
128 }
129
130 static struct GLX_egl_context *
131 GLX_egl_context(_EGLContext *ctx)
132 {
133 return (struct GLX_egl_context *) ctx;
134 }
135
136 static struct GLX_egl_surface *
137 GLX_egl_surface(_EGLSurface *surf)
138 {
139 return (struct GLX_egl_surface *) surf;
140 }
141
142 static int
143 GLX_egl_config_index(_EGLConfig *conf)
144 {
145 return ((struct GLX_egl_config *) conf)->index;
146 }
147
148
149 #define MAP_ATTRIB(attr, memb) \
150 { attr, offsetof(__GLcontextModes, memb) }
151
152
153 static const struct {
154 int attr;
155 int offset;
156 } fbconfig_attributes[] = {
157 /* table 3.1 of GLX 1.4 */
158 MAP_ATTRIB(GLX_FBCONFIG_ID, fbconfigID),
159 MAP_ATTRIB(GLX_BUFFER_SIZE, rgbBits),
160 MAP_ATTRIB(GLX_LEVEL, level),
161 MAP_ATTRIB(GLX_DOUBLEBUFFER, doubleBufferMode),
162 MAP_ATTRIB(GLX_STEREO, stereoMode),
163 MAP_ATTRIB(GLX_AUX_BUFFERS, numAuxBuffers),
164 MAP_ATTRIB(GLX_RED_SIZE, redBits),
165 MAP_ATTRIB(GLX_GREEN_SIZE, greenBits),
166 MAP_ATTRIB(GLX_BLUE_SIZE, blueBits),
167 MAP_ATTRIB(GLX_ALPHA_SIZE, alphaBits),
168 MAP_ATTRIB(GLX_DEPTH_SIZE, depthBits),
169 MAP_ATTRIB(GLX_STENCIL_SIZE, stencilBits),
170 MAP_ATTRIB(GLX_ACCUM_RED_SIZE, accumRedBits),
171 MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE, accumGreenBits),
172 MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE, accumBlueBits),
173 MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE, accumAlphaBits),
174 MAP_ATTRIB(GLX_SAMPLE_BUFFERS, sampleBuffers),
175 MAP_ATTRIB(GLX_SAMPLES, samples),
176 MAP_ATTRIB(GLX_RENDER_TYPE, renderType),
177 MAP_ATTRIB(GLX_DRAWABLE_TYPE, drawableType),
178 MAP_ATTRIB(GLX_X_RENDERABLE, xRenderable),
179 MAP_ATTRIB(GLX_X_VISUAL_TYPE, visualType),
180 MAP_ATTRIB(GLX_CONFIG_CAVEAT, visualRating),
181 MAP_ATTRIB(GLX_TRANSPARENT_TYPE, transparentPixel),
182 MAP_ATTRIB(GLX_TRANSPARENT_INDEX_VALUE, transparentIndex),
183 MAP_ATTRIB(GLX_TRANSPARENT_RED_VALUE, transparentRed),
184 MAP_ATTRIB(GLX_TRANSPARENT_GREEN_VALUE, transparentGreen),
185 MAP_ATTRIB(GLX_TRANSPARENT_BLUE_VALUE, transparentBlue),
186 MAP_ATTRIB(GLX_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
187 MAP_ATTRIB(GLX_MAX_PBUFFER_WIDTH, maxPbufferWidth),
188 MAP_ATTRIB(GLX_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
189 MAP_ATTRIB(GLX_MAX_PBUFFER_PIXELS, maxPbufferPixels),
190 MAP_ATTRIB(GLX_VISUAL_ID, visualID),
191 };
192
193
194 static EGLBoolean
195 convert_fbconfig(Display *dpy, GLXFBConfig fbconfig,
196 struct GLX_egl_config *GLX_conf)
197 {
198 __GLcontextModes mode;
199 int err = 0, attr, val, i;
200
201 memset(&mode, 0, sizeof(mode));
202
203 for (i = 0; i < ARRAY_SIZE(fbconfig_attributes); i++) {
204 int offset = fbconfig_attributes[i].offset;
205 attr = fbconfig_attributes[i].attr;
206 err = glXGetFBConfigAttrib(dpy, fbconfig, attr, &val);
207 if (err) {
208 if (err == GLX_BAD_ATTRIBUTE) {
209 err = 0;
210 continue;
211 }
212 break;
213 }
214 *((int *) ((char *) &mode + offset)) = val;
215 }
216 if (err)
217 return EGL_FALSE;
218
219 /* must have rgba bit */
220 if (!(mode.renderType & GLX_RGBA_BIT))
221 return EGL_FALSE;
222
223 /* pixmap and pbuffer surfaces must be single-buffered in EGL */
224 if (mode.doubleBufferMode) {
225 mode.drawableType &= ~(GLX_PIXMAP_BIT | GLX_PBUFFER_BIT);
226 if (!mode.drawableType)
227 return EGL_FALSE;
228 }
229
230 mode.rgbMode = GL_TRUE;
231 mode.haveAccumBuffer = (mode.accumRedBits +
232 mode.accumGreenBits +
233 mode.accumBlueBits +
234 mode.accumAlphaBits > 0);
235 mode.haveDepthBuffer = (mode.depthBits > 0);
236 mode.haveStencilBuffer = (mode.stencilBits > 0);
237
238 GLX_conf->double_buffered = (mode.doubleBufferMode != 0);
239 return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode,
240 EGL_OPENGL_BIT, EGL_OPENGL_BIT);
241 }
242
243
244 static const struct {
245 int attr;
246 int offset;
247 } visual_attributes[] = {
248 /* table 3.7 of GLX 1.4 */
249 /* no GLX_USE_GL */
250 MAP_ATTRIB(GLX_BUFFER_SIZE, rgbBits),
251 MAP_ATTRIB(GLX_LEVEL, level),
252 MAP_ATTRIB(GLX_RGBA, rgbMode),
253 MAP_ATTRIB(GLX_DOUBLEBUFFER, doubleBufferMode),
254 MAP_ATTRIB(GLX_STEREO, stereoMode),
255 MAP_ATTRIB(GLX_AUX_BUFFERS, numAuxBuffers),
256 MAP_ATTRIB(GLX_RED_SIZE, redBits),
257 MAP_ATTRIB(GLX_GREEN_SIZE, greenBits),
258 MAP_ATTRIB(GLX_BLUE_SIZE, blueBits),
259 MAP_ATTRIB(GLX_ALPHA_SIZE, alphaBits),
260 MAP_ATTRIB(GLX_DEPTH_SIZE, depthBits),
261 MAP_ATTRIB(GLX_STENCIL_SIZE, stencilBits),
262 MAP_ATTRIB(GLX_ACCUM_RED_SIZE, accumRedBits),
263 MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE, accumGreenBits),
264 MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE, accumBlueBits),
265 MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE, accumAlphaBits),
266 MAP_ATTRIB(GLX_SAMPLE_BUFFERS, sampleBuffers),
267 MAP_ATTRIB(GLX_SAMPLES, samples),
268 MAP_ATTRIB(GLX_FBCONFIG_ID, fbconfigID),
269 /* GLX_EXT_visual_rating */
270 MAP_ATTRIB(GLX_VISUAL_CAVEAT_EXT, visualRating),
271 };
272
273
274 static int
275 get_visual_type(const XVisualInfo *vis)
276 {
277 int klass;
278
279 #if defined(__cplusplus) || defined(c_plusplus)
280 klass = vis->c_class;
281 #else
282 klass = vis->class;
283 #endif
284
285 switch (klass) {
286 case TrueColor:
287 return GLX_TRUE_COLOR;
288 case DirectColor:
289 return GLX_DIRECT_COLOR;
290 case PseudoColor:
291 return GLX_PSEUDO_COLOR;
292 case StaticColor:
293 return GLX_STATIC_COLOR;
294 case GrayScale:
295 return GLX_GRAY_SCALE;
296 case StaticGray:
297 return GLX_STATIC_GRAY;
298 default:
299 return GLX_NONE;
300 }
301 }
302
303
304 static EGLBoolean
305 convert_visual(Display *dpy, XVisualInfo *vinfo,
306 struct GLX_egl_config *GLX_conf)
307 {
308 __GLcontextModes mode;
309 int err, attr, val, i;
310
311 /* the visual must support OpenGL */
312 err = glXGetConfig(dpy, vinfo, GLX_USE_GL, &val);
313 if (err || !val)
314 return EGL_FALSE;
315
316 memset(&mode, 0, sizeof(mode));
317
318 for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) {
319 int offset = visual_attributes[i].offset;
320 attr = visual_attributes[i].attr;
321 err = glXGetConfig(dpy, vinfo, attr, &val);
322 if (err) {
323 if (err == GLX_BAD_ATTRIBUTE) {
324 err = 0;
325 continue;
326 }
327 break;
328 }
329 *((int *) ((char *) &mode + offset)) = val;
330 }
331 if (err)
332 return EGL_FALSE;
333
334 /* must be RGB mode */
335 if (!mode.rgbMode)
336 return EGL_FALSE;
337
338 mode.visualID = vinfo->visualid;
339 mode.visualType = get_visual_type(vinfo);
340 mode.redMask = vinfo->red_mask;
341 mode.greenMask = vinfo->green_mask;
342 mode.blueMask = vinfo->blue_mask;
343
344 mode.drawableType = GLX_WINDOW_BIT;
345 /* pixmap surfaces must be single-buffered in EGL */
346 if (!mode.doubleBufferMode)
347 mode.drawableType |= GLX_PIXMAP_BIT;
348
349 mode.renderType = GLX_RGBA_BIT;
350 mode.xRenderable = GL_TRUE;
351 mode.haveAccumBuffer = (mode.accumRedBits +
352 mode.accumGreenBits +
353 mode.accumBlueBits +
354 mode.accumAlphaBits > 0);
355 mode.haveDepthBuffer = (mode.depthBits > 0);
356 mode.haveStencilBuffer = (mode.stencilBits > 0);
357
358 GLX_conf->double_buffered = (mode.doubleBufferMode != 0);
359 return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode,
360 EGL_OPENGL_BIT, EGL_OPENGL_BIT);
361 }
362
363
364 static void
365 fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf)
366 {
367 _EGLConfig *conf = &GLX_conf->Base;
368 EGLint surface_type, r, g, b, a;
369
370 surface_type = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
371 if (!GLX_conf->double_buffered && GLX_dpy->single_buffered_quirk) {
372 /* some GLX impls do not like single-buffered window surface */
373 surface_type &= ~EGL_WINDOW_BIT;
374 /* pbuffer bit is usually not set */
375 if (GLX_dpy->have_pbuffer)
376 surface_type |= EGL_PBUFFER_BIT;
377 SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
378 }
379
380 /* no visual attribs unless window bit is set */
381 if (!(surface_type & EGL_WINDOW_BIT)) {
382 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, 0);
383 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_NONE);
384 }
385
386 /* make sure buffer size is set correctly */
387 r = GET_CONFIG_ATTRIB(conf, EGL_RED_SIZE);
388 g = GET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE);
389 b = GET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE);
390 a = GET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE);
391 SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, r + g + b + a);
392 }
393
394
395 static EGLBoolean
396 create_configs(_EGLDisplay *dpy, struct GLX_egl_display *GLX_dpy,
397 EGLint screen)
398 {
399 EGLint num_configs = 0, i;
400 EGLint id = 1;
401
402 if (GLX_dpy->have_fbconfig) {
403 GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs);
404 }
405 else {
406 XVisualInfo vinfo_template;
407 long mask;
408
409 vinfo_template.screen = screen;
410 mask = VisualScreenMask;
411 GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &vinfo_template,
412 &num_configs);
413 }
414
415 if (!num_configs)
416 return EGL_FALSE;
417
418 for (i = 0; i < num_configs; i++) {
419 struct GLX_egl_config *GLX_conf, template;
420 EGLBoolean ok;
421
422 memset(&template, 0, sizeof(template));
423 _eglInitConfig(&template.Base, id);
424 if (GLX_dpy->have_fbconfig)
425 ok = convert_fbconfig(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &template);
426 else
427 ok = convert_visual(GLX_dpy->dpy, &GLX_dpy->visuals[i], &template);
428 if (!ok)
429 continue;
430
431 fix_config(GLX_dpy, &template);
432 if (!_eglValidateConfig(&template.Base, EGL_FALSE)) {
433 _eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i);
434 continue;
435 }
436
437 GLX_conf = CALLOC_STRUCT(GLX_egl_config);
438 if (GLX_conf) {
439 memcpy(GLX_conf, &template, sizeof(template));
440 GLX_conf->index = i;
441
442 _eglAddConfig(dpy, &GLX_conf->Base);
443 id++;
444 }
445 }
446
447 return EGL_TRUE;
448 }
449
450
451 static void
452 check_extensions(struct GLX_egl_display *GLX_dpy, EGLint screen)
453 {
454 GLX_dpy->extensions =
455 glXQueryExtensionsString(GLX_dpy->dpy, screen);
456 if (GLX_dpy->extensions) {
457 /* glXGetProcAddress is assumed */
458
459 if (strstr(GLX_dpy->extensions, "GLX_SGI_make_current_read")) {
460 /* GLX 1.3 entry points are used */
461 GLX_dpy->have_make_current_read = EGL_TRUE;
462 }
463
464 if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) {
465 /* GLX 1.3 entry points are used */
466 GLX_dpy->have_fbconfig = EGL_TRUE;
467 }
468
469 if (strstr(GLX_dpy->extensions, "GLX_SGIX_pbuffer")) {
470 GLX_dpy->glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)
471 glXGetProcAddress((const GLubyte *) "glXCreateGLXPbufferSGIX");
472 GLX_dpy->glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC)
473 glXGetProcAddress((const GLubyte *) "glXDestroyGLXPbufferSGIX");
474
475 if (GLX_dpy->glXCreateGLXPbufferSGIX &&
476 GLX_dpy->glXDestroyGLXPbufferSGIX &&
477 GLX_dpy->have_fbconfig)
478 GLX_dpy->have_pbuffer = EGL_TRUE;
479 }
480 }
481
482 if (GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3) {
483 GLX_dpy->have_1_3 = EGL_TRUE;
484 GLX_dpy->have_make_current_read = EGL_TRUE;
485 GLX_dpy->have_fbconfig = EGL_TRUE;
486 GLX_dpy->have_pbuffer = EGL_TRUE;
487 }
488 }
489
490
491 static void
492 check_quirks(struct GLX_egl_display *GLX_dpy, EGLint screen)
493 {
494 const char *vendor;
495
496 GLX_dpy->single_buffered_quirk = EGL_TRUE;
497 GLX_dpy->glx_window_quirk = EGL_TRUE;
498
499 vendor = glXGetClientString(GLX_dpy->dpy, GLX_VENDOR);
500 if (vendor && strstr(vendor, "NVIDIA")) {
501 vendor = glXQueryServerString(GLX_dpy->dpy, screen, GLX_VENDOR);
502 if (vendor && strstr(vendor, "NVIDIA")) {
503 _eglLog(_EGL_DEBUG, "disable quirks");
504 GLX_dpy->single_buffered_quirk = EGL_FALSE;
505 GLX_dpy->glx_window_quirk = EGL_FALSE;
506 }
507 }
508 }
509
510
511 /**
512 * Called via eglInitialize(), GLX_drv->API.Initialize().
513 */
514 static EGLBoolean
515 GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
516 EGLint *major, EGLint *minor)
517 {
518 struct GLX_egl_display *GLX_dpy;
519
520 GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
521 if (!GLX_dpy)
522 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
523
524 GLX_dpy->dpy = (Display *) disp->NativeDisplay;
525 if (!GLX_dpy->dpy) {
526 GLX_dpy->dpy = XOpenDisplay(NULL);
527 if (!GLX_dpy->dpy) {
528 _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed");
529 free(GLX_dpy);
530 return EGL_FALSE;
531 }
532 }
533
534 if (!glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
535 _eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
536 if (!disp->NativeDisplay)
537 XCloseDisplay(GLX_dpy->dpy);
538 free(GLX_dpy);
539 return EGL_FALSE;
540 }
541
542 check_extensions(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
543 check_quirks(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
544
545 create_configs(disp, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
546 if (!disp->NumConfigs) {
547 _eglLog(_EGL_WARNING, "GLX: failed to create any config");
548 if (!disp->NativeDisplay)
549 XCloseDisplay(GLX_dpy->dpy);
550 free(GLX_dpy);
551 return EGL_FALSE;
552 }
553
554 disp->DriverData = (void *) GLX_dpy;
555 disp->ClientAPIsMask = EGL_OPENGL_BIT;
556
557 /* we're supporting EGL 1.4 */
558 *major = 1;
559 *minor = 4;
560
561 return EGL_TRUE;
562 }
563
564 /**
565 * Called via eglTerminate(), drv->API.Terminate().
566 */
567 static EGLBoolean
568 GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
569 {
570 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
571
572 _eglReleaseDisplayResources(drv, disp);
573 _eglCleanupDisplay(disp);
574
575 if (GLX_dpy->visuals)
576 XFree(GLX_dpy->visuals);
577 if (GLX_dpy->fbconfigs)
578 XFree(GLX_dpy->fbconfigs);
579
580 if (!disp->NativeDisplay)
581 XCloseDisplay(GLX_dpy->dpy);
582 free(GLX_dpy);
583
584 disp->DriverData = NULL;
585
586 return EGL_TRUE;
587 }
588
589
590 /**
591 * Called via eglCreateContext(), drv->API.CreateContext().
592 */
593 static _EGLContext *
594 GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
595 _EGLContext *share_list, const EGLint *attrib_list)
596 {
597 struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
598 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
599 struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list);
600
601 if (!GLX_ctx) {
602 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
603 return NULL;
604 }
605
606 if (!_eglInitContext(drv, &GLX_ctx->Base, conf, attrib_list)) {
607 free(GLX_ctx);
608 return NULL;
609 }
610
611 if (GLX_dpy->have_fbconfig)
612 GLX_ctx->context =
613 glXCreateNewContext(GLX_dpy->dpy,
614 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
615 GLX_RGBA_TYPE,
616 GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
617 GL_TRUE);
618 else
619 GLX_ctx->context =
620 glXCreateContext(GLX_dpy->dpy,
621 &GLX_dpy->visuals[GLX_egl_config_index(conf)],
622 GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
623 GL_TRUE);
624 if (!GLX_ctx->context) {
625 free(GLX_ctx);
626 return NULL;
627 }
628
629 return &GLX_ctx->Base;
630 }
631
632
633 /**
634 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
635 */
636 static EGLBoolean
637 GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
638 _EGLSurface *rsurf, _EGLContext *ctx)
639 {
640 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
641 struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
642 struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
643 struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
644 GLXDrawable ddraw, rdraw;
645 GLXContext cctx;
646
647 if (!_eglMakeCurrent(drv, disp, dsurf, rsurf, ctx))
648 return EGL_FALSE;
649
650 ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None;
651 rdraw = (GLX_rsurf) ? GLX_rsurf->glx_drawable : None;
652 cctx = (GLX_ctx) ? GLX_ctx->context : NULL;
653
654 if (GLX_dpy->have_make_current_read)
655 return glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx);
656 else if (ddraw == rdraw)
657 return glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx);
658
659 return EGL_FALSE;
660 }
661
662 /** Get size of given window */
663 static Status
664 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
665 {
666 Window root;
667 Status stat;
668 int xpos, ypos;
669 unsigned int w, h, bw, depth;
670 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
671 *width = w;
672 *height = h;
673 return stat;
674 }
675
676 /**
677 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
678 */
679 static _EGLSurface *
680 GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
681 NativeWindowType window, const EGLint *attrib_list)
682 {
683 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
684 struct GLX_egl_surface *GLX_surf;
685 uint width, height;
686
687 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
688 if (!GLX_surf) {
689 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
690 return NULL;
691 }
692
693 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_WINDOW_BIT,
694 conf, attrib_list)) {
695 free(GLX_surf);
696 return NULL;
697 }
698
699 GLX_surf->drawable = window;
700
701 if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk)
702 GLX_surf->glx_drawable =
703 glXCreateWindow(GLX_dpy->dpy,
704 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
705 GLX_surf->drawable, NULL);
706 else
707 GLX_surf->glx_drawable = GLX_surf->drawable;
708
709 if (!GLX_surf->glx_drawable) {
710 free(GLX_surf);
711 return NULL;
712 }
713
714 get_drawable_size(GLX_dpy->dpy, window, &width, &height);
715 GLX_surf->Base.Width = width;
716 GLX_surf->Base.Height = height;
717
718 return &GLX_surf->Base;
719 }
720
721 static _EGLSurface *
722 GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
723 NativePixmapType pixmap, const EGLint *attrib_list)
724 {
725 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
726 struct GLX_egl_surface *GLX_surf;
727 uint width, height;
728
729 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
730 if (!GLX_surf) {
731 _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
732 return NULL;
733 }
734
735 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PIXMAP_BIT,
736 conf, attrib_list)) {
737 free(GLX_surf);
738 return NULL;
739 }
740
741 GLX_surf->drawable = pixmap;
742
743 if (GLX_dpy->have_1_3) {
744 GLX_surf->glx_drawable =
745 glXCreatePixmap(GLX_dpy->dpy,
746 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
747 GLX_surf->drawable, NULL);
748 }
749 else if (GLX_dpy->have_fbconfig) {
750 GLXFBConfig fbconfig = GLX_dpy->fbconfigs[GLX_egl_config_index(conf)];
751 XVisualInfo *vinfo = glXGetVisualFromFBConfig(GLX_dpy->dpy, fbconfig);
752 if (vinfo) {
753 GLX_surf->glx_drawable =
754 glXCreateGLXPixmap(GLX_dpy->dpy, vinfo, GLX_surf->drawable);
755 XFree(vinfo);
756 }
757 }
758 else {
759 GLX_surf->glx_drawable =
760 glXCreateGLXPixmap(GLX_dpy->dpy,
761 &GLX_dpy->visuals[GLX_egl_config_index(conf)],
762 GLX_surf->drawable);
763 }
764
765 if (!GLX_surf->glx_drawable) {
766 free(GLX_surf);
767 return NULL;
768 }
769
770 get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height);
771 GLX_surf->Base.Width = width;
772 GLX_surf->Base.Height = height;
773
774 return &GLX_surf->Base;
775 }
776
777 static _EGLSurface *
778 GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
779 _EGLConfig *conf, const EGLint *attrib_list)
780 {
781 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
782 struct GLX_egl_surface *GLX_surf;
783 int attribs[5];
784 int i;
785
786 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
787 if (!GLX_surf) {
788 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
789 return NULL;
790 }
791
792 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PBUFFER_BIT,
793 conf, attrib_list)) {
794 free(GLX_surf);
795 return NULL;
796 }
797
798 i = 0;
799 attribs[i] = None;
800
801 GLX_surf->drawable = None;
802
803 if (GLX_dpy->have_1_3) {
804 /* put geometry in attribs */
805 if (GLX_surf->Base.Width) {
806 attribs[i++] = GLX_PBUFFER_WIDTH;
807 attribs[i++] = GLX_surf->Base.Width;
808 }
809 if (GLX_surf->Base.Height) {
810 attribs[i++] = GLX_PBUFFER_HEIGHT;
811 attribs[i++] = GLX_surf->Base.Height;
812 }
813 attribs[i] = None;
814
815 GLX_surf->glx_drawable =
816 glXCreatePbuffer(GLX_dpy->dpy,
817 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
818 attribs);
819 }
820 else if (GLX_dpy->have_pbuffer) {
821 GLX_surf->glx_drawable = GLX_dpy->glXCreateGLXPbufferSGIX(
822 GLX_dpy->dpy,
823 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
824 GLX_surf->Base.Width,
825 GLX_surf->Base.Height,
826 attribs);
827 }
828
829 if (!GLX_surf->glx_drawable) {
830 free(GLX_surf);
831 return NULL;
832 }
833
834 return &GLX_surf->Base;
835 }
836
837 static EGLBoolean
838 GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
839 {
840 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
841 if (!_eglIsSurfaceBound(surf)) {
842 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
843
844 if (GLX_dpy->have_1_3) {
845 switch (surf->Type) {
846 case EGL_WINDOW_BIT:
847 if (!GLX_dpy->glx_window_quirk)
848 glXDestroyWindow(GLX_dpy->dpy, GLX_surf->glx_drawable);
849 break;
850 case EGL_PBUFFER_BIT:
851 glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->glx_drawable);
852 break;
853 case EGL_PIXMAP_BIT:
854 glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable);
855 break;
856 default:
857 break;
858 }
859 }
860 else {
861 switch (surf->Type) {
862 case EGL_PBUFFER_BIT:
863 GLX_dpy->glXDestroyGLXPbufferSGIX(GLX_dpy->dpy,
864 GLX_surf->glx_drawable);
865 break;
866 case EGL_PIXMAP_BIT:
867 glXDestroyGLXPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable);
868 break;
869 default:
870 break;
871 }
872 }
873 free(surf);
874 }
875
876 return EGL_TRUE;
877 }
878
879
880 static EGLBoolean
881 GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
882 {
883 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
884 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
885
886 glXSwapBuffers(GLX_dpy->dpy, GLX_surf->glx_drawable);
887
888 return EGL_TRUE;
889 }
890
891 /*
892 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
893 */
894 static _EGLProc
895 GLX_eglGetProcAddress(_EGLDriver *drv, const char *procname)
896 {
897 return (_EGLProc) glXGetProcAddress((const GLubyte *) procname);
898 }
899
900 static EGLBoolean
901 GLX_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
902 {
903 glXWaitGL();
904 return EGL_TRUE;
905 }
906
907 static EGLBoolean
908 GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
909 {
910 if (engine != EGL_CORE_NATIVE_ENGINE)
911 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
912 glXWaitX();
913 return EGL_TRUE;
914 }
915
916 static void
917 GLX_Unload(_EGLDriver *drv)
918 {
919 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
920 free(GLX_drv);
921 }
922
923
924 /**
925 * This is the main entrypoint into the driver, called by libEGL.
926 * Create a new _EGLDriver object and init its dispatch table.
927 */
928 _EGLDriver *
929 _eglMain(const char *args)
930 {
931 struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
932
933 if (!GLX_drv)
934 return NULL;
935
936 _eglInitDriverFallbacks(&GLX_drv->Base);
937 GLX_drv->Base.API.Initialize = GLX_eglInitialize;
938 GLX_drv->Base.API.Terminate = GLX_eglTerminate;
939 GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
940 GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
941 GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
942 GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
943 GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
944 GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
945 GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
946 GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
947 GLX_drv->Base.API.WaitClient = GLX_eglWaitClient;
948 GLX_drv->Base.API.WaitNative = GLX_eglWaitNative;
949
950 GLX_drv->Base.Name = "GLX";
951 GLX_drv->Base.Unload = GLX_Unload;
952
953 return &GLX_drv->Base;
954 }