Merge branch 'mesa_7_5_branch' into mesa_7_6_branch
[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 /*
37 * TODO:
38 *
39 * test eglBind/ReleaseTexImage
40 */
41
42
43 #include <assert.h>
44 #include <stdio.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include "dlfcn.h"
49 #include <X11/Xlib.h>
50 #include <GL/gl.h>
51 #include "glxclient.h"
52
53 #include "eglconfig.h"
54 #include "eglcontext.h"
55 #include "egldisplay.h"
56 #include "egldriver.h"
57 #include "eglglobals.h"
58 #include "egllog.h"
59 #include "eglsurface.h"
60
61 #include <GL/gl.h>
62
63 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
64
65 static const EGLint all_apis = (EGL_OPENGL_ES_BIT
66 | EGL_OPENGL_ES2_BIT
67 | EGL_OPENVG_BIT
68 /* | EGL_OPENGL_BIT */); /* can't do */
69
70 struct visual_attribs
71 {
72 /* X visual attribs */
73 int id;
74 int klass;
75 int depth;
76 int redMask, greenMask, blueMask;
77 int colormapSize;
78 int bitsPerRGB;
79
80 /* GL visual attribs */
81 int supportsGL;
82 int transparentType;
83 int transparentRedValue;
84 int transparentGreenValue;
85 int transparentBlueValue;
86 int transparentAlphaValue;
87 int transparentIndexValue;
88 int bufferSize;
89 int level;
90 int render_type;
91 int doubleBuffer;
92 int stereo;
93 int auxBuffers;
94 int redSize, greenSize, blueSize, alphaSize;
95 int depthSize;
96 int stencilSize;
97 int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
98 int numSamples, numMultisample;
99 int visualCaveat;
100 };
101
102 /** subclass of _EGLDriver */
103 struct GLX_egl_driver
104 {
105 _EGLDriver Base; /**< base class */
106 };
107
108
109 /** driver data of _EGLDisplay */
110 struct GLX_egl_display
111 {
112 Display *dpy;
113 XVisualInfo *visuals;
114 GLXFBConfig *fbconfigs;
115
116 int glx_maj, glx_min;
117 };
118
119
120 /** subclass of _EGLContext */
121 struct GLX_egl_context
122 {
123 _EGLContext Base; /**< base class */
124
125 GLXContext context;
126 };
127
128
129 /** subclass of _EGLSurface */
130 struct GLX_egl_surface
131 {
132 _EGLSurface Base; /**< base class */
133
134 GLXDrawable drawable;
135 };
136
137
138 /** subclass of _EGLConfig */
139 struct GLX_egl_config
140 {
141 _EGLConfig Base; /**< base class */
142 int index;
143 };
144
145 /** cast wrapper */
146 static struct GLX_egl_driver *
147 GLX_egl_driver(_EGLDriver *drv)
148 {
149 return (struct GLX_egl_driver *) drv;
150 }
151
152 static struct GLX_egl_display *
153 GLX_egl_display(_EGLDisplay *dpy)
154 {
155 return (struct GLX_egl_display *) dpy->DriverData;
156 }
157
158 static struct GLX_egl_context *
159 GLX_egl_context(_EGLContext *ctx)
160 {
161 return (struct GLX_egl_context *) ctx;
162 }
163
164 static struct GLX_egl_surface *
165 GLX_egl_surface(_EGLSurface *surf)
166 {
167 return (struct GLX_egl_surface *) surf;
168 }
169
170 static int
171 GLX_egl_config_index(_EGLConfig *conf)
172 {
173 return ((struct GLX_egl_config *) conf)->index;
174 }
175
176 static GLboolean
177 get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
178 struct visual_attribs *attribs)
179 {
180 const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
181 int rgba;
182
183 memset(attribs, 0, sizeof(struct visual_attribs));
184
185 attribs->id = vInfo->visualid;
186 #if defined(__cplusplus) || defined(c_plusplus)
187 attribs->klass = vInfo->c_class;
188 #else
189 attribs->klass = vInfo->class;
190 #endif
191 attribs->depth = vInfo->depth;
192 attribs->redMask = vInfo->red_mask;
193 attribs->greenMask = vInfo->green_mask;
194 attribs->blueMask = vInfo->blue_mask;
195 attribs->colormapSize = vInfo->colormap_size;
196 attribs->bitsPerRGB = vInfo->bits_per_rgb;
197
198 if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
199 !attribs->supportsGL)
200 return GL_FALSE;
201 glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
202 glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
203 glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
204 if (!rgba)
205 return GL_FALSE;
206 attribs->render_type = GLX_RGBA_BIT;
207
208 glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
209 if (!attribs->doubleBuffer)
210 return GL_FALSE;
211
212 glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
213 glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
214 glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
215 glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
216 glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
217 glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
218 glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
219 glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
220 glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
221 glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
222 glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
223 glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
224
225 /* get transparent pixel stuff */
226 glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
227 if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
228 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
229 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
230 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
231 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
232 }
233 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
234 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
235 }
236
237 /* multisample attribs */
238 #ifdef GLX_ARB_multisample
239 if (ext && strstr(ext, "GLX_ARB_multisample")) {
240 glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
241 glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
242 }
243 #endif
244 else {
245 attribs->numSamples = 0;
246 attribs->numMultisample = 0;
247 }
248
249 #if defined(GLX_EXT_visual_rating)
250 if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
251 glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
252 }
253 else {
254 attribs->visualCaveat = GLX_NONE_EXT;
255 }
256 #else
257 attribs->visualCaveat = 0;
258 #endif
259
260 return GL_TRUE;
261 }
262
263 #ifdef GLX_VERSION_1_3
264
265 static int
266 glx_token_to_visual_class(int visual_type)
267 {
268 switch (visual_type) {
269 case GLX_TRUE_COLOR:
270 return TrueColor;
271 case GLX_DIRECT_COLOR:
272 return DirectColor;
273 case GLX_PSEUDO_COLOR:
274 return PseudoColor;
275 case GLX_STATIC_COLOR:
276 return StaticColor;
277 case GLX_GRAY_SCALE:
278 return GrayScale;
279 case GLX_STATIC_GRAY:
280 return StaticGray;
281 case GLX_NONE:
282 default:
283 return None;
284 }
285 }
286
287 static int
288 get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
289 struct visual_attribs *attribs)
290 {
291 int visual_type;
292 int fbconfig_id;
293
294 memset(attribs, 0, sizeof(struct visual_attribs));
295
296 glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &fbconfig_id);
297
298 glXGetFBConfigAttrib(dpy, fbconfig, GLX_VISUAL_ID, &attribs->id);
299
300 #if 0
301 attribs->depth = vInfo->depth;
302 attribs->redMask = vInfo->red_mask;
303 attribs->greenMask = vInfo->green_mask;
304 attribs->blueMask = vInfo->blue_mask;
305 attribs->colormapSize = vInfo->colormap_size;
306 attribs->bitsPerRGB = vInfo->bits_per_rgb;
307 #endif
308
309 glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
310 attribs->klass = glx_token_to_visual_class(visual_type);
311
312 glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
313 glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
314 glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
315 if (!(attribs->render_type & GLX_RGBA_BIT))
316 return 0;
317
318 glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
319 if (!attribs->doubleBuffer)
320 return 0;
321
322 glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
323 glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
324
325 glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
326 glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
327 glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
328 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
329 glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
330 glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
331
332 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
333 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
334 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
335 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
336
337 /* get transparent pixel stuff */
338 glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
339 if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
340 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
341 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
342 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
343 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
344 }
345 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
346 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
347 }
348
349 glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
350 glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
351
352 glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
353
354 if (attribs->id == 0) {
355 attribs->id = fbconfig_id;
356 return EGL_PBUFFER_BIT | EGL_PIXMAP_BIT;
357 }
358
359 return EGL_WINDOW_BIT;
360 }
361
362 #endif
363
364 static EGLBoolean
365 create_configs(_EGLDisplay *disp, struct GLX_egl_display *GLX_dpy)
366 {
367 XVisualInfo theTemplate;
368 int numVisuals;
369 long mask;
370 int i;
371 struct visual_attribs attribs;
372
373 GLX_dpy->fbconfigs = NULL;
374
375 #ifdef GLX_VERSION_1_3
376 /* get list of all fbconfigs on this screen */
377 GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, DefaultScreen(GLX_dpy->dpy), &numVisuals);
378
379 if (numVisuals == 0) {
380 GLX_dpy->fbconfigs = NULL;
381 goto xvisual;
382 }
383
384 for (i = 0; i < numVisuals; i++) {
385 struct GLX_egl_config *config;
386 int bit;
387
388 bit = get_fbconfig_attribs(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &attribs);
389 if (!bit)
390 continue;
391
392 config = CALLOC_STRUCT(GLX_egl_config);
393
394 config->index = i;
395 _eglInitConfig(&config->Base, (i+1));
396 SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
397 SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
398 SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
399 SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
400 SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
401 SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
402 SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
403 SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
404 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
405 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
406 SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
407 SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
408 SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, bit);
409
410 /* XXX possibly other things to init... */
411
412 _eglAddConfig(disp, &config->Base);
413 }
414
415 goto end;
416 #endif
417
418 xvisual:
419 /* get list of all visuals on this screen */
420 theTemplate.screen = DefaultScreen(GLX_dpy->dpy);
421 mask = VisualScreenMask;
422 GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &theTemplate, &numVisuals);
423
424 for (i = 0; i < numVisuals; i++) {
425 struct GLX_egl_config *config;
426
427 if (!get_visual_attribs(GLX_dpy->dpy, &GLX_dpy->visuals[i], &attribs))
428 continue;
429
430 config = CALLOC_STRUCT(GLX_egl_config);
431
432 config->index = i;
433 _eglInitConfig(&config->Base, (i+1));
434 SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
435 SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
436 SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
437 SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
438 SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
439 SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
440 SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
441 SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
442 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
443 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
444 SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
445 SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
446 SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE,
447 (EGL_WINDOW_BIT /*| EGL_PBUFFER_BIT | EGL_PIXMAP_BIT*/));
448
449 /* XXX possibly other things to init... */
450
451 _eglAddConfig(disp, &config->Base);
452 }
453
454 end:
455 return EGL_TRUE;
456 }
457
458 /**
459 * Called via eglInitialize(), GLX_drv->API.Initialize().
460 */
461 static EGLBoolean
462 GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
463 EGLint *major, EGLint *minor)
464 {
465 struct GLX_egl_display *GLX_dpy;
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->NativeDisplay;
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 disp->DriverData = (void *) GLX_dpy;
482 disp->ClientAPIsMask = all_apis;
483
484 glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min);
485
486 /* we're supporting EGL 1.4 */
487 *major = 1;
488 *minor = 4;
489
490 create_configs(disp, GLX_dpy);
491
492 return EGL_TRUE;
493 }
494
495 /**
496 * Called via eglTerminate(), drv->API.Terminate().
497 */
498 static EGLBoolean
499 GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
500 {
501 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
502
503 _eglReleaseDisplayResources(drv, disp);
504 _eglCleanupDisplay(disp);
505
506 if (GLX_dpy->visuals)
507 XFree(GLX_dpy->visuals);
508 if (GLX_dpy->fbconfigs)
509 XFree(GLX_dpy->fbconfigs);
510
511 if (!disp->NativeDisplay)
512 XCloseDisplay(GLX_dpy->dpy);
513 free(GLX_dpy);
514
515 disp->DriverData = NULL;
516
517 return EGL_TRUE;
518 }
519
520
521 /**
522 * Called via eglCreateContext(), drv->API.CreateContext().
523 */
524 static _EGLContext *
525 GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
526 _EGLContext *share_list, const EGLint *attrib_list)
527 {
528 struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
529 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
530 struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list);
531
532 if (!GLX_ctx) {
533 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
534 return NULL;
535 }
536
537 if (!_eglInitContext(drv, &GLX_ctx->Base, conf, attrib_list)) {
538 free(GLX_ctx);
539 return NULL;
540 }
541
542 #ifdef GLX_VERSION_1_3
543 if (GLX_dpy->fbconfigs)
544 GLX_ctx->context =
545 glXCreateNewContext(GLX_dpy->dpy,
546 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
547 GLX_RGBA_TYPE,
548 GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
549 GL_TRUE);
550 else
551 #endif
552 GLX_ctx->context =
553 glXCreateContext(GLX_dpy->dpy,
554 &GLX_dpy->visuals[GLX_egl_config_index(conf)],
555 GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
556 GL_TRUE);
557 if (!GLX_ctx->context) {
558 free(GLX_ctx);
559 return NULL;
560 }
561
562 #if 1
563 /* (maybe?) need to have a direct rendering context */
564 if (!glXIsDirect(GLX_dpy->dpy, GLX_ctx->context)) {
565 glXDestroyContext(GLX_dpy->dpy, GLX_ctx->context);
566 free(GLX_ctx);
567 return NULL;
568 }
569 #endif
570
571 return &GLX_ctx->Base;
572 }
573
574
575 /**
576 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
577 */
578 static EGLBoolean
579 GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
580 _EGLSurface *rsurf, _EGLContext *ctx)
581 {
582 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
583 struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
584 struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
585 struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
586 GLXDrawable ddraw, rdraw;
587 GLXContext cctx;
588
589 if (!_eglMakeCurrent(drv, disp, dsurf, rsurf, ctx))
590 return EGL_FALSE;
591
592 ddraw = (GLX_dsurf) ? GLX_dsurf->drawable : None;
593 rdraw = (GLX_rsurf) ? GLX_rsurf->drawable : None;
594 cctx = (GLX_ctx) ? GLX_ctx->context : NULL;
595
596 #ifdef GLX_VERSION_1_3
597 if (glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx))
598 return EGL_TRUE;
599 #endif
600
601 if (ddraw == rdraw && glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx))
602 return EGL_TRUE;
603
604 return EGL_FALSE;
605 }
606
607 /** Get size of given window */
608 static Status
609 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
610 {
611 Window root;
612 Status stat;
613 int xpos, ypos;
614 unsigned int w, h, bw, depth;
615 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
616 *width = w;
617 *height = h;
618 return stat;
619 }
620
621 /**
622 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
623 */
624 static _EGLSurface *
625 GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
626 NativeWindowType window, const EGLint *attrib_list)
627 {
628 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
629 struct GLX_egl_surface *GLX_surf;
630 uint width, height;
631
632 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
633 if (!GLX_surf) {
634 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
635 return NULL;
636 }
637
638 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_WINDOW_BIT,
639 conf, attrib_list)) {
640 free(GLX_surf);
641 return NULL;
642 }
643
644 GLX_surf->drawable = window;
645 get_drawable_size(GLX_dpy->dpy, window, &width, &height);
646 GLX_surf->Base.Width = width;
647 GLX_surf->Base.Height = height;
648
649 return &GLX_surf->Base;
650 }
651
652 #ifdef GLX_VERSION_1_3
653 static _EGLSurface *
654 GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
655 NativePixmapType pixmap, const EGLint *attrib_list)
656 {
657 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
658 struct GLX_egl_surface *GLX_surf;
659 int i;
660
661 /* GLX must >= 1.3 */
662 if (!(GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3))
663 return NULL;
664
665 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
666 if (!GLX_surf) {
667 _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
668 return NULL;
669 }
670
671 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PIXMAP_BIT,
672 conf, attrib_list)) {
673 free(GLX_surf);
674 return NULL;
675 }
676
677 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
678 switch (attrib_list[i]) {
679 /* no attribs at this time */
680 default:
681 _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
682 free(GLX_surf);
683 return NULL;
684 }
685 }
686
687 GLX_surf->drawable =
688 glXCreatePixmap(GLX_dpy->dpy,
689 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
690 pixmap, NULL);
691 if (!GLX_surf->drawable) {
692 free(GLX_surf);
693 return NULL;
694 }
695
696 return &GLX_surf->Base;
697 }
698
699 static _EGLSurface *
700 GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
701 _EGLConfig *conf, const EGLint *attrib_list)
702 {
703 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
704 struct GLX_egl_surface *GLX_surf;
705 int attribs[5];
706 int i = 0, j = 0;
707
708 /* GLX must >= 1.3 */
709 if (!(GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3))
710 return NULL;
711
712 GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
713 if (!GLX_surf) {
714 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
715 return NULL;
716 }
717
718 if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PBUFFER_BIT,
719 conf, attrib_list)) {
720 free(GLX_surf);
721 return NULL;
722 }
723
724 while(attrib_list[i] != EGL_NONE) {
725 switch (attrib_list[i]) {
726 case EGL_WIDTH:
727 attribs[j++] = GLX_PBUFFER_WIDTH;
728 attribs[j++] = attrib_list[i+1];
729 break;
730 case EGL_HEIGHT:
731 attribs[j++] = GLX_PBUFFER_HEIGHT;
732 attribs[j++] = attrib_list[i+1];
733 break;
734 }
735 i++;
736 }
737 attribs[j++] = 0;
738
739 GLX_surf->drawable =
740 glXCreatePbuffer(GLX_dpy->dpy,
741 GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
742 attribs);
743 if (!GLX_surf->drawable) {
744 free(GLX_surf);
745 return NULL;
746 }
747
748 return &GLX_surf->Base;
749 }
750 #endif
751
752 static EGLBoolean
753 GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
754 {
755 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
756 if (!_eglIsSurfaceBound(surf)) {
757 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
758 switch (surf->Type) {
759 case EGL_PBUFFER_BIT:
760 glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->drawable);
761 break;
762 case EGL_PIXMAP_BIT:
763 glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->drawable);
764 break;
765 default:
766 break;
767 }
768 free(surf);
769 }
770
771 return EGL_TRUE;
772 }
773
774
775 static EGLBoolean
776 GLX_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
777 EGLint buffer)
778 {
779 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
780 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
781
782 /* buffer ?? */
783 glXBindTexImageEXT(GLX_dpy->dpy, GLX_surf->drawable,
784 GLX_FRONT_LEFT_EXT, NULL);
785
786 return EGL_TRUE;
787 }
788
789
790 static EGLBoolean
791 GLX_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
792 EGLint buffer)
793 {
794 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
795 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
796
797 /* buffer ?? */
798 glXReleaseTexImageEXT(GLX_dpy->dpy, GLX_surf->drawable,
799 GLX_FRONT_LEFT_EXT);
800
801 return EGL_TRUE;
802 }
803
804
805 static EGLBoolean
806 GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
807 {
808 struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
809 struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
810
811 _eglLog(_EGL_DEBUG, "GLX: EGL SwapBuffers 0x%x",draw);
812
813 glXSwapBuffers(GLX_dpy->dpy, GLX_surf->drawable);
814
815 return EGL_TRUE;
816 }
817
818 /*
819 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
820 */
821 static _EGLProc
822 GLX_eglGetProcAddress(const char *procname)
823 {
824 /* This is a bit of a hack to get at the gallium/Mesa state tracker
825 * function st_get_proc_address(). This will probably change at
826 * some point.
827 */
828 _EGLProc (*get_proc_addr)(const char *procname);
829 _EGLProc proc_addr;
830 get_proc_addr = dlsym(NULL, "st_get_proc_address");
831 if (get_proc_addr)
832 return get_proc_addr(procname);
833
834 proc_addr = glXGetProcAddress((const GLubyte *)procname);
835 if (proc_addr)
836 return proc_addr;
837
838 return (_EGLProc)dlsym(NULL, procname);
839 }
840
841
842 static void
843 GLX_Unload(_EGLDriver *drv)
844 {
845 struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
846 free(GLX_drv);
847 }
848
849
850 /**
851 * This is the main entrypoint into the driver, called by libEGL.
852 * Create a new _EGLDriver object and init its dispatch table.
853 */
854 _EGLDriver *
855 _eglMain(const char *args)
856 {
857 struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
858
859 if (!GLX_drv)
860 return NULL;
861
862 _eglInitDriverFallbacks(&GLX_drv->Base);
863 GLX_drv->Base.API.Initialize = GLX_eglInitialize;
864 GLX_drv->Base.API.Terminate = GLX_eglTerminate;
865 GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
866 GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
867 GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
868 #ifdef GLX_VERSION_1_3
869 GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
870 GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
871 #endif
872 GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
873 GLX_drv->Base.API.BindTexImage = GLX_eglBindTexImage;
874 GLX_drv->Base.API.ReleaseTexImage = GLX_eglReleaseTexImage;
875 GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
876 GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
877
878 GLX_drv->Base.Name = "GLX";
879 GLX_drv->Base.Unload = GLX_Unload;
880
881 return &GLX_drv->Base;
882 }