1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Code to interface a DRI driver to libEGL.
31 * Note that unlike previous DRI/EGL interfaces, this one is meant to
32 * be used _with_ X. Applications will use eglCreateWindowSurface()
33 * to render into X-created windows.
35 * This is an EGL driver that, in turn, loads a regular DRI driver.
36 * There are some dependencies on code in libGL, but those could be
37 * removed with some effort.
48 #include "glapi/glapi.h" /* for glapi functions */
50 #include "eglconfig.h"
51 #include "eglcontext.h"
52 #include "egldisplay.h"
53 #include "egldriver.h"
54 #include "eglglobals.h"
56 #include "eglsurface.h"
58 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
60 /** subclass of _EGLDriver */
61 struct xdri_egl_driver
63 _EGLDriver Base; /**< base class */
67 /** driver data of _EGLDisplay */
68 struct xdri_egl_display
71 __GLXdisplayPrivate *dpyPriv;
72 __GLXDRIdisplay *driDisplay;
74 __GLXscreenConfigs *psc;
79 /** subclass of _EGLContext */
80 struct xdri_egl_context
82 _EGLContext Base; /**< base class */
84 /* just enough info to create dri contexts */
87 __GLXDRIcontext *driContext;
91 /** subclass of _EGLSurface */
92 struct xdri_egl_surface
94 _EGLSurface Base; /**< base class */
97 __GLXDRIdrawable *driDrawable;
101 /** subclass of _EGLConfig */
102 struct xdri_egl_config
104 _EGLConfig Base; /**< base class */
106 const __GLcontextModes *mode; /**< corresponding GLX mode */
112 static INLINE struct xdri_egl_driver *
113 xdri_egl_driver(_EGLDriver *drv)
115 return (struct xdri_egl_driver *) drv;
119 static INLINE struct xdri_egl_display *
120 lookup_display(_EGLDisplay *dpy)
122 return (struct xdri_egl_display *) dpy->DriverData;
126 /** Map EGLSurface handle to xdri_egl_surface object */
127 static INLINE struct xdri_egl_surface *
128 lookup_surface(_EGLSurface *surface)
130 return (struct xdri_egl_surface *) surface;
134 /** Map EGLContext handle to xdri_egl_context object */
135 static INLINE struct xdri_egl_context *
136 lookup_context(_EGLContext *context)
138 return (struct xdri_egl_context *) context;
142 /** Map EGLConfig handle to xdri_egl_config object */
143 static INLINE struct xdri_egl_config *
144 lookup_config(_EGLConfig *conf)
146 return (struct xdri_egl_config *) conf;
150 /** Get size of given window */
152 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
157 unsigned int w, h, bw, depth;
158 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
166 * Produce a set of EGL configs.
169 create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id)
171 static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
177 for (; m; m = m->next) {
178 /* add double buffered visual */
179 if (m->doubleBufferMode) {
180 struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config);
182 _eglInitConfig(&config->Base, id++);
184 SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, m->rgbBits);
185 SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, m->redBits);
186 SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, m->greenBits);
187 SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, m->blueBits);
188 SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, m->alphaBits);
189 SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, m->depthBits);
190 SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, m->stencilBits);
191 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, m->samples);
192 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, m->sampleBuffers);
193 SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, m->visualID);
194 SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType);
195 SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
196 SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
197 SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
199 /* XXX possibly other things to init... */
201 /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */
204 _eglAddConfig(disp, &config->Base);
213 * Called via eglInitialize(), xdri_dpy->API.Initialize().
216 xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
217 EGLint *minor, EGLint *major)
219 struct xdri_egl_display *xdri_dpy;
220 __GLXdisplayPrivate *dpyPriv;
221 __GLXDRIdisplay *driDisplay;
222 __GLXscreenConfigs *psc;
226 xdri_dpy = CALLOC_STRUCT(xdri_egl_display);
228 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
230 xdri_dpy->dpy = (Display *) dpy->NativeDisplay;
231 if (!xdri_dpy->dpy) {
232 xdri_dpy->dpy = XOpenDisplay(NULL);
233 if (!xdri_dpy->dpy) {
235 return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
239 dpyPriv = __glXInitialize(xdri_dpy->dpy);
241 _eglLog(_EGL_WARNING, "failed to create GLX display");
243 return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
246 driDisplay = __driCreateDisplay(dpyPriv, NULL);
248 _eglLog(_EGL_WARNING, "failed to create DRI display");
250 return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
253 scr = DefaultScreen(xdri_dpy->dpy);
254 psc = &dpyPriv->screenConfigs[scr];
256 xdri_dpy->dpyPriv = dpyPriv;
257 xdri_dpy->driDisplay = driDisplay;
261 psc->driScreen = driDisplay->createScreen(psc, scr, dpyPriv);
262 if (!psc->driScreen) {
263 _eglLog(_EGL_WARNING, "failed to create DRI screen #%d", scr);
265 return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
268 /* add visuals and fbconfigs */
269 first_id = create_configs(dpy, psc->visuals, first_id);
270 create_configs(dpy, psc->configs, first_id);
272 dpy->DriverData = xdri_dpy;
273 dpy->ClientAPIsMask = (EGL_OPENGL_BIT |
278 /* we're supporting EGL 1.4 */
287 * Called via eglTerminate(), drv->API.Terminate().
290 xdri_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
292 struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
293 __GLXscreenConfigs *psc;
295 _eglReleaseDisplayResources(drv, dpy);
296 _eglCleanupDisplay(dpy);
299 if (psc->driver_configs) {
301 for (i = 0; psc->driver_configs[i]; i++)
302 free((__DRIconfig *) psc->driver_configs[i]);
303 free(psc->driver_configs);
304 psc->driver_configs = NULL;
306 if (psc->driScreen) {
307 psc->driScreen->destroyScreen(psc);
308 free(psc->driScreen);
309 psc->driScreen = NULL;
312 xdri_dpy->driDisplay->destroyDisplay(xdri_dpy->driDisplay);
313 __glXRelease(xdri_dpy->dpyPriv);
316 dpy->DriverData = NULL;
323 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
326 xdri_eglGetProcAddress(const char *procname)
328 /* the symbol is defined in libGL.so */
329 return (_EGLProc) _glapi_get_proc_address(procname);
334 * Called via eglCreateContext(), drv->API.CreateContext().
337 xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
338 _EGLContext *share_list, const EGLint *attrib_list)
340 struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
341 struct xdri_egl_config *xdri_config = lookup_config(conf);
342 struct xdri_egl_context *shared = lookup_context(share_list);
343 __GLXscreenConfigs *psc = xdri_dpy->psc;
344 int renderType = GLX_RGBA_BIT;
345 struct xdri_egl_context *xdri_ctx;
347 xdri_ctx = CALLOC_STRUCT(xdri_egl_context);
349 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
353 xdri_ctx->dummy_gc = CALLOC_STRUCT(__GLXcontextRec);
354 if (!xdri_ctx->dummy_gc) {
355 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
360 if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) {
361 free(xdri_ctx->dummy_gc);
366 xdri_ctx->driContext =
367 psc->driScreen->createContext(psc,
370 (shared) ? shared->dummy_gc : NULL,
372 if (!xdri_ctx->driContext) {
373 free(xdri_ctx->dummy_gc);
378 /* fill in the required field */
379 xdri_ctx->dummy_gc->driContext = xdri_ctx->driContext;
381 return &xdri_ctx->Base;
386 xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
388 struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
389 struct xdri_egl_context *xdri_ctx = lookup_context(ctx);
391 if (!_eglIsContextBound(ctx)) {
392 xdri_ctx->driContext->destroyContext(xdri_ctx->driContext,
393 xdri_dpy->psc, xdri_dpy->dpy);
394 free(xdri_ctx->dummy_gc);
403 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
406 xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d,
407 _EGLSurface *r, _EGLContext *context)
409 struct xdri_egl_context *xdri_ctx = lookup_context(context);
410 struct xdri_egl_surface *draw = lookup_surface(d);
411 struct xdri_egl_surface *read = lookup_surface(r);
413 if (!_eglMakeCurrent(drv, dpy, d, r, context))
416 /* the symbol is defined in libGL.so */
417 _glapi_check_multithread();
420 if (!xdri_ctx->driContext->bindContext(xdri_ctx->driContext,
422 read->driDrawable)) {
427 _EGLContext *old = _eglGetCurrentContext();
429 xdri_ctx = lookup_context(old);
430 xdri_ctx->driContext->unbindContext(xdri_ctx->driContext);
439 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
442 xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
443 NativeWindowType window, const EGLint *attrib_list)
445 struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
446 struct xdri_egl_config *xdri_config = lookup_config(conf);
447 struct xdri_egl_surface *xdri_surf;
450 xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
452 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
456 if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_WINDOW_BIT,
457 &xdri_config->Base, attrib_list)) {
462 xdri_surf->driDrawable =
463 xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc,
465 (GLXDrawable) window,
467 if (!xdri_surf->driDrawable) {
472 xdri_surf->drawable = (Drawable) window;
474 get_drawable_size(xdri_dpy->dpy, window, &width, &height);
475 xdri_surf->Base.Width = width;
476 xdri_surf->Base.Height = height;
478 return &xdri_surf->Base;
483 * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface().
486 xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
487 const EGLint *attrib_list)
495 xdri_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
497 struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
499 if (!_eglIsSurfaceBound(&xdri_surf->Base)) {
500 xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable);
509 xdri_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
517 xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
525 xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
527 struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
528 struct xdri_egl_surface *xdri_surf = lookup_surface(draw);
530 xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable);
537 xdri_Unload(_EGLDriver *drv)
539 struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
545 * This is the main entrypoint into the driver, called by libEGL.
546 * Create a new _EGLDriver object and init its dispatch table.
549 _eglMain(const char *args)
551 struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver);
555 _eglInitDriverFallbacks(&xdri_drv->Base);
556 xdri_drv->Base.API.Initialize = xdri_eglInitialize;
557 xdri_drv->Base.API.Terminate = xdri_eglTerminate;
559 xdri_drv->Base.API.GetProcAddress = xdri_eglGetProcAddress;
561 xdri_drv->Base.API.CreateContext = xdri_eglCreateContext;
562 xdri_drv->Base.API.DestroyContext = xdri_eglDestroyContext;
563 xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent;
564 xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface;
565 xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface;
566 xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface;
567 xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage;
568 xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage;
569 xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
571 xdri_drv->Base.Name = "X/DRI";
572 xdri_drv->Base.Unload = xdri_Unload;
574 return &xdri_drv->Base;