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