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