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.
45 #include <sys/types.h>
52 #include "glxclient.h"
54 #include "drm_sarea.h"
56 #define _EGL_PLATFORM_X
58 #include "eglconfig.h"
59 #include "eglcontext.h"
60 #include "egldisplay.h"
61 #include "egldriver.h"
62 #include "eglglobals.h"
65 #include "eglsurface.h"
69 typedef void (*glGetIntegerv_t)(GLenum, GLint *);
70 typedef void (*glBindTexture_t)(GLenum, GLuint);
71 typedef void (*glCopyTexImage2D_t)(GLenum, GLint, GLenum, GLint, GLint,
75 #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
78 /** subclass of _EGLDriver */
79 struct xdri_egl_driver
81 _EGLDriver Base; /**< base class */
83 const char *dri_driver_name; /**< name of DRI driver to load */
84 void *dri_driver_handle; /**< returned by dlopen(dri_driver_name) */
86 __GLXdisplayPrivate *glx_priv;
89 /* XXX we're not actually using these at this time: */
94 __DRIframebuffer framebuffer;
102 /** subclass of _EGLContext */
103 struct xdri_egl_context
105 _EGLContext Base; /**< base class */
107 __DRIcontext driContext;
109 GLint bound_tex_object;
113 /** subclass of _EGLSurface */
114 struct xdri_egl_surface
116 _EGLSurface Base; /**< base class */
118 __DRIid driDrawable; /**< DRI surface */
119 drm_drawable_t hDrawable;
123 /** subclass of _EGLConfig */
124 struct xdri_egl_config
126 _EGLConfig Base; /**< base class */
128 const __GLcontextModes *mode; /**< corresponding GLX mode */
134 static struct xdri_egl_driver *
135 xdri_egl_driver(_EGLDriver *drv)
137 return (struct xdri_egl_driver *) drv;
141 /** Map EGLSurface handle to xdri_egl_surface object */
142 static struct xdri_egl_surface *
143 lookup_surface(EGLSurface surf)
145 _EGLSurface *surface = _eglLookupSurface(surf);
146 return (struct xdri_egl_surface *) surface;
150 /** Map EGLContext handle to xdri_egl_context object */
151 static struct xdri_egl_context *
152 lookup_context(EGLContext c)
154 _EGLContext *context = _eglLookupContext(c);
155 return (struct xdri_egl_context *) context;
158 static struct xdri_egl_context *
159 current_context(void)
161 return (struct xdri_egl_context *) _eglGetCurrentContext();
164 /** Map EGLConfig handle to xdri_egl_config object */
165 static struct xdri_egl_config *
166 lookup_config(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
168 _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
169 return (struct xdri_egl_config *) conf;
174 /** Get size of given window */
176 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
181 unsigned int w, h, bw, depth;
182 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
190 * Produce a set of EGL configs.
191 * Note that we get the list of GLcontextModes from the GLX library.
192 * This dependency on GLX lib will be removed someday.
195 create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv)
197 static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
201 __GLXscreenConfigs *scrn = glx_priv->screenConfigs;
202 const __GLcontextModes *m;
205 for (m = scrn->configs; m; m = m->next) {
206 /* EGL requires double-buffered configs */
207 if (m->doubleBufferMode) {
208 struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config);
210 _eglInitConfig(&config->Base, id++);
212 SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, m->rgbBits);
213 SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, m->redBits);
214 SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, m->greenBits);
215 SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, m->blueBits);
216 SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, m->alphaBits);
217 SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, m->depthBits);
218 SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, m->stencilBits);
219 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, m->samples);
220 SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, m->sampleBuffers);
221 SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, m->visualID);
222 SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType);
223 SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
224 SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
225 /* XXX only window rendering allowed ATM */
226 SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE,
227 (EGL_WINDOW_BIT | EGL_PBUFFER_BIT));
229 /* XXX possibly other things to init... */
231 /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */
234 _eglAddConfig(disp, &config->Base);
241 * Called via __DRIinterfaceMethods object
244 dri_get_proc_address(const char * proc_name)
251 dri_context_modes_destroy(__GLcontextModes *modes)
253 _eglLog(_EGL_DEBUG, "%s", __FUNCTION__);
256 __GLcontextModes * const next = modes->next;
264 * Create a linked list of 'count' GLcontextModes.
265 * These are used during the client/server visual negotiation phase,
268 static __GLcontextModes *
269 dri_context_modes_create(unsigned count, size_t minimum_size)
271 /* This code copied from libGLX, and modified */
272 const size_t size = (minimum_size > sizeof(__GLcontextModes))
273 ? minimum_size : sizeof(__GLcontextModes);
274 __GLcontextModes * head = NULL;
275 __GLcontextModes ** next;
279 for (i = 0 ; i < count ; i++) {
280 *next = (__GLcontextModes *) calloc(1, size);
282 dri_context_modes_destroy(head);
287 (*next)->doubleBufferMode = 1;
288 (*next)->visualID = GLX_DONT_CARE;
289 (*next)->visualType = GLX_DONT_CARE;
290 (*next)->visualRating = GLX_NONE;
291 (*next)->transparentPixel = GLX_NONE;
292 (*next)->transparentRed = GLX_DONT_CARE;
293 (*next)->transparentGreen = GLX_DONT_CARE;
294 (*next)->transparentBlue = GLX_DONT_CARE;
295 (*next)->transparentAlpha = GLX_DONT_CARE;
296 (*next)->transparentIndex = GLX_DONT_CARE;
297 (*next)->xRenderable = GLX_DONT_CARE;
298 (*next)->fbconfigID = GLX_DONT_CARE;
299 (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
300 (*next)->bindToTextureRgb = GLX_DONT_CARE;
301 (*next)->bindToTextureRgba = GLX_DONT_CARE;
302 (*next)->bindToMipmapTexture = GLX_DONT_CARE;
303 (*next)->bindToTextureTargets = 0;
304 (*next)->yInverted = GLX_DONT_CARE;
306 next = & ((*next)->next);
314 dri_find_dri_screen(__DRInativeDisplay *ndpy, int scrn)
316 __GLXdisplayPrivate *priv = __glXInitialize(ndpy);
317 __GLXscreenConfigs *scrnConf = priv->screenConfigs;
318 return &scrnConf->driScreen;
323 dri_window_exists(__DRInativeDisplay *ndpy, __DRIid draw)
330 dri_create_context(__DRInativeDisplay *ndpy, int screenNum, int configID,
331 void * contextID, drm_context_t * hw_context)
333 assert(configID >= 0);
334 return XF86DRICreateContextWithConfig(ndpy, screenNum,
335 configID, contextID, hw_context);
340 dri_destroy_context(__DRInativeDisplay * ndpy, int screen, __DRIid context)
342 return XF86DRIDestroyContext(ndpy, screen, context);
347 dri_create_drawable(__DRInativeDisplay * ndpy, int screen,
348 __DRIid drawable, drm_drawable_t * hHWDrawable)
350 _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
352 /* Create DRI drawable for given window ID (drawable) */
353 if (!XF86DRICreateDrawable(ndpy, screen, drawable, hHWDrawable))
361 dri_destroy_drawable(__DRInativeDisplay * ndpy, int screen, __DRIid drawable)
363 _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
364 return XF86DRIDestroyDrawable(ndpy, screen, drawable);
369 dri_get_drawable_info(__DRInativeDisplay *ndpy, int scrn,
370 __DRIid draw, unsigned int * index, unsigned int * stamp,
371 int * x, int * y, int * width, int * height,
372 int * numClipRects, drm_clip_rect_t ** pClipRects,
373 int * backX, int * backY,
374 int * numBackClipRects,
375 drm_clip_rect_t ** pBackClipRects)
377 _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
379 if (!XF86DRIGetDrawableInfo(ndpy, scrn, draw, index, stamp,
381 numClipRects, pClipRects,
383 numBackClipRects, pBackClipRects)) {
392 * Table of functions exported by the loader to the driver.
394 static const __DRIinterfaceMethods interface_methods = {
395 dri_get_proc_address,
397 dri_context_modes_create,
398 dri_context_modes_destroy,
407 dri_destroy_drawable,
408 dri_get_drawable_info,
410 NULL,/*__eglGetUST,*/
411 NULL,/*__eglGetMSCRate,*/
417 init_drm(struct xdri_egl_driver *xdri_drv, _EGLDisplay *disp)
419 __DRIversion ddx_version;
420 __DRIversion dri_version;
421 __DRIversion drm_version;
422 drmVersionPtr version;
426 int scrn = DefaultScreen(disp->Xdpy);
429 createNewScreen = (PFNCREATENEWSCREENFUNC)
430 dlsym(xdri_drv->dri_driver_handle, createNewScreenName);
431 if (!createNewScreen) {
432 _eglLog(_EGL_WARNING, "XDRI: Couldn't find %s function in the driver.",
433 createNewScreenName);
437 _eglLog(_EGL_DEBUG, "XDRI: Found %s", createNewScreenName);
442 * Get the DRI X extension version.
444 dri_version.major = 4;
445 dri_version.minor = 0;
446 dri_version.patch = 0;
448 if (!XF86DRIOpenConnection(disp->Xdpy, scrn,
449 &xdri_drv->hSAREA, &xdri_drv->busID)) {
450 _eglLog(_EGL_WARNING, "XF86DRIOpenConnection failed");
453 xdri_drv->drmFD = drmOpenOnce(NULL, xdri_drv->busID, &newlyopened);
454 if (xdri_drv->drmFD < 0) {
455 perror("drmOpenOnce failed: ");
459 _eglLog(_EGL_DEBUG, "XDRI: drmOpenOnce returned %d", xdri_drv->drmFD);
463 if (drmGetMagic(xdri_drv->drmFD, &xdri_drv->magic)) {
464 perror("drmGetMagic failed: ");
468 version = drmGetVersion(xdri_drv->drmFD);
470 drm_version.major = version->version_major;
471 drm_version.minor = version->version_minor;
472 drm_version.patch = version->version_patchlevel;
473 drmFreeVersion(version);
474 _eglLog(_EGL_DEBUG, "XDRI: Got DRM version %d.%d.%d",
480 drm_version.major = -1;
481 drm_version.minor = -1;
482 drm_version.patch = -1;
483 _eglLog(_EGL_WARNING, "XDRI: drmGetVersion() failed");
487 /* Authenticate w/ server.
489 if (!XF86DRIAuthConnection(disp->Xdpy, scrn, xdri_drv->magic)) {
490 _eglLog(_EGL_WARNING, "XDRI: XF86DRIAuthConnection() failed");
494 _eglLog(_EGL_DEBUG, "XDRI: XF86DRIAuthConnection() success");
503 * Get device name (like "tdfx") and the ddx version
504 * numbers. We'll check the version in each DRI driver's
505 * "createNewScreen" function.
507 if (!XF86DRIGetClientDriverName(disp->Xdpy, scrn,
512 _eglLog(_EGL_WARNING, "XDRI: XF86DRIGetClientDriverName failed");
516 _eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetClientDriverName returned %s", driverName);
520 /* Get framebuffer info.
524 if (!XF86DRIGetDeviceInfo(disp->Xdpy, scrn,
527 &xdri_drv->framebuffer.size,
528 &xdri_drv->framebuffer.stride,
529 &xdri_drv->framebuffer.dev_priv_size,
530 &xdri_drv->framebuffer.dev_priv)) {
531 _eglLog(_EGL_WARNING, "XDRI: XF86DRIGetDeviceInfo() failed");
535 _eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetDeviceInfo() success");
537 xdri_drv->framebuffer.width = DisplayWidth(disp->Xdpy, scrn);
538 xdri_drv->framebuffer.height = DisplayHeight(disp->Xdpy, scrn);
541 /* Map the framebuffer region. (this may not be needed)
543 status = drmMap(xdri_drv->drmFD, hFB, xdri_drv->framebuffer.size,
544 (drmAddressPtr) &xdri_drv->framebuffer.base);
546 _eglLog(_EGL_WARNING, "XDRI: drmMap(framebuffer) failed");
550 _eglLog(_EGL_DEBUG, "XDRI: drmMap(framebuffer) success");
553 /* Map the SAREA region.
555 status = drmMap(xdri_drv->drmFD, xdri_drv->hSAREA, SAREA_MAX, &xdri_drv->pSAREA);
557 _eglLog(_EGL_WARNING, "XDRI: drmMap(sarea) failed");
561 _eglLog(_EGL_DEBUG, "XDRI: drmMap(sarea) success");
569 * Load the DRI driver named by "xdri_drv->dri_driver_name".
570 * Basically, dlopen() the library to set "xdri_drv->dri_driver_handle".
572 * Later, we'll call dlsym(createNewScreenName) to get a pointer to
573 * the driver's createNewScreen() function which is the bootstrap function.
575 * \return EGL_TRUE for success, EGL_FALSE for failure
578 load_dri_driver(struct xdri_egl_driver *xdri_drv)
581 int flags = RTLD_NOW;
583 /* try "egl_xxx_dri.so" first */
584 snprintf(filename, sizeof(filename), "egl_%s.so", xdri_drv->dri_driver_name);
585 _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename);
586 xdri_drv->dri_driver_handle = dlopen(filename, flags);
587 if (xdri_drv->dri_driver_handle) {
588 _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) OK", filename);
592 _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) fail (%s)", filename, dlerror());
595 /* try regular "xxx_dri.so" next */
596 snprintf(filename, sizeof(filename), "%s.so", xdri_drv->dri_driver_name);
597 _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename);
598 xdri_drv->dri_driver_handle = dlopen(filename, flags);
599 if (xdri_drv->dri_driver_handle) {
600 _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) OK", filename);
604 _eglLog(_EGL_WARNING, "XDRI Could not open %s (%s)", filename, dlerror());
610 * Called via eglInitialize(), xdri_drv->API.Initialize().
613 xdri_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
614 EGLint *minor, EGLint *major)
616 struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
617 _EGLDisplay *disp = _eglLookupDisplay(dpy);
618 static char name[100];
620 _eglLog(_EGL_DEBUG, "XDRI: eglInitialize");
623 disp->Xdpy = XOpenDisplay(NULL);
625 _eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed");
631 /* choose the DRI driver to load */
632 xdri_drv->dri_driver_name = _eglChooseDRMDriver(0);
633 if (!load_dri_driver(xdri_drv))
636 (void) load_dri_driver;
640 if (!init_drm(xdri_drv, disp))
647 * NOTE: this call to __glXInitialize() bootstraps the whole GLX/DRI
648 * interface, loads the DRI driver, etc.
649 * This replaces the load_dri_driver() and init_drm() code above.
651 xdri_drv->glx_priv = __glXInitialize(disp->Xdpy);
653 create_configs(disp, xdri_drv->glx_priv);
655 xdri_drv->Base.Initialized = EGL_TRUE;
657 if (xdri_drv->dri_driver_name)
658 snprintf(name, sizeof(name), "X/DRI:%s", xdri_drv->dri_driver_name);
660 snprintf(name, sizeof(name), "X/DRI");
661 xdri_drv->Base.Name = name;
663 /* we're supporting EGL 1.4 */
672 * Do some clean-up that normally occurs in XCloseDisplay().
673 * We do this here because we're about to unload a dynamic library
674 * that has added some per-display extension data and callbacks.
675 * If we don't do this here we'll crash in XCloseDisplay() because it'll
676 * try to call functions that went away when the driver library was unloaded.
679 FreeDisplayExt(Display *dpy)
681 _XExtension *ext, *next;
683 for (ext = dpy->ext_procs; ext; ext = next) {
685 if (ext->close_display) {
686 ext->close_display(dpy, &ext->codes);
687 ext->close_display = NULL;
693 dpy->ext_procs = NULL;
695 _XFreeExtData (dpy->ext_data);
696 dpy->ext_data = NULL;
701 * Called via eglTerminate(), drv->API.Terminate().
704 xdri_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
706 struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
707 _EGLDisplay *disp = _eglLookupDisplay(dpy);
709 _eglLog(_EGL_DEBUG, "XDRI: eglTerminate");
711 _eglLog(_EGL_DEBUG, "XDRI: Closing %s", xdri_drv->dri_driver_name);
713 FreeDisplayExt(disp->Xdpy);
716 /* this causes a segfault for some reason */
717 dlclose(xdri_drv->dri_driver_handle);
719 xdri_drv->dri_driver_handle = NULL;
721 free((void*) xdri_drv->dri_driver_name);
728 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
731 xdri_eglGetProcAddress(const char *procname)
734 _EGLDriver *drv = NULL;
736 struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
737 /*_EGLDisplay *disp = _eglLookupDisplay(dpy);*/
738 _EGLProc *proc = xdri_drv->driScreen.getProcAddress(procname);
741 /* This is a bit of a hack to get at the gallium/Mesa state tracker
742 * function st_get_proc_address(). This will probably change at
745 _EGLProc (*st_get_proc_addr)(const char *procname);
746 st_get_proc_addr = dlsym(NULL, "st_get_proc_address");
747 if (st_get_proc_addr) {
748 return st_get_proc_addr(procname);
758 * Called via eglCreateContext(), drv->API.CreateContext().
761 xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
762 EGLContext share_list, const EGLint *attrib_list)
764 _EGLDisplay *disp = _eglLookupDisplay(dpy);
765 struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config);
767 int renderType = GLX_RGBA_BIT;
769 struct xdri_egl_context *xdri_ctx = CALLOC_STRUCT(xdri_egl_context);
771 return EGL_NO_CONTEXT;
773 if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) {
775 return EGL_NO_CONTEXT;
781 struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
782 __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
783 xdri_ctx->driContext.private =
784 scrnConf->driScreen.createNewContext(disp->Xdpy,
785 xdri_config->mode, renderType,
786 shared, &xdri_ctx->driContext);
789 if (!xdri_ctx->driContext.private) {
790 _eglLog(_EGL_DEBUG, "driScreen.createNewContext failed");
792 return EGL_NO_CONTEXT;
795 xdri_ctx->driContext.mode = xdri_config->mode;
797 return _eglLinkContext(&xdri_ctx->Base, &disp);
802 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
805 xdri_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
806 EGLSurface r, EGLContext context)
808 _EGLDisplay *disp = _eglLookupDisplay(dpy);
809 struct xdri_egl_context *xdri_ctx = lookup_context(context);
810 struct xdri_egl_surface *xdri_draw = lookup_surface(d);
811 struct xdri_egl_surface *xdri_read = lookup_surface(r);
812 __DRIid draw = xdri_draw ? xdri_draw->driDrawable : 0;
813 __DRIid read = xdri_read ? xdri_read->driDrawable : 0;
814 int scrn = DefaultScreen(disp->Xdpy);
816 if (!_eglMakeCurrent(drv, dpy, d, r, context))
821 !xdri_ctx->driContext.bindContext(disp->Xdpy, scrn, draw, read,
822 &xdri_ctx->driContext)) {
831 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
834 xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
835 NativeWindowType window, const EGLint *attrib_list)
837 _EGLDisplay *disp = _eglLookupDisplay(dpy);
838 struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config);
839 struct xdri_egl_surface *xdri_surf;
840 int scrn = DefaultScreen(disp->Xdpy);
843 xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
845 return EGL_NO_SURFACE;
847 if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_WINDOW_BIT,
848 &xdri_config->Base, attrib_list)) {
853 if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) {
858 xdri_surf->driDrawable = window;
860 _eglLinkSurface(&xdri_surf->Base, disp);
862 get_drawable_size(disp->Xdpy, window, &width, &height);
863 xdri_surf->Base.Width = width;
864 xdri_surf->Base.Height = height;
867 "XDRI: CreateWindowSurface win 0x%x handle %d hDrawable %d",
868 (int) window, _eglGetSurfaceHandle(&xdri_surf->Base),
869 (int) xdri_surf->hDrawable);
871 return _eglGetSurfaceHandle(&xdri_surf->Base);
876 * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface().
879 xdri_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
880 const EGLint *attrib_list)
882 _EGLDisplay *disp = _eglLookupDisplay(dpy);
883 struct xdri_egl_surface *xdri_surf;
884 struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config);
885 int scrn = DefaultScreen(disp->Xdpy);
888 xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
890 return EGL_NO_SURFACE;
892 if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_PBUFFER_BIT,
893 &xdri_config->Base, attrib_list)) {
898 /* Create a dummy X window */
900 Window root = RootWindow(disp->Xdpy, scrn);
901 XSetWindowAttributes attr;
902 XVisualInfo *visInfo, visTemplate;
906 visTemplate.visualid = xdri_config->mode->visualID;
907 visInfo = XGetVisualInfo(disp->Xdpy, VisualIDMask, &visTemplate, &nvis);
909 return EGL_NO_SURFACE;
912 attr.background_pixel = 0;
913 attr.border_pixel = 0;
914 attr.colormap = XCreateColormap(disp->Xdpy, root,
915 visInfo->visual, AllocNone);
916 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
917 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
919 window = XCreateWindow(disp->Xdpy, root, 0, 0,
920 xdri_surf->Base.Width, xdri_surf->Base.Height,
921 0, visInfo->depth, InputOutput,
922 visInfo->visual, mask, &attr);
924 /*XMapWindow(disp->Xdpy, window);*/
927 /* set hints and properties */
929 sizehints.width = xdri_surf->Base.Width;
930 sizehints.height = xdri_surf->Base.Height;
931 sizehints.flags = USPosition;
932 XSetNormalHints(disp->Xdpy, window, &sizehints);
936 if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) {
941 xdri_surf->driDrawable = window;
943 _eglLinkSurface(&xdri_surf->Base, disp);
946 "XDRI: CreatePbufferSurface handle %d hDrawable %d",
947 _eglGetSurfaceHandle(&xdri_surf->Base),
948 (int) xdri_surf->hDrawable);
950 return _eglGetSurfaceHandle(&xdri_surf->Base);
956 xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
958 struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
960 _eglUnlinkSurface(&xdri_surf->Base);
961 if (xdri_surf->Base.IsBound) {
962 xdri_surf->Base.DeletePending = EGL_TRUE;
966 st_unreference_framebuffer(surf->Framebuffer);
973 _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
980 xdri_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
983 typedef int (*bind_teximage)(__DRInativeDisplay *dpy,
984 __DRIid surface, __DRIscreen *psc,
985 int buffer, int target, int format,
986 int level, int mipmap);
988 bind_teximage egl_dri_bind_teximage;
990 _EGLDisplay *disp = _eglLookupDisplay(dpy);
992 struct xdri_egl_context *xdri_ctx = current_context();
993 struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
994 struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
996 __DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0;
998 __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
999 __DRIscreen *psc = &scrnConf->driScreen;
1001 /* this call just does error checking */
1002 if (!_eglBindTexImage(drv, dpy, surface, buffer)) {
1006 egl_dri_bind_teximage =
1007 (bind_teximage) dlsym(NULL, "egl_dri_bind_teximage");
1008 if (egl_dri_bind_teximage) {
1009 return egl_dri_bind_teximage(disp->Xdpy, dri_surf, psc,
1011 xdri_surf->Base.TextureTarget,
1012 xdri_surf->Base.TextureFormat,
1013 xdri_surf->Base.MipmapLevel,
1014 xdri_surf->Base.MipmapTexture);
1017 /* fallback path based on glCopyTexImage() */
1018 /* Get/save currently bound 2D texobj name */
1019 glGetIntegerv_t glGetIntegerv_func =
1020 (glGetIntegerv_t) dlsym(NULL, "glGetIntegerv");
1021 GLint curTexObj = 0;
1022 if (glGetIntegerv_func) {
1023 (*glGetIntegerv_func)(GL_TEXTURE_BINDING_2D, &curTexObj);
1025 xdri_ctx->bound_tex_object = curTexObj;
1033 xdri_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
1036 typedef int (*release_teximage)(__DRInativeDisplay *dpy,
1037 __DRIid surface, __DRIscreen *psc,
1038 int buffer, int target, int format,
1039 int level, int mipmap);
1040 release_teximage egl_dri_release_teximage;
1042 _EGLDisplay *disp = _eglLookupDisplay(dpy);
1044 struct xdri_egl_context *xdri_ctx = current_context();
1045 struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
1046 struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
1048 __DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0;
1050 __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
1051 __DRIscreen *psc = &scrnConf->driScreen;
1053 /* this call just does error checking */
1054 if (!_eglReleaseTexImage(drv, dpy, surface, buffer)) {
1058 egl_dri_release_teximage =
1059 (release_teximage) dlsym(NULL, "egl_dri_release_teximage");
1060 if (egl_dri_release_teximage) {
1061 return egl_dri_release_teximage(disp->Xdpy, dri_surf, psc,
1063 xdri_surf->Base.TextureTarget,
1064 xdri_surf->Base.TextureFormat,
1065 xdri_surf->Base.MipmapLevel,
1066 xdri_surf->Base.MipmapTexture);
1069 /* fallback path based on glCopyTexImage() */
1070 glGetIntegerv_t glGetIntegerv_func =
1071 (glGetIntegerv_t) dlsym(NULL, "glGetIntegerv");
1072 glBindTexture_t glBindTexture_func =
1073 (glBindTexture_t) dlsym(NULL, "glBindTexture");
1074 glCopyTexImage2D_t glCopyTexImage2D_func =
1075 (glCopyTexImage2D_t) dlsym(NULL, "glCopyTexImage2D");
1078 GLint level, width, height;
1080 if (xdri_surf->Base.TextureFormat == EGL_TEXTURE_RGBA)
1081 intFormat = GL_RGBA;
1084 level = xdri_surf->Base.MipmapLevel;
1085 width = xdri_surf->Base.Width >> level;
1086 height = xdri_surf->Base.Height >> level;
1088 if (width > 0 && height > 0 &&
1089 glGetIntegerv_func && glBindTexture_func && glCopyTexImage2D_func) {
1090 glGetIntegerv_func(GL_TEXTURE_BINDING_2D, &curTexObj);
1091 /* restore texobj from time of eglBindTexImage() call */
1092 if (curTexObj != xdri_ctx->bound_tex_object)
1093 glBindTexture_func(GL_TEXTURE_2D, xdri_ctx->bound_tex_object);
1094 /* copy pbuffer image to texture */
1095 glCopyTexImage2D_func(GL_TEXTURE_2D,
1098 0, 0, width, height, 0);
1099 /* restore current texture */
1100 if (curTexObj != xdri_ctx->bound_tex_object)
1101 glBindTexture_func(GL_TEXTURE_2D, curTexObj);
1103 xdri_ctx->bound_tex_object = -1;
1111 xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
1113 _EGLDisplay *disp = _eglLookupDisplay(dpy);
1115 _eglLog(_EGL_DEBUG, "XDRI: EGL SwapBuffers");
1117 /* error checking step: */
1118 if (!_eglSwapBuffers(drv, dpy, draw))
1122 struct xdri_egl_surface *xdri_surf = lookup_surface(draw);
1123 struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
1124 __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
1125 __DRIscreen *psc = &scrnConf->driScreen;
1126 __DRIdrawable * const pdraw = psc->getDrawable(disp->Xdpy,
1127 xdri_surf->driDrawable,
1131 pdraw->swapBuffers(disp->Xdpy, pdraw->private);
1133 _eglLog(_EGL_WARNING, "pdraw is null in SwapBuffers");
1141 * This is the main entrypoint into the driver, called by libEGL.
1142 * Create a new _EGLDriver object and init its dispatch table.
1145 _eglMain(_EGLDisplay *disp, const char *args)
1147 struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver);
1151 /* Tell libGL to prefer the EGL drivers over regular DRI drivers */
1154 _eglInitDriverFallbacks(&xdri_drv->Base);
1155 xdri_drv->Base.API.Initialize = xdri_eglInitialize;
1156 xdri_drv->Base.API.Terminate = xdri_eglTerminate;
1158 xdri_drv->Base.API.GetProcAddress = xdri_eglGetProcAddress;
1160 xdri_drv->Base.API.CreateContext = xdri_eglCreateContext;
1161 xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent;
1162 xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface;
1163 xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface;
1164 xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface;
1165 xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage;
1166 xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage;
1167 xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
1169 xdri_drv->Base.ClientAPIsMask = (EGL_OPENGL_BIT |
1171 EGL_OPENGL_ES2_BIT |
1173 xdri_drv->Base.Name = "X/DRI";
1175 _eglLog(_EGL_DEBUG, "XDRI: main(%s)", args);
1177 return &xdri_drv->Base;