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