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