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