X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglx%2Fx11%2Fdri_glx.c;h=44724d2c7d0ffce3ed21a356afca549eb4c3cc36;hb=b4866f8a5229d4769a49b4c54a1675a61497d206;hp=08e419c1efb1ea825761a39a48447881c528b1e9;hpb=9110425c72e45f618131b559eba883fd6c5536b4;p=mesa.git diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index 08e419c1efb..44724d2c7d0 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -34,29 +34,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING -#include -#include -#include -#include -#include "glheader.h" +#include +#include +#include #include "glxclient.h" +#include "glcontextmodes.h" #include "xf86dri.h" #include "sarea.h" -#include #include #include -#include -#include "glcontextmodes.h" #include #include "xf86drm.h" - - -#ifndef RTLD_NOW -#define RTLD_NOW 0 -#endif -#ifndef RTLD_GLOBAL -#define RTLD_GLOBAL 0 -#endif +#include "dri_common.h" typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; @@ -74,134 +63,17 @@ struct __GLXDRIdisplayPrivateRec { struct __GLXDRIcontextPrivateRec { __GLXDRIcontext base; - __DRIcontext driContext; + __DRIcontext *driContext; XID hwContextID; + __GLXscreenConfigs *psc; }; -#ifndef DEFAULT_DRIVER_DIR -/* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */ -#define DEFAULT_DRIVER_DIR "/usr/X11R6/lib/modules/dri" -#endif - -static void InfoMessageF(const char *f, ...) -{ - va_list args; - const char *env; - - if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) { - fprintf(stderr, "libGL: "); - va_start(args, f); - vfprintf(stderr, f, args); - va_end(args); - } -} - -/** - * Print error to stderr, unless LIBGL_DEBUG=="quiet". - */ -static void ErrorMessageF(const char *f, ...) -{ - va_list args; - const char *env; - - if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) { - fprintf(stderr, "libGL error: "); - va_start(args, f); - vfprintf(stderr, f, args); - va_end(args); - } -} - - -/** - * Versioned name of the expected \c __driCreateNewScreen function. - * - * The version of the last incompatible loader/driver inteface change is - * appended to the name of the \c __driCreateNewScreen function. This - * prevents loaders from trying to load drivers that are too old. - */ -static const char createNewScreenName[] = __DRI_CREATE_NEW_SCREEN_STRING; - - -/** - * Try to \c dlopen the named driver. - * - * This function adds the "_dri.so" suffix to the driver name and searches the - * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in - * order to find the driver. - * - * \param driverName - a name like "tdfx", "i810", "mga", etc. - * - * \returns - * A handle from \c dlopen, or \c NULL if driver file not found. - */ -static void *OpenDriver(const char *driverName) -{ - void *glhandle, *handle; - const char *libPaths, *p, *next; - char realDriverName[200]; - int len; - - /* Attempt to make sure libGL symbols will be visible to the driver */ - glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL); - - libPaths = NULL; - if (geteuid() == getuid()) { - /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ - libPaths = getenv("LIBGL_DRIVERS_PATH"); - if (!libPaths) - libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */ - } - if (libPaths == NULL) - libPaths = DEFAULT_DRIVER_DIR; - - handle = NULL; - for (p = libPaths; *p; p = next) { - next = strchr(p, ':'); - if (next == NULL) { - len = strlen(p); - next = p + len; - } else { - len = next - p; - next++; - } - -#ifdef GLX_USE_TLS - snprintf(realDriverName, sizeof realDriverName, - "%.*s/tls/%s_dri.so", len, p, driverName); - InfoMessageF("OpenDriver: trying %s\n", realDriverName); - handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); -#endif - - if ( handle == NULL ) { - snprintf(realDriverName, sizeof realDriverName, - "%.*s/%s_dri.so", len, p, driverName); - InfoMessageF("OpenDriver: trying %s\n", realDriverName); - handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); - } - - if ( handle != NULL ) - break; - else - ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror()); - } - - if (!handle) - ErrorMessageF("unable to load driver: %s_dri.so\n", driverName); - - if (glhandle) - dlclose(glhandle); - - return handle; -} - - /* * Given a display pointer and screen number, determine the name of * the DRI driver for the screen. (I.e. "r128", "tdfx", etc). * Return True for success, False for failure. */ -static Bool GetDriverName(Display *dpy, int scrNum, char **driverName) +static Bool driGetDriverName(Display *dpy, int scrNum, char **driverName) { int directCapable; Bool b; @@ -231,25 +103,6 @@ static Bool GetDriverName(Display *dpy, int scrNum, char **driverName) return True; } - -/* - * Given a display pointer and screen number, return a __DRIdriver handle. - * Return NULL if anything goes wrong. - */ -static void *driGetDriver(Display *dpy, int scrNum) -{ - char *driverName; - void *ret; - - if (GetDriverName(dpy, scrNum, &driverName)) { - ret = OpenDriver(driverName); - if (driverName) - Xfree(driverName); - return ret; - } - return NULL; -} - /* * Exported function for querying the DRI driver for a given screen. * @@ -259,7 +112,7 @@ static void *driGetDriver(Display *dpy, int scrNum) PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) { static char ret[32]; char *driverName; - if (GetDriverName(dpy, scrNum, &driverName)) { + if (driGetDriverName(dpy, scrNum, &driverName)) { int len; if (!driverName) return NULL; @@ -273,7 +126,6 @@ PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) { return NULL; } - /* * Exported function for obtaining a driver's option list (UTF-8 encoded XML). * @@ -285,68 +137,17 @@ PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) { * * Note: The driver remains opened after this function returns. */ -PUBLIC const char *glXGetDriverConfig (const char *driverName) { - void *handle = OpenDriver (driverName); +PUBLIC const char *glXGetDriverConfig (const char *driverName) +{ + void *handle = driOpenDriver (driverName); if (handle) return dlsym (handle, "__driConfigOptions"); else return NULL; } -static void -filter_modes( __GLcontextModes ** server_modes, - const __GLcontextModes * driver_modes ) -{ - __GLcontextModes * m; - __GLcontextModes ** prev_next; - const __GLcontextModes * check; - - if (driver_modes == NULL) { - fprintf(stderr, "libGL warning: 3D driver returned no fbconfigs.\n"); - return; - } - - /* For each mode in server_modes, check to see if a matching mode exists - * in driver_modes. If not, then the mode is not available. - */ - - prev_next = server_modes; - for ( m = *prev_next ; m != NULL ; m = *prev_next ) { - GLboolean do_delete = GL_TRUE; - - for ( check = driver_modes ; check != NULL ; check = check->next ) { - if ( _gl_context_modes_are_same( m, check ) ) { - do_delete = GL_FALSE; - break; - } - } - - /* The 3D has to support all the modes that match the GLX visuals - * sent from the X server. - */ - if ( do_delete && (m->visualID != 0) ) { - do_delete = GL_FALSE; - - /* don't warn for this visual (Novell #247471 / X.Org #6689) */ - if (m->visualRating != GLX_NON_CONFORMANT_CONFIG) { - fprintf(stderr, "libGL warning: 3D driver claims to not " - "support visual 0x%02x\n", m->visualID); - } - } - - if ( do_delete ) { - *prev_next = m->next; - - m->next = NULL; - _gl_context_modes_destroy( m ); - } - else { - prev_next = & m->next; - } - } -} - #ifdef XDAMAGE_1_1_INTERFACE + static GLboolean has_damage_post(Display *dpy) { static GLboolean inited = GL_FALSE; @@ -367,20 +168,18 @@ static GLboolean has_damage_post(Display *dpy) return has_damage; } -#endif /* XDAMAGE_1_1_INTERFACE */ static void __glXReportDamage(__DRIdrawable *driDraw, int x, int y, drm_clip_rect_t *rects, int num_rects, - GLboolean front_buffer) + GLboolean front_buffer, + void *loaderPrivate) { -#ifdef XDAMAGE_1_1_INTERFACE XRectangle *xrects; XserverRegion region; int i; int x_off, y_off; - __GLXdrawable *glxDraw = - containerOf(driDraw, __GLXdrawable, driDrawable); + __GLXDRIdrawable *glxDraw = loaderPrivate; __GLXscreenConfigs *psc = glxDraw->psc; Display *dpy = psc->dpy; Drawable drawable; @@ -395,7 +194,7 @@ static void __glXReportDamage(__DRIdrawable *driDraw, } else{ x_off = 0; y_off = 0; - drawable = glxDraw->drawable; + drawable = glxDraw->xDrawable; } xrects = malloc(sizeof(XRectangle) * num_rects); @@ -412,19 +211,25 @@ static void __glXReportDamage(__DRIdrawable *driDraw, free(xrects); XDamageAdd(dpy, drawable, region); XFixesDestroyRegion(dpy, region); -#endif } +static const __DRIdamageExtension damageExtension = { + { __DRI_DAMAGE, __DRI_DAMAGE_VERSION }, + __glXReportDamage, +}; + +#endif + static GLboolean __glXDRIGetDrawableInfo(__DRIdrawable *drawable, unsigned int *index, unsigned int *stamp, int *X, int *Y, int *W, int *H, int *numClipRects, drm_clip_rect_t ** pClipRects, int *backX, int *backY, - int *numBackClipRects, drm_clip_rect_t **pBackClipRects) + int *numBackClipRects, drm_clip_rect_t **pBackClipRects, + void *loaderPrivate) { - __GLXDRIdrawable *glxDraw = - containerOf(drawable, __GLXDRIdrawable, driDrawable); + __GLXDRIdrawable *glxDraw = loaderPrivate; __GLXscreenConfigs *psc = glxDraw->psc; Display *dpy = psc->dpy; @@ -435,40 +240,21 @@ __glXDRIGetDrawableInfo(__DRIdrawable *drawable, numBackClipRects, pBackClipRects); } - -/** - * Table of functions exported by the loader to the driver. - */ -static const __DRIcontextModesExtension contextModesExtension = { - { __DRI_CONTEXT_MODES, __DRI_CONTEXT_MODES_VERSION }, - _gl_context_modes_create, - _gl_context_modes_destroy, -}; - -static const __DRIsystemTimeExtension systemTimeExtension = { - { __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION }, - __glXGetUST, - __driGetMscRateOML, -}; - static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = { { __DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION }, __glXDRIGetDrawableInfo }; -static const __DRIdamageExtension damageExtension = { - { __DRI_DAMAGE, __DRI_DAMAGE_VERSION }, - __glXReportDamage, -}; - static const __DRIextension *loader_extensions[] = { - &contextModesExtension.base, &systemTimeExtension.base, &getDrawableInfoExtension.base, +#ifdef XDAMAGE_1_1_INTERFACE &damageExtension.base, +#endif NULL }; +#ifndef GLX_USE_APPLEGL /** * Perform the required libGL-side initialization and call the client-side @@ -482,18 +268,12 @@ static const __DRIextension *loader_extensions[] = { * \c __driCreateNewScreen function. * \returns A pointer to the \c __DRIscreenPrivate structure returned by * the client-side driver on success, or \c NULL on failure. - * - * \todo This function needs to be modified to remove context-modes from the - * list stored in the \c __GLXscreenConfigsRec to match the list - * returned by the client-side driver. */ static void * CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, - __GLXDRIdisplayPrivate * driDpy, - PFNCREATENEWSCREENFUNC createNewScreen) + __GLXDRIdisplayPrivate * driDpy) { void *psp = NULL; -#ifndef GLX_USE_APPLEGL drm_handle_t hSAREA; drmAddress pSAREA = MAP_FAILED; char *BusID; @@ -503,195 +283,187 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, __DRIframebuffer framebuffer; int fd = -1; int status; - const char * err_msg; - const char * err_extra; + drm_magic_t magic; + drmVersionPtr version; + int newlyopened; + char *driverName; + drm_handle_t hFB; + int junk; + const __DRIconfig **driver_configs; + + /* DRI protocol version. */ dri_version.major = driDpy->driMajor; dri_version.minor = driDpy->driMinor; dri_version.patch = driDpy->driPatch; - - err_msg = "XF86DRIOpenConnection"; - err_extra = NULL; - framebuffer.base = MAP_FAILED; framebuffer.dev_priv = NULL; - if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { - int newlyopened; - fd = drmOpenOnce(NULL,BusID, &newlyopened); - Xfree(BusID); /* No longer needed */ - - err_msg = "open DRM"; - err_extra = strerror( -fd ); - - if (fd >= 0) { - drm_magic_t magic; - - err_msg = "drmGetMagic"; - err_extra = NULL; - - if (!drmGetMagic(fd, &magic)) { - drmVersionPtr version = drmGetVersion(fd); - if (version) { - drm_version.major = version->version_major; - drm_version.minor = version->version_minor; - drm_version.patch = version->version_patchlevel; - drmFreeVersion(version); - } - else { - drm_version.major = -1; - drm_version.minor = -1; - drm_version.patch = -1; - } - - err_msg = "XF86DRIAuthConnection"; - if (!newlyopened || XF86DRIAuthConnection(dpy, scrn, magic)) { - char *driverName; - - /* - * Get device name (like "tdfx") and the ddx version - * numbers. We'll check the version in each DRI driver's - * "createNewScreen" function. - */ - err_msg = "XF86DRIGetClientDriverName"; - if (XF86DRIGetClientDriverName(dpy, scrn, - &ddx_version.major, - &ddx_version.minor, - &ddx_version.patch, - &driverName)) { - drm_handle_t hFB; - int junk; - - /* No longer needed. */ - Xfree( driverName ); - - - /* - * Get device-specific info. pDevPriv will point to a struct - * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) - * that has information about the screen size, depth, pitch, - * ancilliary buffers, DRM mmap handles, etc. - */ - err_msg = "XF86DRIGetDeviceInfo"; - if (XF86DRIGetDeviceInfo(dpy, scrn, - &hFB, - &junk, - &framebuffer.size, - &framebuffer.stride, - &framebuffer.dev_priv_size, - &framebuffer.dev_priv)) { - framebuffer.width = DisplayWidth(dpy, scrn); - framebuffer.height = DisplayHeight(dpy, scrn); - - /* - * Map the framebuffer region. - */ - status = drmMap(fd, hFB, framebuffer.size, - (drmAddressPtr)&framebuffer.base); - - err_msg = "drmMap of framebuffer"; - err_extra = strerror( -status ); - - if ( status == 0 ) { - /* - * Map the SAREA region. Further mmap regions - * may be setup in each DRI driver's - * "createNewScreen" function. - */ - status = drmMap(fd, hSAREA, SAREA_MAX, - &pSAREA); - - err_msg = "drmMap of sarea"; - err_extra = strerror( -status ); - - if ( status == 0 ) { - __GLcontextModes * driver_modes = NULL; - - err_msg = "InitDriver"; - err_extra = NULL; - psp = (*createNewScreen)(scrn, - &psc->__driScreen, - & ddx_version, - & dri_version, - & drm_version, - & framebuffer, - pSAREA, - fd, - loader_extensions, - & driver_modes ); - - filter_modes(&psc->configs, driver_modes); - filter_modes(&psc->visuals, driver_modes); - _gl_context_modes_destroy(driver_modes); - } - } - } - } - } - } - } + if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { + ErrorMessageF("XF86DRIOpenConnection failed\n"); + goto handle_error; } - if ( psp == NULL ) { - if ( pSAREA != MAP_FAILED ) { - (void)drmUnmap(pSAREA, SAREA_MAX); - } + fd = drmOpenOnce(NULL, BusID, &newlyopened); - if ( framebuffer.base != MAP_FAILED ) { - (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size); - } + Xfree(BusID); /* No longer needed */ - if ( framebuffer.dev_priv != NULL ) { - Xfree(framebuffer.dev_priv); - } + if (fd < 0) { + ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd)); + goto handle_error; + } - if ( fd >= 0 ) { - (void)drmCloseOnce(fd); - } + if (drmGetMagic(fd, &magic)) { + ErrorMessageF("drmGetMagic failed\n"); + goto handle_error; + } - (void)XF86DRICloseConnection(dpy, scrn); + version = drmGetVersion(fd); + if (version) { + drm_version.major = version->version_major; + drm_version.minor = version->version_minor; + drm_version.patch = version->version_patchlevel; + drmFreeVersion(version); + } + else { + drm_version.major = -1; + drm_version.minor = -1; + drm_version.patch = -1; + } - if ( err_extra != NULL ) { - fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg, - err_extra); - } - else { - fprintf(stderr, "libGL error: %s failed\n", err_msg ); - } + if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) { + ErrorMessageF("XF86DRIAuthConnection failed\n"); + goto handle_error; + } - fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n"); + /* Get device name (like "tdfx") and the ddx version numbers. + * We'll check the version in each DRI driver's "createNewScreen" + * function. */ + if (!XF86DRIGetClientDriverName(dpy, scrn, + &ddx_version.major, + &ddx_version.minor, + &ddx_version.patch, + &driverName)) { + ErrorMessageF("XF86DRIGetClientDriverName failed\n"); + goto handle_error; + } + + Xfree(driverName); /* No longer needed. */ + + /* + * Get device-specific info. pDevPriv will point to a struct + * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that + * has information about the screen size, depth, pitch, ancilliary + * buffers, DRM mmap handles, etc. + */ + if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk, + &framebuffer.size, &framebuffer.stride, + &framebuffer.dev_priv_size, &framebuffer.dev_priv)) { + ErrorMessageF("XF86DRIGetDeviceInfo failed"); + goto handle_error; + } + + framebuffer.width = DisplayWidth(dpy, scrn); + framebuffer.height = DisplayHeight(dpy, scrn); + + /* Map the framebuffer region. */ + status = drmMap(fd, hFB, framebuffer.size, + (drmAddressPtr)&framebuffer.base); + if (status != 0) { + ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status)); + goto handle_error; + } + + /* Map the SAREA region. Further mmap regions may be setup in + * each DRI driver's "createNewScreen" function. + */ + status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); + if (status != 0) { + ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status)); + goto handle_error; + } + + psp = (*psc->legacy->createNewScreen)(scrn, + &ddx_version, + &dri_version, + &drm_version, + &framebuffer, + pSAREA, + fd, + loader_extensions, + &driver_configs, + psc); + + if (psp == NULL) { + ErrorMessageF("Calling driver entry point failed"); + goto handle_error; } -#endif /* !GLX_USE_APPLEGL */ + + psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); + psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); return psp; + + handle_error: + if (pSAREA != MAP_FAILED) + drmUnmap(pSAREA, SAREA_MAX); + + if (framebuffer.base != MAP_FAILED) + drmUnmap((drmAddress)framebuffer.base, framebuffer.size); + + if (framebuffer.dev_priv != NULL) + Xfree(framebuffer.dev_priv); + + if (fd >= 0) + drmCloseOnce(fd); + + XF86DRICloseConnection(dpy, scrn); + + ErrorMessageF("reverting to software direct rendering\n"); + + return NULL; } +#else /* !GLX_USE_APPLEGL */ + +static void * +CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, + __GLXDRIdisplayPrivate * driDpy) +{ + return NULL; +} + +#endif /* !GLX_USE_APPLEGL */ + static void driDestroyContext(__GLXDRIcontext *context, __GLXscreenConfigs *psc, Display *dpy) { __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - (*pcp->driContext.destroyContext)(&pcp->driContext); + (*psc->core->destroyContext)(pcp->driContext); XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); + Xfree(pcp); } static Bool driBindContext(__GLXDRIcontext *context, __GLXDRIdrawable *draw, __GLXDRIdrawable *read) { __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - return (*pcp->driContext.bindContext)(&pcp->driContext, - &draw->driDrawable, - &read->driDrawable); + return (*core->bindContext)(pcp->driContext, + draw->driDrawable, + read->driDrawable); } static void driUnbindContext(__GLXDRIcontext *context) { __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - (*pcp->driContext.unbindContext)(&pcp->driContext); + (*core->unbindContext)(pcp->driContext); } static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc, @@ -702,62 +474,70 @@ static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc, __GLXDRIcontextPrivate *pcp, *pcp_shared; drm_context_t hwContext; __DRIcontext *shared = NULL; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; - if (psc && psc->driScreen) { - if (shareList) { - pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; - shared = &pcp_shared->driContext; - } - - pcp = Xmalloc(sizeof *pcp); - if (pcp == NULL) - return NULL; + if (!psc || !psc->driScreen) + return NULL; - if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr, - mode->visualID, - &pcp->hwContextID, &hwContext)) { - Xfree(pcp); - return NULL; - } + if (shareList) { + pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; + shared = pcp_shared->driContext; + } - pcp->driContext.private = - (*psc->__driScreen.createNewContext)(&psc->__driScreen, - mode, renderType, - shared, - hwContext, - &pcp->driContext); - if (pcp->driContext.private == NULL) { - XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); - Xfree(pcp); - return NULL; - } + pcp = Xmalloc(sizeof *pcp); + if (pcp == NULL) + return NULL; - pcp->base.destroyContext = driDestroyContext; - pcp->base.bindContext = driBindContext; - pcp->base.unbindContext = driUnbindContext; + pcp->psc = psc; + if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr, + mode->visualID, + &pcp->hwContextID, &hwContext)) { + Xfree(pcp); + return NULL; + } - return &pcp->base; + pcp->driContext = + (*psc->legacy->createNewContext)(psc->__driScreen, + config->driConfig, + renderType, + shared, + hwContext, + pcp); + if (pcp->driContext == NULL) { + XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); + Xfree(pcp); + return NULL; } - return NULL; + pcp->base.destroyContext = driDestroyContext; + pcp->base.bindContext = driBindContext; + pcp->base.unbindContext = driUnbindContext; + + return &pcp->base; } static void driDestroyDrawable(__GLXDRIdrawable *pdraw) { __GLXscreenConfigs *psc = pdraw->psc; - (*pdraw->driDrawable.destroyDrawable)(&pdraw->driDrawable); + (*psc->core->destroyDrawable)(pdraw->driDrawable); XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable); Xfree(pdraw); } static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc, + XID xDrawable, GLXDrawable drawable, - GLXContext gc) + const __GLcontextModes *modes) { __GLXDRIdrawable *pdraw; drm_drawable_t hwDrawable; void *empty_attribute_list = NULL; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; + + /* Old dri can't handle GLX 1.3+ drawable constructors. */ + if (xDrawable != drawable) + return NULL; pdraw = Xmalloc(sizeof(*pdraw)); if (!pdraw) @@ -770,16 +550,15 @@ static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc, return NULL; /* Create a new drawable */ - pdraw->driDrawable.private = - (*psc->__driScreen.createNewDrawable)(&psc->__driScreen, - gc->mode, - &pdraw->driDrawable, - hwDrawable, - GLX_WINDOW_BIT, - 0, - empty_attribute_list); - - if (!pdraw->driDrawable.private) { + pdraw->driDrawable = + (*psc->legacy->createNewDrawable)(psc->__driScreen, + config->driConfig, + hwDrawable, + GLX_WINDOW_BIT, + empty_attribute_list, + pdraw); + + if (!pdraw->driDrawable) { XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable); Xfree(pdraw); return NULL; @@ -790,12 +569,24 @@ static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc, return pdraw; } +static void driSwapBuffers(__GLXDRIdrawable *pdraw) +{ + (*pdraw->psc->core->swapBuffers)(pdraw->driDrawable); +} + +static void driCopySubBuffer(__GLXDRIdrawable *pdraw, + int x, int y, int width, int height) +{ + (*pdraw->psc->driCopySubBuffer->copySubBuffer)(pdraw->driDrawable, + x, y, width, height); +} + static void driDestroyScreen(__GLXscreenConfigs *psc) { /* Free the direct rendering per screen data */ - if (psc->__driScreen.private) - (*psc->__driScreen.destroyScreen)(&psc->__driScreen); - psc->__driScreen.private = NULL; + if (psc->__driScreen) + (*psc->core->destroyScreen)(psc->__driScreen); + psc->__driScreen = NULL; if (psc->driver) dlclose(psc->driver); } @@ -803,9 +594,11 @@ static void driDestroyScreen(__GLXscreenConfigs *psc) static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen, __GLXdisplayPrivate *priv) { - PFNCREATENEWSCREENFUNC createNewScreen; __GLXDRIdisplayPrivate *pdp; __GLXDRIscreen *psp; + const __DRIextension **extensions; + char *driverName; + int i; psp = Xmalloc(sizeof *psp); if (psp == NULL) @@ -814,20 +607,54 @@ static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen, /* Initialize per screen dynamic client GLX extensions */ psc->ext_list_first_time = GL_TRUE; - psc->driver = driGetDriver(priv->dpy, screen); - createNewScreen = dlsym(psc->driver, createNewScreenName); - if (createNewScreenName == NULL) + if (!driGetDriverName(priv->dpy, screen, &driverName)) { + Xfree(psp); + return NULL; + } + + psc->driver = driOpenDriver(driverName); + Xfree(driverName); + if (psc->driver == NULL) { + Xfree(psp); + return NULL; + } + + extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); + Xfree(psp); return NULL; + } + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_CORE) == 0) + psc->core = (__DRIcoreExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0) + psc->legacy = (__DRIlegacyExtension *) extensions[i]; + } + + if (psc->core == NULL || psc->legacy == NULL) { + Xfree(psp); + return NULL; + } + pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay; - psc->__driScreen.private = - CallCreateNewScreen(psc->dpy, screen, psc, pdp, createNewScreen); - if (psc->__driScreen.private != NULL) - __glXScrEnableDRIExtension(psc); + psc->__driScreen = + CallCreateNewScreen(psc->dpy, screen, psc, pdp); + if (psc->__driScreen == NULL) { + dlclose(psc->driver); + Xfree(psp); + return NULL; + } + + driBindExtensions(psc, 0); + if (psc->driCopySubBuffer) + psp->copySubBuffer = driCopySubBuffer; psp->destroyScreen = driDestroyScreen; psp->createContext = driCreateContext; psp->createDrawable = driCreateDrawable; + psp->swapBuffers = driSwapBuffers; return psp; }