diff options
Diffstat (limited to 'src/egl/drivers/xdri/egl_xdri.c')
-rw-r--r-- | src/egl/drivers/xdri/egl_xdri.c | 1060 |
1 files changed, 229 insertions, 831 deletions
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c index 3b3e312746..518091a2d1 100644 --- a/src/egl/drivers/xdri/egl_xdri.c +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -39,63 +39,40 @@ * Authors: Brian Paul */ - #include <assert.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include "dlfcn.h" +#include <stdlib.h> #include <X11/Xlib.h> -#include <GL/gl.h> -#include "xf86dri.h" -#include "glxclient.h" -#include "dri_util.h" -#include "drm_sarea.h" -#define _EGL_PLATFORM_X +#include "glxinit.h" +#include "driinit.h" +#include "glapi/glapi.h" /* for glapi functions */ #include "eglconfig.h" #include "eglcontext.h" #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" -#include "eglhash.h" #include "egllog.h" #include "eglsurface.h" -#include <GL/gl.h> - -typedef void (*glGetIntegerv_t)(GLenum, GLint *); -typedef void (*glBindTexture_t)(GLenum, GLuint); -typedef void (*glCopyTexImage2D_t)(GLenum, GLint, GLenum, GLint, GLint, - GLint, GLint, GLint); - - #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) - /** subclass of _EGLDriver */ struct xdri_egl_driver { _EGLDriver Base; /**< base class */ - - const char *dri_driver_name; /**< name of DRI driver to load */ - void *dri_driver_handle; /**< returned by dlopen(dri_driver_name) */ - - __GLXdisplayPrivate *glx_priv; +}; - /* XXX we're not actually using these at this time: */ - int chipset; - int minor; - int drmFD; +/** driver data of _EGLDisplay */ +struct xdri_egl_display +{ + Display *dpy; + __GLXdisplayPrivate *dpyPriv; + __GLXDRIdisplay *driDisplay; - __DRIframebuffer framebuffer; - drm_handle_t hSAREA; - drmAddress pSAREA; - char *busID; - drm_magic_t magic; + __GLXscreenConfigs *psc; + EGLint scr; }; @@ -104,9 +81,10 @@ struct xdri_egl_context { _EGLContext Base; /**< base class */ - __DRIcontext driContext; + /* just enough info to create dri contexts */ + GLXContext dummy_gc; - GLint bound_tex_object; + __GLXDRIcontext *driContext; }; @@ -115,8 +93,8 @@ struct xdri_egl_surface { _EGLSurface Base; /**< base class */ - __DRIid driDrawable; /**< DRI surface */ - drm_drawable_t hDrawable; + Drawable drawable; + __GLXDRIdrawable *driDrawable; }; @@ -131,46 +109,44 @@ struct xdri_egl_config /** cast wrapper */ -static struct xdri_egl_driver * +static INLINE struct xdri_egl_driver * xdri_egl_driver(_EGLDriver *drv) { return (struct xdri_egl_driver *) drv; } +static INLINE struct xdri_egl_display * +lookup_display(_EGLDisplay *dpy) +{ + return (struct xdri_egl_display *) dpy->DriverData; +} + + /** Map EGLSurface handle to xdri_egl_surface object */ -static struct xdri_egl_surface * -lookup_surface(EGLSurface surf) +static INLINE struct xdri_egl_surface * +lookup_surface(_EGLSurface *surface) { - _EGLSurface *surface = _eglLookupSurface(surf); return (struct xdri_egl_surface *) surface; } /** Map EGLContext handle to xdri_egl_context object */ -static struct xdri_egl_context * -lookup_context(EGLContext c) +static INLINE struct xdri_egl_context * +lookup_context(_EGLContext *context) { - _EGLContext *context = _eglLookupContext(c); return (struct xdri_egl_context *) context; } -static struct xdri_egl_context * -current_context(void) -{ - return (struct xdri_egl_context *) _eglGetCurrentContext(); -} /** Map EGLConfig handle to xdri_egl_config object */ -static struct xdri_egl_config * -lookup_config(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config) +static INLINE struct xdri_egl_config * +lookup_config(_EGLConfig *conf) { - _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); return (struct xdri_egl_config *) conf; } - /** Get size of given window */ static Status get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) @@ -188,22 +164,18 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) /** * Produce a set of EGL configs. - * Note that we get the list of GLcontextModes from the GLX library. - * This dependency on GLX lib will be removed someday. */ -static void -create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv) +static EGLint +create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id) { static const EGLint all_apis = (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT | EGL_OPENGL_BIT); - __GLXscreenConfigs *scrn = glx_priv->screenConfigs; - const __GLcontextModes *m; - int id = 1; + int id = first_id; - for (m = scrn->configs; m; m = m->next) { - /* EGL requires double-buffered configs */ + for (; m; m = m->next) { + /* add double buffered visual */ if (m->doubleBufferMode) { struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config); @@ -222,9 +194,7 @@ create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv) SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType); SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis); SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis); - /* XXX only window rendering allowed ATM */ - SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, - (EGL_WINDOW_BIT | EGL_PBUFFER_BIT)); + SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); /* XXX possibly other things to init... */ @@ -234,431 +204,76 @@ create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv) _eglAddConfig(disp, &config->Base); } } -} - - -/** - * Called via __DRIinterfaceMethods object - */ -static __DRIfuncPtr -dri_get_proc_address(const char * proc_name) -{ - return NULL; -} - - -static void -dri_context_modes_destroy(__GLcontextModes *modes) -{ - _eglLog(_EGL_DEBUG, "%s", __FUNCTION__); - - while (modes) { - __GLcontextModes * const next = modes->next; - free(modes); - modes = next; - } -} - - -/** - * Create a linked list of 'count' GLcontextModes. - * These are used during the client/server visual negotiation phase, - * then discarded. - */ -static __GLcontextModes * -dri_context_modes_create(unsigned count, size_t minimum_size) -{ - /* This code copied from libGLX, and modified */ - const size_t size = (minimum_size > sizeof(__GLcontextModes)) - ? minimum_size : sizeof(__GLcontextModes); - __GLcontextModes * head = NULL; - __GLcontextModes ** next; - unsigned i; - - next = & head; - for (i = 0 ; i < count ; i++) { - *next = (__GLcontextModes *) calloc(1, size); - if (*next == NULL) { - dri_context_modes_destroy(head); - head = NULL; - break; - } - - (*next)->doubleBufferMode = 1; - (*next)->visualID = GLX_DONT_CARE; - (*next)->visualType = GLX_DONT_CARE; - (*next)->visualRating = GLX_NONE; - (*next)->transparentPixel = GLX_NONE; - (*next)->transparentRed = GLX_DONT_CARE; - (*next)->transparentGreen = GLX_DONT_CARE; - (*next)->transparentBlue = GLX_DONT_CARE; - (*next)->transparentAlpha = GLX_DONT_CARE; - (*next)->transparentIndex = GLX_DONT_CARE; - (*next)->xRenderable = GLX_DONT_CARE; - (*next)->fbconfigID = GLX_DONT_CARE; - (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; - (*next)->bindToTextureRgb = GLX_DONT_CARE; - (*next)->bindToTextureRgba = GLX_DONT_CARE; - (*next)->bindToMipmapTexture = GLX_DONT_CARE; - (*next)->bindToTextureTargets = 0; - (*next)->yInverted = GLX_DONT_CARE; - - next = & ((*next)->next); - } - - return head; -} - - -static __DRIscreen * -dri_find_dri_screen(__DRInativeDisplay *ndpy, int scrn) -{ - __GLXdisplayPrivate *priv = __glXInitialize(ndpy); - __GLXscreenConfigs *scrnConf = priv->screenConfigs; - return &scrnConf->driScreen; -} - - -static GLboolean -dri_window_exists(__DRInativeDisplay *ndpy, __DRIid draw) -{ - return EGL_TRUE; -} - - -static GLboolean -dri_create_context(__DRInativeDisplay *ndpy, int screenNum, int configID, - void * contextID, drm_context_t * hw_context) -{ - assert(configID >= 0); - return XF86DRICreateContextWithConfig(ndpy, screenNum, - configID, contextID, hw_context); -} - - -static GLboolean -dri_destroy_context(__DRInativeDisplay * ndpy, int screen, __DRIid context) -{ - return XF86DRIDestroyContext(ndpy, screen, context); -} - - -static GLboolean -dri_create_drawable(__DRInativeDisplay * ndpy, int screen, - __DRIid drawable, drm_drawable_t * hHWDrawable) -{ - _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__); - - /* Create DRI drawable for given window ID (drawable) */ - if (!XF86DRICreateDrawable(ndpy, screen, drawable, hHWDrawable)) - return EGL_FALSE; - - return EGL_TRUE; -} - - -static GLboolean -dri_destroy_drawable(__DRInativeDisplay * ndpy, int screen, __DRIid drawable) -{ - _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__); - return XF86DRIDestroyDrawable(ndpy, screen, drawable); -} - - -static GLboolean -dri_get_drawable_info(__DRInativeDisplay *ndpy, int scrn, - __DRIid draw, unsigned int * index, unsigned int * stamp, - int * x, int * y, int * width, int * height, - int * numClipRects, drm_clip_rect_t ** pClipRects, - int * backX, int * backY, - int * numBackClipRects, - drm_clip_rect_t ** pBackClipRects) -{ - _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__); - - if (!XF86DRIGetDrawableInfo(ndpy, scrn, draw, index, stamp, - x, y, width, height, - numClipRects, pClipRects, - backX, backY, - numBackClipRects, pBackClipRects)) { - return EGL_FALSE; - } - return EGL_TRUE; + return id; } /** - * Table of functions exported by the loader to the driver. + * Called via eglInitialize(), xdri_dpy->API.Initialize(). */ -static const __DRIinterfaceMethods interface_methods = { - dri_get_proc_address, - - dri_context_modes_create, - dri_context_modes_destroy, - - dri_find_dri_screen, - dri_window_exists, - - dri_create_context, - dri_destroy_context, - - dri_create_drawable, - dri_destroy_drawable, - dri_get_drawable_info, - - NULL,/*__eglGetUST,*/ - NULL,/*__eglGetMSCRate,*/ -}; - - - static EGLBoolean -init_drm(struct xdri_egl_driver *xdri_drv, _EGLDisplay *disp) +xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, + EGLint *minor, EGLint *major) { - __DRIversion ddx_version; - __DRIversion dri_version; - __DRIversion drm_version; - drmVersionPtr version; - drm_handle_t hFB; - int newlyopened; - int status; - int scrn = DefaultScreen(disp->Xdpy); - -#if 0 - createNewScreen = (PFNCREATENEWSCREENFUNC) - dlsym(xdri_drv->dri_driver_handle, createNewScreenName); - if (!createNewScreen) { - _eglLog(_EGL_WARNING, "XDRI: Couldn't find %s function in the driver.", - createNewScreenName); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: Found %s", createNewScreenName); - } -#endif - - /* - * Get the DRI X extension version. - */ - dri_version.major = 4; - dri_version.minor = 0; - dri_version.patch = 0; - - if (!XF86DRIOpenConnection(disp->Xdpy, scrn, - &xdri_drv->hSAREA, &xdri_drv->busID)) { - _eglLog(_EGL_WARNING, "XF86DRIOpenConnection failed"); - } - - xdri_drv->drmFD = drmOpenOnce(NULL, xdri_drv->busID, &newlyopened); - if (xdri_drv->drmFD < 0) { - perror("drmOpenOnce failed: "); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: drmOpenOnce returned %d", xdri_drv->drmFD); - } - - - if (drmGetMagic(xdri_drv->drmFD, &xdri_drv->magic)) { - perror("drmGetMagic failed: "); - return EGL_FALSE; - } - - version = drmGetVersion(xdri_drv->drmFD); - if (version) { - drm_version.major = version->version_major; - drm_version.minor = version->version_minor; - drm_version.patch = version->version_patchlevel; - drmFreeVersion(version); - _eglLog(_EGL_DEBUG, "XDRI: Got DRM version %d.%d.%d", - drm_version.major, - drm_version.minor, - drm_version.patch); - } - else { - drm_version.major = -1; - drm_version.minor = -1; - drm_version.patch = -1; - _eglLog(_EGL_WARNING, "XDRI: drmGetVersion() failed"); - return EGL_FALSE; - } - - /* Authenticate w/ server. - */ - if (!XF86DRIAuthConnection(disp->Xdpy, scrn, xdri_drv->magic)) { - _eglLog(_EGL_WARNING, "XDRI: XF86DRIAuthConnection() failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: XF86DRIAuthConnection() success"); - } - - /* Get ddx version. - */ - { - char *driverName; - - /* - * Get device name (like "tdfx") and the ddx version - * numbers. We'll check the version in each DRI driver's - * "createNewScreen" function. - */ - if (!XF86DRIGetClientDriverName(disp->Xdpy, scrn, - &ddx_version.major, - &ddx_version.minor, - &ddx_version.patch, - &driverName)) { - _eglLog(_EGL_WARNING, "XDRI: XF86DRIGetClientDriverName failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetClientDriverName returned %s", driverName); + struct xdri_egl_display *xdri_dpy; + __GLXdisplayPrivate *dpyPriv; + __GLXDRIdisplay *driDisplay; + __GLXscreenConfigs *psc; + EGLint first_id = 1; + int scr; + + xdri_dpy = CALLOC_STRUCT(xdri_egl_display); + if (!xdri_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + xdri_dpy->dpy = (Display *) dpy->NativeDisplay; + if (!xdri_dpy->dpy) { + xdri_dpy->dpy = XOpenDisplay(NULL); + if (!xdri_dpy->dpy) { + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } } - /* Get framebuffer info. - */ - { - int junk; - if (!XF86DRIGetDeviceInfo(disp->Xdpy, scrn, - &hFB, - &junk, - &xdri_drv->framebuffer.size, - &xdri_drv->framebuffer.stride, - &xdri_drv->framebuffer.dev_priv_size, - &xdri_drv->framebuffer.dev_priv)) { - _eglLog(_EGL_WARNING, "XDRI: XF86DRIGetDeviceInfo() failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetDeviceInfo() success"); - } - xdri_drv->framebuffer.width = DisplayWidth(disp->Xdpy, scrn); - xdri_drv->framebuffer.height = DisplayHeight(disp->Xdpy, scrn); - } - - /* Map the framebuffer region. (this may not be needed) - */ - status = drmMap(xdri_drv->drmFD, hFB, xdri_drv->framebuffer.size, - (drmAddressPtr) &xdri_drv->framebuffer.base); - if (status != 0) { - _eglLog(_EGL_WARNING, "XDRI: drmMap(framebuffer) failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: drmMap(framebuffer) success"); - } - - /* Map the SAREA region. - */ - status = drmMap(xdri_drv->drmFD, xdri_drv->hSAREA, SAREA_MAX, &xdri_drv->pSAREA); - if (status != 0) { - _eglLog(_EGL_WARNING, "XDRI: drmMap(sarea) failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: drmMap(sarea) success"); - } - - return EGL_TRUE; -} - - -/** - * Load the DRI driver named by "xdri_drv->dri_driver_name". - * Basically, dlopen() the library to set "xdri_drv->dri_driver_handle". - * - * Later, we'll call dlsym(createNewScreenName) to get a pointer to - * the driver's createNewScreen() function which is the bootstrap function. - * - * \return EGL_TRUE for success, EGL_FALSE for failure - */ -static EGLBoolean -load_dri_driver(struct xdri_egl_driver *xdri_drv) -{ - char filename[100]; - int flags = RTLD_NOW; - - /* try "egl_xxx_dri.so" first */ - snprintf(filename, sizeof(filename), "egl_%s.so", xdri_drv->dri_driver_name); - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename); - xdri_drv->dri_driver_handle = dlopen(filename, flags); - if (xdri_drv->dri_driver_handle) { - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) OK", filename); - return EGL_TRUE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) fail (%s)", filename, dlerror()); + dpyPriv = __glXInitialize(xdri_dpy->dpy); + if (!dpyPriv) { + _eglLog(_EGL_WARNING, "failed to create GLX display"); + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } - /* try regular "xxx_dri.so" next */ - snprintf(filename, sizeof(filename), "%s.so", xdri_drv->dri_driver_name); - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename); - xdri_drv->dri_driver_handle = dlopen(filename, flags); - if (xdri_drv->dri_driver_handle) { - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) OK", filename); - return EGL_TRUE; + driDisplay = __driCreateDisplay(dpyPriv, NULL); + if (!driDisplay) { + _eglLog(_EGL_WARNING, "failed to create DRI display"); + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } - _eglLog(_EGL_WARNING, "XDRI Could not open %s (%s)", filename, dlerror()); - return EGL_FALSE; -} - - -/** - * Called via eglInitialize(), xdri_drv->API.Initialize(). - */ -static EGLBoolean -xdri_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, - EGLint *minor, EGLint *major) -{ - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - _EGLDisplay *disp = _eglLookupDisplay(dpy); - static char name[100]; + scr = DefaultScreen(xdri_dpy->dpy); + psc = &dpyPriv->screenConfigs[scr]; - _eglLog(_EGL_DEBUG, "XDRI: eglInitialize"); + xdri_dpy->dpyPriv = dpyPriv; + xdri_dpy->driDisplay = driDisplay; + xdri_dpy->psc = psc; + xdri_dpy->scr = scr; - if (!disp->Xdpy) { - disp->Xdpy = XOpenDisplay(NULL); - if (!disp->Xdpy) { - _eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed"); - return EGL_FALSE; - } + psc->driScreen = driDisplay->createScreen(psc, scr, dpyPriv); + if (!psc->driScreen) { + _eglLog(_EGL_WARNING, "failed to create DRI screen #%d", scr); + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } -#if 0 - /* choose the DRI driver to load */ - xdri_drv->dri_driver_name = _eglChooseDRMDriver(0); - if (!load_dri_driver(xdri_drv)) - return EGL_FALSE; -#else - (void) load_dri_driver; -#endif - -#if 0 - if (!init_drm(xdri_drv, disp)) - return EGL_FALSE; -#else - (void) init_drm; -#endif - - /* - * NOTE: this call to __glXInitialize() bootstraps the whole GLX/DRI - * interface, loads the DRI driver, etc. - * This replaces the load_dri_driver() and init_drm() code above. - */ - xdri_drv->glx_priv = __glXInitialize(disp->Xdpy); - - create_configs(disp, xdri_drv->glx_priv); + /* add visuals and fbconfigs */ + first_id = create_configs(dpy, psc->visuals, first_id); + create_configs(dpy, psc->configs, first_id); - xdri_drv->Base.Initialized = EGL_TRUE; - - if (xdri_drv->dri_driver_name) - snprintf(name, sizeof(name), "X/DRI:%s", xdri_drv->dri_driver_name); - else - snprintf(name, sizeof(name), "X/DRI"); - xdri_drv->Base.Name = name; + dpy->DriverData = xdri_dpy; + dpy->ClientAPIsMask = (EGL_OPENGL_BIT | + EGL_OPENGL_ES_BIT | + EGL_OPENGL_ES2_BIT | + EGL_OPENVG_BIT); /* we're supporting EGL 1.4 */ *minor = 1; @@ -668,57 +283,37 @@ xdri_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, } -/* - * Do some clean-up that normally occurs in XCloseDisplay(). - * We do this here because we're about to unload a dynamic library - * that has added some per-display extension data and callbacks. - * If we don't do this here we'll crash in XCloseDisplay() because it'll - * try to call functions that went away when the driver library was unloaded. - */ -static void -FreeDisplayExt(Display *dpy) -{ - _XExtension *ext, *next; - - for (ext = dpy->ext_procs; ext; ext = next) { - next = ext->next; - if (ext->close_display) { - ext->close_display(dpy, &ext->codes); - ext->close_display = NULL; - } - if (ext->name) - Xfree(ext->name); - Xfree(ext); - } - dpy->ext_procs = NULL; - - _XFreeExtData (dpy->ext_data); - dpy->ext_data = NULL; -} - - /** * Called via eglTerminate(), drv->API.Terminate(). */ static EGLBoolean -xdri_eglTerminate(_EGLDriver *drv, EGLDisplay dpy) +xdri_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) { - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + __GLXscreenConfigs *psc; - _eglLog(_EGL_DEBUG, "XDRI: eglTerminate"); + _eglReleaseDisplayResources(drv, dpy); + _eglCleanupDisplay(dpy); - _eglLog(_EGL_DEBUG, "XDRI: Closing %s", xdri_drv->dri_driver_name); - - FreeDisplayExt(disp->Xdpy); + psc = xdri_dpy->psc; + if (psc->driver_configs) { + unsigned int i; + for (i = 0; psc->driver_configs[i]; i++) + free((__DRIconfig *) psc->driver_configs[i]); + free(psc->driver_configs); + psc->driver_configs = NULL; + } + if (psc->driScreen) { + psc->driScreen->destroyScreen(psc); + free(psc->driScreen); + psc->driScreen = NULL; + } -#if 0 - /* this causes a segfault for some reason */ - dlclose(xdri_drv->dri_driver_handle); -#endif - xdri_drv->dri_driver_handle = NULL; + xdri_dpy->driDisplay->destroyDisplay(xdri_dpy->driDisplay); + __glXRelease(xdri_dpy->dpyPriv); - free((void*) xdri_drv->dri_driver_name); + free(xdri_dpy); + dpy->DriverData = NULL; return EGL_TRUE; } @@ -730,71 +325,77 @@ xdri_eglTerminate(_EGLDriver *drv, EGLDisplay dpy) static _EGLProc xdri_eglGetProcAddress(const char *procname) { -#if 0 - _EGLDriver *drv = NULL; - - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - /*_EGLDisplay *disp = _eglLookupDisplay(dpy);*/ - _EGLProc *proc = xdri_drv->driScreen.getProcAddress(procname); - return proc; -#elif 1 - /* This is a bit of a hack to get at the gallium/Mesa state tracker - * function st_get_proc_address(). This will probably change at - * some point. - */ - _EGLProc (*st_get_proc_addr)(const char *procname); - st_get_proc_addr = dlsym(NULL, "st_get_proc_address"); - if (st_get_proc_addr) { - return st_get_proc_addr(procname); - } - return NULL; -#else - return NULL; -#endif + /* the symbol is defined in libGL.so */ + return (_EGLProc) _glapi_get_proc_address(procname); } /** * Called via eglCreateContext(), drv->API.CreateContext(). */ -static EGLContext -xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, - EGLContext share_list, const EGLint *attrib_list) -{ - _EGLDisplay *disp = _eglLookupDisplay(dpy); - struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config); - void *shared = NULL; +static _EGLContext * +xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + _EGLContext *share_list, const EGLint *attrib_list) +{ + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_config *xdri_config = lookup_config(conf); + struct xdri_egl_context *shared = lookup_context(share_list); + __GLXscreenConfigs *psc = xdri_dpy->psc; int renderType = GLX_RGBA_BIT; + struct xdri_egl_context *xdri_ctx; - struct xdri_egl_context *xdri_ctx = CALLOC_STRUCT(xdri_egl_context); - if (!xdri_ctx) - return EGL_NO_CONTEXT; + xdri_ctx = CALLOC_STRUCT(xdri_egl_context); + if (!xdri_ctx) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + return NULL; + } - if (!_eglInitContext(drv, dpy, &xdri_ctx->Base, config, attrib_list)) { + xdri_ctx->dummy_gc = CALLOC_STRUCT(__GLXcontextRec); + if (!xdri_ctx->dummy_gc) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); free(xdri_ctx); - return EGL_NO_CONTEXT; + return NULL; } - assert(xdri_config); - - { - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs; - xdri_ctx->driContext.private = - scrnConf->driScreen.createNewContext(disp->Xdpy, - xdri_config->mode, renderType, - shared, &xdri_ctx->driContext); + if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) { + free(xdri_ctx->dummy_gc); + free(xdri_ctx); + return NULL; } - if (!xdri_ctx->driContext.private) { - _eglLog(_EGL_DEBUG, "driScreen.createNewContext failed"); + xdri_ctx->driContext = + psc->driScreen->createContext(psc, + xdri_config->mode, + xdri_ctx->dummy_gc, + (shared) ? shared->dummy_gc : NULL, + renderType); + if (!xdri_ctx->driContext) { + free(xdri_ctx->dummy_gc); free(xdri_ctx); - return EGL_NO_CONTEXT; + return NULL; } - xdri_ctx->driContext.mode = xdri_config->mode; + /* fill in the required field */ + xdri_ctx->dummy_gc->driContext = xdri_ctx->driContext; - return _eglGetContextHandle(&xdri_ctx->Base); + return &xdri_ctx->Base; +} + + +static EGLBoolean +xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_context *xdri_ctx = lookup_context(ctx); + + if (!_eglIsContextBound(ctx)) { + xdri_ctx->driContext->destroyContext(xdri_ctx->driContext, + xdri_dpy->psc, xdri_dpy->dpy); + free(xdri_ctx->dummy_gc); + free(xdri_ctx); + } + + return EGL_TRUE; } @@ -802,25 +403,32 @@ xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, * Called via eglMakeCurrent(), drv->API.MakeCurrent(). */ static EGLBoolean -xdri_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, - EGLSurface r, EGLContext context) +xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, + _EGLSurface *r, _EGLContext *context) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); struct xdri_egl_context *xdri_ctx = lookup_context(context); - struct xdri_egl_surface *xdri_draw = lookup_surface(d); - struct xdri_egl_surface *xdri_read = lookup_surface(r); - __DRIid draw = xdri_draw ? xdri_draw->driDrawable : 0; - __DRIid read = xdri_read ? xdri_read->driDrawable : 0; - int scrn = DefaultScreen(disp->Xdpy); + struct xdri_egl_surface *draw = lookup_surface(d); + struct xdri_egl_surface *read = lookup_surface(r); if (!_eglMakeCurrent(drv, dpy, d, r, context)) return EGL_FALSE; + /* the symbol is defined in libGL.so */ + _glapi_check_multithread(); - if (xdri_ctx && - !xdri_ctx->driContext.bindContext(disp->Xdpy, scrn, draw, read, - &xdri_ctx->driContext)) { - return EGL_FALSE; + if (xdri_ctx) { + if (!xdri_ctx->driContext->bindContext(xdri_ctx->driContext, + draw->driDrawable, + read->driDrawable)) { + return EGL_FALSE; + } + } + else { + _EGLContext *old = _eglGetCurrentContext(); + if (old) { + xdri_ctx = lookup_context(old); + xdri_ctx->driContext->unbindContext(xdri_ctx->driContext); + } } return EGL_TRUE; @@ -830,309 +438,106 @@ xdri_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, /** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ -static EGLSurface -xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +static _EGLSurface * +xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_config *xdri_config = lookup_config(conf); struct xdri_egl_surface *xdri_surf; - int scrn = DefaultScreen(disp->Xdpy); uint width, height; xdri_surf = CALLOC_STRUCT(xdri_egl_surface); - if (!xdri_surf) - return EGL_NO_SURFACE; + if (!xdri_surf) { + _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); + return NULL; + } - if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_WINDOW_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_WINDOW_BIT, + &xdri_config->Base, attrib_list)) { free(xdri_surf); - return EGL_FALSE; + return NULL; } - if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) { + xdri_surf->driDrawable = + xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc, + (XID) window, + (GLXDrawable) window, + xdri_config->mode); + if (!xdri_surf->driDrawable) { free(xdri_surf); - return EGL_FALSE; + return NULL; } - xdri_surf->driDrawable = window; + xdri_surf->drawable = (Drawable) window; - _eglSaveSurface(&xdri_surf->Base); - - get_drawable_size(disp->Xdpy, window, &width, &height); + get_drawable_size(xdri_dpy->dpy, window, &width, &height); xdri_surf->Base.Width = width; xdri_surf->Base.Height = height; - _eglLog(_EGL_DEBUG, - "XDRI: CreateWindowSurface win 0x%x handle %d hDrawable %d", - (int) window, _eglGetSurfaceHandle(&xdri_surf->Base), - (int) xdri_surf->hDrawable); - - return _eglGetSurfaceHandle(&xdri_surf->Base); + return &xdri_surf->Base; } /** * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface(). */ -static EGLSurface -xdri_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +static _EGLSurface * +xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); - struct xdri_egl_surface *xdri_surf; - struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config); - int scrn = DefaultScreen(disp->Xdpy); - Window window; - - xdri_surf = CALLOC_STRUCT(xdri_egl_surface); - if (!xdri_surf) - return EGL_NO_SURFACE; - - if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_PBUFFER_BIT, - config, attrib_list)) { - free(xdri_surf); - return EGL_FALSE; - } - - /* Create a dummy X window */ - { - Window root = RootWindow(disp->Xdpy, scrn); - XSetWindowAttributes attr; - XVisualInfo *visInfo, visTemplate; - unsigned mask; - int nvis; - - visTemplate.visualid = xdri_config->mode->visualID; - visInfo = XGetVisualInfo(disp->Xdpy, VisualIDMask, &visTemplate, &nvis); - if (!visInfo) { - return EGL_NO_SURFACE; - } - - attr.background_pixel = 0; - attr.border_pixel = 0; - attr.colormap = XCreateColormap(disp->Xdpy, root, - visInfo->visual, AllocNone); - attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; - mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - - window = XCreateWindow(disp->Xdpy, root, 0, 0, - xdri_surf->Base.Width, xdri_surf->Base.Height, - 0, visInfo->depth, InputOutput, - visInfo->visual, mask, &attr); - - /*XMapWindow(disp->Xdpy, window);*/ - XFree(visInfo); - - /* set hints and properties */ - /* - sizehints.width = xdri_surf->Base.Width; - sizehints.height = xdri_surf->Base.Height; - sizehints.flags = USPosition; - XSetNormalHints(disp->Xdpy, window, &sizehints); - */ - } - - if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) { - free(xdri_surf); - return EGL_FALSE; - } - - xdri_surf->driDrawable = window; - - _eglSaveSurface(&xdri_surf->Base); - - _eglLog(_EGL_DEBUG, - "XDRI: CreatePbufferSurface handle %d hDrawable %d", - _eglGetSurfaceHandle(&xdri_surf->Base), - (int) xdri_surf->hDrawable); - - return _eglGetSurfaceHandle(&xdri_surf->Base); + return NULL; } static EGLBoolean -xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +xdri_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) { struct xdri_egl_surface *xdri_surf = lookup_surface(surface); - if (xdri_surf) { - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface); - if (xdri_surf->Base.IsBound) { - xdri_surf->Base.DeletePending = EGL_TRUE; - } - else { - /* - st_unreference_framebuffer(surf->Framebuffer); - */ - free(xdri_surf); - } - return EGL_TRUE; - } - else { - _eglError(EGL_BAD_SURFACE, "eglDestroySurface"); - return EGL_FALSE; + + if (!_eglIsSurfaceBound(&xdri_surf->Base)) { + xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable); + free(xdri_surf); } + + return EGL_TRUE; } static EGLBoolean -xdri_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, +xdri_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer) { - typedef int (*bind_teximage)(__DRInativeDisplay *dpy, - __DRIid surface, __DRIscreen *psc, - int buffer, int target, int format, - int level, int mipmap); - - bind_teximage egl_dri_bind_teximage; - - _EGLDisplay *disp = _eglLookupDisplay(dpy); - - struct xdri_egl_context *xdri_ctx = current_context(); - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - struct xdri_egl_surface *xdri_surf = lookup_surface(surface); - - __DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0; - - __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs; - __DRIscreen *psc = &scrnConf->driScreen; - - /* this call just does error checking */ - if (!_eglBindTexImage(drv, dpy, surface, buffer)) { - return EGL_FALSE; - } - - egl_dri_bind_teximage = - (bind_teximage) dlsym(NULL, "egl_dri_bind_teximage"); - if (egl_dri_bind_teximage) { - return egl_dri_bind_teximage(disp->Xdpy, dri_surf, psc, - buffer, - xdri_surf->Base.TextureTarget, - xdri_surf->Base.TextureFormat, - xdri_surf->Base.MipmapLevel, - xdri_surf->Base.MipmapTexture); - } - else { - /* fallback path based on glCopyTexImage() */ - /* Get/save currently bound 2D texobj name */ - glGetIntegerv_t glGetIntegerv_func = - (glGetIntegerv_t) dlsym(NULL, "glGetIntegerv"); - GLint curTexObj = 0; - if (glGetIntegerv_func) { - (*glGetIntegerv_func)(GL_TEXTURE_BINDING_2D, &curTexObj); - } - xdri_ctx->bound_tex_object = curTexObj; - } - return EGL_FALSE; } static EGLBoolean -xdri_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, +xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer) { - typedef int (*release_teximage)(__DRInativeDisplay *dpy, - __DRIid surface, __DRIscreen *psc, - int buffer, int target, int format, - int level, int mipmap); - release_teximage egl_dri_release_teximage; - - _EGLDisplay *disp = _eglLookupDisplay(dpy); - - struct xdri_egl_context *xdri_ctx = current_context(); - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - struct xdri_egl_surface *xdri_surf = lookup_surface(surface); - - __DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0; - - __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs; - __DRIscreen *psc = &scrnConf->driScreen; - - /* this call just does error checking */ - if (!_eglReleaseTexImage(drv, dpy, surface, buffer)) { - return EGL_FALSE; - } - - egl_dri_release_teximage = - (release_teximage) dlsym(NULL, "egl_dri_release_teximage"); - if (egl_dri_release_teximage) { - return egl_dri_release_teximage(disp->Xdpy, dri_surf, psc, - buffer, - xdri_surf->Base.TextureTarget, - xdri_surf->Base.TextureFormat, - xdri_surf->Base.MipmapLevel, - xdri_surf->Base.MipmapTexture); - } - else { - /* fallback path based on glCopyTexImage() */ - glGetIntegerv_t glGetIntegerv_func = - (glGetIntegerv_t) dlsym(NULL, "glGetIntegerv"); - glBindTexture_t glBindTexture_func = - (glBindTexture_t) dlsym(NULL, "glBindTexture"); - glCopyTexImage2D_t glCopyTexImage2D_func = - (glCopyTexImage2D_t) dlsym(NULL, "glCopyTexImage2D"); - GLint curTexObj; - GLenum intFormat; - GLint level, width, height; - - if (xdri_surf->Base.TextureFormat == EGL_TEXTURE_RGBA) - intFormat = GL_RGBA; - else - intFormat = GL_RGB; - level = xdri_surf->Base.MipmapLevel; - width = xdri_surf->Base.Width >> level; - height = xdri_surf->Base.Height >> level; - - if (width > 0 && height > 0 && - glGetIntegerv_func && glBindTexture_func && glCopyTexImage2D_func) { - glGetIntegerv_func(GL_TEXTURE_BINDING_2D, &curTexObj); - /* restore texobj from time of eglBindTexImage() call */ - if (curTexObj != xdri_ctx->bound_tex_object) - glBindTexture_func(GL_TEXTURE_2D, xdri_ctx->bound_tex_object); - /* copy pbuffer image to texture */ - glCopyTexImage2D_func(GL_TEXTURE_2D, - level, - intFormat, - 0, 0, width, height, 0); - /* restore current texture */ - if (curTexObj != xdri_ctx->bound_tex_object) - glBindTexture_func(GL_TEXTURE_2D, curTexObj); - } - xdri_ctx->bound_tex_object = -1; - } - return EGL_FALSE; } static EGLBoolean -xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_surface *xdri_surf = lookup_surface(draw); - _eglLog(_EGL_DEBUG, "XDRI: EGL SwapBuffers"); + xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable); - /* error checking step: */ - if (!_eglSwapBuffers(drv, dpy, draw)) - return EGL_FALSE; + return EGL_TRUE; +} - { - struct xdri_egl_surface *xdri_surf = lookup_surface(draw); - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs; - __DRIscreen *psc = &scrnConf->driScreen; - __DRIdrawable * const pdraw = psc->getDrawable(disp->Xdpy, - xdri_surf->driDrawable, - psc->private); - - if (pdraw) - pdraw->swapBuffers(disp->Xdpy, pdraw->private); - else - _eglLog(_EGL_WARNING, "pdraw is null in SwapBuffers"); - } - return EGL_TRUE; +static void +xdri_Unload(_EGLDriver *drv) +{ + struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); + free(xdri_drv); } @@ -1141,15 +546,12 @@ xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) * Create a new _EGLDriver object and init its dispatch table. */ _EGLDriver * -_eglMain(_EGLDisplay *disp, const char *args) +_eglMain(const char *args) { struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver); if (!xdri_drv) return NULL; - /* Tell libGL to prefer the EGL drivers over regular DRI drivers */ - __glXPreferEGL(1); - _eglInitDriverFallbacks(&xdri_drv->Base); xdri_drv->Base.API.Initialize = xdri_eglInitialize; xdri_drv->Base.API.Terminate = xdri_eglTerminate; @@ -1157,6 +559,7 @@ _eglMain(_EGLDisplay *disp, const char *args) xdri_drv->Base.API.GetProcAddress = xdri_eglGetProcAddress; xdri_drv->Base.API.CreateContext = xdri_eglCreateContext; + xdri_drv->Base.API.DestroyContext = xdri_eglDestroyContext; xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent; xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface; xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface; @@ -1165,13 +568,8 @@ _eglMain(_EGLDisplay *disp, const char *args) xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage; xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers; - xdri_drv->Base.ClientAPIsMask = (EGL_OPENGL_BIT | - EGL_OPENGL_ES_BIT | - EGL_OPENGL_ES2_BIT | - EGL_OPENVG_BIT); xdri_drv->Base.Name = "X/DRI"; - - _eglLog(_EGL_DEBUG, "XDRI: main(%s)", args); + xdri_drv->Base.Unload = xdri_Unload; return &xdri_drv->Base; } |