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