diff options
Diffstat (limited to 'src/glx/x11/glxext.c')
-rw-r--r-- | src/glx/x11/glxext.c | 452 |
1 files changed, 239 insertions, 213 deletions
diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c index 8fe10338a80..4fcf6e5df07 100644 --- a/src/glx/x11/glxext.c +++ b/src/glx/x11/glxext.c @@ -61,6 +61,7 @@ #include <inttypes.h> #include <sys/mman.h> #include "xf86dri.h" +#include "xf86drm.h" #include "sarea.h" #include "dri_glx.h" #endif @@ -108,10 +109,6 @@ static int _mesa_sparc_needs_init = 1; #define INIT_MESA_SPARC #endif -#ifdef GLX_DIRECT_RENDERING -static __DRIscreen *__glXFindDRIScreen(__DRInativeDisplay *dpy, int scrn); -#endif /* GLX_DIRECT_RENDERING */ - static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext gc); @@ -363,9 +360,10 @@ static void FreeScreenConfigs(__GLXdisplayPrivate *priv) #ifdef GLX_DIRECT_RENDERING /* Free the direct rendering per screen data */ if (psc->driScreen.private) - (*psc->driScreen.destroyScreen)(priv->dpy, i, - psc->driScreen.private); + (*psc->driScreen.destroyScreen)(&psc->driScreen); psc->driScreen.private = NULL; + if (psc->drawHash) + __glxHashDestroy(psc->drawHash); #endif } XFree((char*) priv->screenConfigs); @@ -694,21 +692,8 @@ filter_modes( __GLcontextModes ** server_modes, return modes_count; } - -/** - * Implement \c __DRIinterfaceMethods::getProcAddress. - */ -static __DRIfuncPtr get_proc_address( const char * proc_name ) -{ - if (strcmp( proc_name, "glxEnableExtension" ) == 0) { - return (__DRIfuncPtr) __glXScrEnableExtension; - } - - return NULL; -} - #ifdef XDAMAGE_1_1_INTERFACE -static GLboolean has_damage_post(__DRInativeDisplay *dpy) +static GLboolean has_damage_post(Display *dpy) { static GLboolean inited = GL_FALSE; static GLboolean has_damage; @@ -730,8 +715,7 @@ static GLboolean has_damage_post(__DRInativeDisplay *dpy) } #endif /* XDAMAGE_1_1_INTERFACE */ -static void __glXReportDamage(__DRInativeDisplay *dpy, int screen, - __DRIid drawable, +static void __glXReportDamage(__DRIdrawable *driDraw, int x, int y, drm_clip_rect_t *rects, int num_rects, GLboolean front_buffer) @@ -741,6 +725,11 @@ static void __glXReportDamage(__DRInativeDisplay *dpy, int screen, XserverRegion region; int i; int x_off, y_off; + __GLXdrawable *glxDraw = + containerOf(driDraw, __GLXdrawable, driDrawable); + __GLXscreenConfigs *psc = glxDraw->psc; + Display *dpy = psc->dpy; + Drawable drawable; if (!has_damage_post(dpy)) return; @@ -748,10 +737,11 @@ static void __glXReportDamage(__DRInativeDisplay *dpy, int screen, if (front_buffer) { x_off = x; y_off = y; - drawable = RootWindow(dpy, screen); + drawable = RootWindow(dpy, psc->scr); } else{ x_off = 0; y_off = 0; + drawable = glxDraw->drawable; } xrects = malloc(sizeof(XRectangle) * num_rects); @@ -771,24 +761,35 @@ static void __glXReportDamage(__DRInativeDisplay *dpy, int screen, #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) +{ + __GLXdrawable *glxDraw = + containerOf(drawable, __GLXdrawable, driDrawable); + __GLXscreenConfigs *psc = glxDraw->psc; + Display *dpy = psc->dpy; + + return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable, + index, stamp, X, Y, W, H, + numClipRects, pClipRects, + backX, backY, + numBackClipRects, pBackClipRects); +} + + /** * Table of functions exported by the loader to the driver. */ static const __DRIinterfaceMethods interface_methods = { - get_proc_address, - _gl_context_modes_create, _gl_context_modes_destroy, - - __glXFindDRIScreen, - __glXWindowExists, - - XF86DRICreateContextWithConfig, - XF86DRIDestroyContext, - XF86DRICreateDrawable, - XF86DRIDestroyDrawable, - XF86DRIGetDrawableInfo, + __glXDRIGetDrawableInfo, __glXGetUST, __glXGetMscRateOML, @@ -816,7 +817,7 @@ static const __DRIinterfaceMethods interface_methods = { * returned by the client-side driver. */ static void * -CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, +CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, __DRIdisplay * driDpy, PFNCREATENEWSCREENFUNC createNewScreen) { @@ -937,13 +938,11 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, if ( status == 0 ) { __GLcontextModes * driver_modes = NULL; - __GLXscreenConfigs *configs = psc->screenConfigs; err_msg = "InitDriver"; err_extra = NULL; - psp = (*createNewScreen)(dpy, scrn, - psc, - configs->configs, + psp = (*createNewScreen)(scrn, + &psc->driScreen, & ddx_version, & dri_version, & drm_version, @@ -954,8 +953,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, & interface_methods, & driver_modes ); - filter_modes( & configs->configs, - driver_modes ); + filter_modes(&psc->configs, driver_modes); _gl_context_modes_destroy( driver_modes ); } } @@ -999,8 +997,131 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, return psp; } + #endif /* GLX_DIRECT_RENDERING */ +static __GLcontextModes * +createConfigsFromProperties(Display *dpy, int nvisuals, int nprops, + int screen, GLboolean tagged_only) +{ + INT32 buf[__GLX_TOTAL_CONFIG], *props; + unsigned prop_size; + __GLcontextModes *modes, *m; + int i; + + if (nprops == 0) + return NULL; + + /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ + + /* Check number of properties */ + if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) + return NULL; + + /* Allocate memory for our config structure */ + modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes)); + if (!modes) + return NULL; + + prop_size = nprops * __GLX_SIZE_INT32; + if (prop_size <= sizeof(buf)) + props = buf; + else + props = Xmalloc(prop_size); + + /* Read each config structure and convert it into our format */ + m = modes; + for (i = 0; i < nvisuals; i++) { + _XRead(dpy, (char *)props, prop_size); + /* Older X servers don't send this so we default it here. */ + m->drawableType = GLX_WINDOW_BIT; + __glXInitializeVisualConfigFromTags(m, nprops, props, + tagged_only, GL_TRUE); + m->screen = screen; + m = m->next; + } + + if (props != buf) + Xfree(props); + + return modes; +} + +static GLboolean +getVisualConfigs(Display *dpy, __GLXdisplayPrivate *priv, int screen) +{ + xGLXGetVisualConfigsReq *req; + __GLXscreenConfigs *psc; + xGLXGetVisualConfigsReply reply; + + LockDisplay(dpy); + + psc = priv->screenConfigs + screen; + psc->visuals = NULL; + GetReq(GLXGetVisualConfigs, req); + req->reqType = priv->majorOpcode; + req->glxCode = X_GLXGetVisualConfigs; + req->screen = screen; + + if (!_XReply(dpy, (xReply*) &reply, 0, False)) + goto out; + + psc->visuals = createConfigsFromProperties(dpy, + reply.numVisuals, + reply.numProps, + screen, GL_FALSE); + + out: + UnlockDisplay(dpy); + return psc->visuals != NULL; +} + +static GLboolean +getFBConfigs(Display *dpy, __GLXdisplayPrivate *priv, int screen) +{ + xGLXGetFBConfigsReq *fb_req; + xGLXGetFBConfigsSGIXReq *sgi_req; + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXGetFBConfigsReply reply; + __GLXscreenConfigs *psc; + + psc = priv->screenConfigs + screen; + psc->serverGLXexts = __glXGetStringFromServer(dpy, priv->majorOpcode, + X_GLXQueryServerString, + screen, GLX_EXTENSIONS); + + LockDisplay(dpy); + + psc->configs = NULL; + if (atof(priv->serverGLXversion) >= 1.3) { + GetReq(GLXGetFBConfigs, fb_req); + fb_req->reqType = priv->majorOpcode; + fb_req->glxCode = X_GLXGetFBConfigs; + fb_req->screen = screen; + } else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXGetFBConfigsSGIXReq + + sz_xGLXVendorPrivateWithReplyReq, vpreq); + sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; + sgi_req->reqType = priv->majorOpcode; + sgi_req->glxCode = X_GLXVendorPrivateWithReply; + sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; + sgi_req->screen = screen; + } else + goto out; + + if (!_XReply(dpy, (xReply*) &reply, 0, False)) + goto out; + + psc->configs = createConfigsFromProperties(dpy, + reply.numFBConfigs, + reply.numAttribs * 2, + screen, GL_TRUE); + + out: + UnlockDisplay(dpy); + return psc->configs != NULL; +} /* ** Allocate the memory for the per screen configs for each screen. @@ -1008,17 +1129,8 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, */ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv) { - xGLXGetVisualConfigsReq *req; - xGLXGetFBConfigsReq *fb_req; - xGLXVendorPrivateWithReplyReq *vpreq; - xGLXGetFBConfigsSGIXReq *sgi_req; - xGLXGetVisualConfigsReply reply; __GLXscreenConfigs *psc; - __GLcontextModes *config; - GLint i, j, nprops, screens; - INT32 buf[__GLX_TOTAL_CONFIG], *props; - unsigned supported_request = 0; - unsigned prop_size; + GLint i, screens; /* ** First allocate memory for the array of per screen configs. @@ -1032,143 +1144,28 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv) priv->screenConfigs = psc; priv->serverGLXversion = __glXGetStringFromServer(dpy, priv->majorOpcode, - X_GLXQueryServerString, - 0, GLX_VERSION); + X_GLXQueryServerString, + 0, GLX_VERSION); if ( priv->serverGLXversion == NULL ) { FreeScreenConfigs(priv); return GL_FALSE; } - if ( atof( priv->serverGLXversion ) >= 1.3 ) { - supported_request = 1; - } - - /* - ** Now fetch each screens configs structures. If a screen supports - ** GL (by returning a numVisuals > 0) then allocate memory for our - ** config structure and then fill it in. - */ for (i = 0; i < screens; i++, psc++) { - if ( supported_request != 1 ) { - psc->serverGLXexts = __glXGetStringFromServer(dpy, priv->majorOpcode, - X_GLXQueryServerString, - i, GLX_EXTENSIONS); - if ( strstr( psc->serverGLXexts, "GLX_SGIX_fbconfig" ) != NULL ) { - supported_request = 2; - } - else { - supported_request = 3; - } - } - - - LockDisplay(dpy); - switch( supported_request ) { - case 1: - GetReq(GLXGetFBConfigs,fb_req); - fb_req->reqType = priv->majorOpcode; - fb_req->glxCode = X_GLXGetFBConfigs; - fb_req->screen = i; - break; - - case 2: - GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXGetFBConfigsSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq); - sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; - sgi_req->reqType = priv->majorOpcode; - sgi_req->glxCode = X_GLXVendorPrivateWithReply; - sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; - sgi_req->screen = i; - break; - - case 3: - GetReq(GLXGetVisualConfigs,req); - req->reqType = priv->majorOpcode; - req->glxCode = X_GLXGetVisualConfigs; - req->screen = i; - break; - } - - if (!_XReply(dpy, (xReply*) &reply, 0, False)) { - /* Something is busted. Punt. */ - UnlockDisplay(dpy); - SyncHandle(); - FreeScreenConfigs(priv); - return GL_FALSE; - } - - if (!reply.numVisuals) { - /* This screen does not support GL rendering */ - UnlockDisplay(dpy); - continue; - } + getVisualConfigs(dpy, priv, i); + getFBConfigs(dpy, priv, i); - /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for - * FIXME: FBconfigs? - */ - /* Check number of properties */ - nprops = reply.numProps; - if ((nprops < __GLX_MIN_CONFIG_PROPS) || - (nprops > __GLX_MAX_CONFIG_PROPS)) { - /* Huh? Not in protocol defined limits. Punt */ - UnlockDisplay(dpy); - SyncHandle(); - FreeScreenConfigs(priv); - return GL_FALSE; - } - - /* Allocate memory for our config structure */ - psc->configs = _gl_context_modes_create(reply.numVisuals, - sizeof(__GLcontextModes)); - if (!psc->configs) { - UnlockDisplay(dpy); +#ifdef GLX_DIRECT_RENDERING + psc->scr = i; + psc->dpy = dpy; + /* Create drawable hash */ + psc->drawHash = __glxHashCreate(); + if ( psc->drawHash == NULL ) { SyncHandle(); FreeScreenConfigs(priv); return GL_FALSE; } - /* Allocate memory for the properties, if needed */ - if ( supported_request != 3 ) { - nprops *= 2; - } - - prop_size = nprops * __GLX_SIZE_INT32; - - if (prop_size <= sizeof(buf)) { - props = buf; - } else { - props = (INT32 *) Xmalloc(prop_size); - } - - /* Read each config structure and convert it into our format */ - config = psc->configs; - for (j = 0; j < reply.numVisuals; j++) { - assert( config != NULL ); - _XRead(dpy, (char *)props, prop_size); - - if ( supported_request != 3 ) { - config->rgbMode = GL_TRUE; - config->drawableType = GLX_WINDOW_BIT; - } - else { - config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT; - } - - __glXInitializeVisualConfigFromTags( config, nprops, props, - (supported_request != 3), - GL_TRUE ); - if ( config->fbconfigID == GLX_DONT_CARE ) { - config->fbconfigID = config->visualID; - } - config->screen = i; - config = config->next; - } - if (props != buf) { - Xfree((char *)props); - } - UnlockDisplay(dpy); - -#ifdef GLX_DIRECT_RENDERING /* Initialize per screen dynamic client GLX extensions */ psc->ext_list_first_time = GL_TRUE; /* Initialize the direct rendering per screen data and functions */ @@ -1179,11 +1176,12 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv) if (priv->driDisplay.createNewScreen && priv->driDisplay.createNewScreen[i]) { - psc->driScreen.screenConfigs = (void *)psc; psc->driScreen.private = - CallCreateNewScreen(dpy, i, & psc->driScreen, + CallCreateNewScreen(dpy, i, psc, & priv->driDisplay, priv->driDisplay.createNewScreen[i] ); + if (psc->driScreen.private != NULL) + __glXScrEnableDRIExtension(psc); } } #endif @@ -1363,7 +1361,8 @@ GLubyte *__glXFlushRenderBuffer(__GLXcontext *ctx, GLubyte *pc) if ( (dpy != NULL) && (size > 0) ) { #ifdef USE_XCB - xcb_glx_render(c, ctx->currentContextTag, size, (char *)ctx->buf); + xcb_glx_render(c, ctx->currentContextTag, size, + (const uint8_t *)ctx->buf); #else /* Send the entire buffer as an X request */ LockDisplay(dpy); @@ -1506,33 +1505,6 @@ PUBLIC GLXDrawable glXGetCurrentDrawable(void) /************************************************************************/ -#ifdef GLX_DIRECT_RENDERING -/* Return the DRI per screen structure */ -__DRIscreen *__glXFindDRIScreen(__DRInativeDisplay *dpy, int scrn) -{ - __DRIscreen *pDRIScreen = NULL; - XExtDisplayInfo *info = __glXFindDisplay(dpy); - XExtData **privList, *found; - __GLXdisplayPrivate *dpyPriv; - XEDataObject dataObj; - - __glXLock(); - dataObj.display = dpy; - privList = XEHeadOfExtensionList(dataObj); - found = XFindOnExtensionList(privList, info->codes->extension); - __glXUnlock(); - - if (found) { - dpyPriv = (__GLXdisplayPrivate *)found->private_data; - pDRIScreen = &dpyPriv->screenConfigs[scrn].driScreen; - } - - return pDRIScreen; -} -#endif - -/************************************************************************/ - static Bool SendMakeCurrentRequest( Display *dpy, CARD8 opcode, GLXContextID gc, GLXContextTag old_gc, GLXDrawable draw, GLXDrawable read, xGLXMakeCurrentReply * reply ); @@ -1617,20 +1589,71 @@ static Bool SendMakeCurrentRequest(Display *dpy, CARD8 opcode, #ifdef GLX_DIRECT_RENDERING +static __DRIdrawable * +FetchDRIDrawable( Display *dpy, GLXDrawable drawable, GLXContext gc) +{ + __GLXdisplayPrivate * const priv = __glXInitialize(dpy); + __GLXdrawable *pdraw; + __GLXscreenConfigs *sc; + drm_drawable_t hwDrawable; + void *empty_attribute_list = NULL; + + if (priv == NULL || priv->driDisplay.private == NULL) + return NULL; + + sc = &priv->screenConfigs[gc->screen]; + if (__glxHashLookup(sc->drawHash, drawable, (void *) &pdraw) == 0) + return &pdraw->driDrawable; + + /* Allocate a new drawable */ + pdraw = Xmalloc(sizeof(*pdraw)); + if (!pdraw) + return NULL; + + pdraw->drawable = drawable; + pdraw->psc = sc; + + if (!XF86DRICreateDrawable(dpy, sc->scr, drawable, &hwDrawable)) + return NULL; + + /* Create a new drawable */ + pdraw->driDrawable.private = + (*sc->driScreen.createNewDrawable)(&sc->driScreen, + gc->mode, + &pdraw->driDrawable, + hwDrawable, + GLX_WINDOW_BIT, + empty_attribute_list); + + if (!pdraw->driDrawable.private) { + XF86DRIDestroyDrawable(dpy, sc->scr, drawable); + Xfree(pdraw); + return NULL; + } + + if (__glxHashInsert(sc->drawHash, drawable, pdraw)) { + (*pdraw->driDrawable.destroyDrawable)(&pdraw->driDrawable); + XF86DRIDestroyDrawable(dpy, sc->scr, drawable); + Xfree(pdraw); + return NULL; + } + + return &pdraw->driDrawable; +} + static Bool BindContextWrapper( Display *dpy, GLXContext gc, GLXDrawable draw, GLXDrawable read ) { - return (*gc->driContext.bindContext)(dpy, gc->screen, draw, read, - & gc->driContext); + __DRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc); + __DRIdrawable *pread = FetchDRIDrawable(dpy, read, gc); + + return (*gc->driContext.bindContext)(&gc->driContext, pdraw, pread); } static Bool UnbindContextWrapper( GLXContext gc ) { - return (*gc->driContext.unbindContext)(gc->currentDpy, gc->screen, - gc->currentDrawable, - gc->currentReadable, - & gc->driContext ); + return (*gc->driContext.unbindContext)(&gc->driContext); } #endif /* GLX_DIRECT_RENDERING */ @@ -1742,7 +1765,10 @@ USED static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw, if (oldGC->isDirect) { if (oldGC->driContext.private) { (*oldGC->driContext.destroyContext) - (dpy, oldGC->screen, oldGC->driContext.private); + (&oldGC->driContext); + XF86DRIDestroyContext(oldGC->createDpy, + oldGC->psc->scr, + gc->hwContextID); oldGC->driContext.private = NULL; } } |