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