diff options
Diffstat (limited to 'src/glx/dri_glx.c')
-rw-r--r-- | src/glx/dri_glx.c | 381 |
1 files changed, 290 insertions, 91 deletions
diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c index 12a2cf3af24..fd14285a481 100644 --- a/src/glx/dri_glx.c +++ b/src/glx/dri_glx.c @@ -47,10 +47,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86drm.h" #include "dri_common.h" -typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; -typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; - -struct __GLXDRIdisplayPrivateRec +struct dri_display { __GLXDRIdisplay base; @@ -62,14 +59,40 @@ struct __GLXDRIdisplayPrivateRec int driPatch; }; -struct __GLXDRIcontextPrivateRec +struct dri_screen +{ + __GLXscreenConfigs base; + + __DRIscreen *driScreen; + __GLXDRIscreen vtable; + const __DRIlegacyExtension *legacy; + const __DRIcoreExtension *core; + const __DRIswapControlExtension *swapControl; + const __DRImediaStreamCounterExtension *msc; + const __DRIconfig **driver_configs; + const __DRIcopySubBufferExtension *driCopySubBuffer; + + void *driver; + int fd; +}; + +struct dri_context { - __GLXDRIcontext base; + __GLXcontext base; + __GLXDRIcontext dri_vtable; __DRIcontext *driContext; XID hwContextID; - __GLXscreenConfigs *psc; }; +struct dri_drawable +{ + __GLXDRIdrawable base; + + __DRIdrawable *driDrawable; +}; + +static const struct glx_context_vtable dri_context_vtable; + /* * Given a display pointer and screen number, determine the name of * the DRI driver for the screen. (I.e. "r128", "tdfx", etc). @@ -293,8 +316,8 @@ static const __DRIextension *loader_extensions[] = { * the client-side driver on success, or \c NULL on failure. */ static void * -CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, - __GLXDRIdisplayPrivate * driDpy) +CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, + struct dri_display * driDpy) { void *psp = NULL; drm_handle_t hSAREA; @@ -424,8 +447,10 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, goto handle_error; } - psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); - psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); + psc->base.configs = + driConvertConfigs(psc->core, psc->base.configs, driver_configs); + psc->base.visuals = + driConvertConfigs(psc->core, psc->base.visuals, driver_configs); psc->driver_configs = driver_configs; @@ -433,7 +458,7 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, * in the X server, so DRI1 can't render to them properly. Mark them as * non-conformant to prevent apps from picking them up accidentally. */ - for (visual = psc->visuals; visual; visual = visual->next) { + for (visual = psc->base.visuals; visual; visual = visual->next) { XVisualInfo template; XVisualInfo *visuals; int num_visuals; @@ -474,52 +499,72 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, } static void -driDestroyContext(__GLXDRIcontext * context, - __GLXscreenConfigs * psc, Display * dpy) +dri_destroy_context(__GLXcontext * context) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + struct dri_context *pcp = (struct dri_context *) context; + struct dri_screen *psc = (struct dri_screen *) context->psc; + + if (context->xid) + glx_send_destroy_context(psc->base.dpy, context->xid); + + if (context->extensions) + XFree((char *) context->extensions); + + GarbageCollectDRIDrawables(context->psc); (*psc->core->destroyContext) (pcp->driContext); - XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); + XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID); Xfree(pcp); } static Bool -driBindContext(__GLXDRIcontext * context, - __GLXDRIdrawable * draw, __GLXDRIdrawable * read) +driBindContext(__GLXcontext *context, + __GLXDRIdrawable *draw, __GLXDRIdrawable *read) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - const __DRIcoreExtension *core = pcp->psc->core; + struct dri_context *pcp = (struct dri_context *) context; + struct dri_screen *psc = (struct dri_screen *) pcp->base.psc; + struct dri_drawable *pdr = (struct dri_drawable *) draw; + struct dri_drawable *prd = (struct dri_drawable *) read; - return (*core->bindContext) (pcp->driContext, - draw->driDrawable, read->driDrawable); + return (*psc->core->bindContext) (pcp->driContext, + pdr->driDrawable, prd->driDrawable); } static void -driUnbindContext(__GLXDRIcontext * context) +driUnbindContext(__GLXcontext * context) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - const __DRIcoreExtension *core = pcp->psc->core; + struct dri_context *pcp = (struct dri_context *) context; + struct dri_screen *psc = (struct dri_screen *) pcp->base.psc; - (*core->unbindContext) (pcp->driContext); + (*psc->core->unbindContext) (pcp->driContext); } -static __GLXDRIcontext * -driCreateContext(__GLXscreenConfigs * psc, - const __GLcontextModes * mode, - GLXContext gc, GLXContext shareList, int renderType) +static const struct glx_context_vtable dri_context_vtable = { + dri_destroy_context, + NULL, + NULL, + DRI_glXUseXFont, + NULL, + NULL, +}; + +static __GLXcontext * +dri_create_context(__GLXscreenConfigs *base, + const __GLcontextModes *mode, + GLXContext shareList, int renderType) { - __GLXDRIcontextPrivate *pcp, *pcp_shared; + struct dri_context *pcp, *pcp_shared; + struct dri_screen *psc = (struct dri_screen *) base; drm_context_t hwContext; __DRIcontext *shared = NULL; __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; - if (!psc || !psc->driScreen) + if (!psc->base.driScreen) return NULL; if (shareList) { - pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; + pcp_shared = (struct dri_context *) shareList->driContext; shared = pcp_shared->driContext; } @@ -527,8 +572,13 @@ driCreateContext(__GLXscreenConfigs * psc, if (pcp == NULL) return NULL; - pcp->psc = psc; - if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr, + memset(pcp, 0, sizeof *pcp); + if (!glx_context_init(&pcp->base, &psc->base, mode)) { + Xfree(pcp); + return NULL; + } + + if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr, mode->visualID, &pcp->hwContextID, &hwContext)) { Xfree(pcp); @@ -536,18 +586,19 @@ driCreateContext(__GLXscreenConfigs * psc, } pcp->driContext = - (*psc->legacy->createNewContext) (psc->__driScreen, + (*psc->legacy->createNewContext) (psc->driScreen, config->driConfig, renderType, shared, hwContext, pcp); if (pcp->driContext == NULL) { - XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); + XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID); Xfree(pcp); return NULL; } - pcp->base.destroyContext = driDestroyContext; - pcp->base.bindContext = driBindContext; - pcp->base.unbindContext = driUnbindContext; + pcp->base.vtable = &dri_context_vtable; + pcp->base.driContext = &pcp->dri_vtable; + pcp->dri_vtable.bindContext = driBindContext; + pcp->dri_vtable.unbindContext = driUnbindContext; return &pcp->base; } @@ -555,63 +606,70 @@ driCreateContext(__GLXscreenConfigs * psc, static void driDestroyDrawable(__GLXDRIdrawable * pdraw) { - __GLXscreenConfigs *psc = pdraw->psc; + struct dri_screen *psc = (struct dri_screen *) pdraw->psc; + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; - (*psc->core->destroyDrawable) (pdraw->driDrawable); - XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable); + (*psc->core->destroyDrawable) (pdp->driDrawable); + XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable); Xfree(pdraw); } static __GLXDRIdrawable * -driCreateDrawable(__GLXscreenConfigs * psc, +driCreateDrawable(__GLXscreenConfigs *base, XID xDrawable, GLXDrawable drawable, const __GLcontextModes * modes) { - __GLXDRIdrawable *pdraw; drm_drawable_t hwDrawable; void *empty_attribute_list = NULL; __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; + struct dri_screen *psc = (struct dri_screen *) base; + struct dri_drawable *pdp; /* Old dri can't handle GLX 1.3+ drawable constructors. */ if (xDrawable != drawable) return NULL; - pdraw = Xmalloc(sizeof(*pdraw)); - if (!pdraw) + pdp = Xmalloc(sizeof *pdp); + if (!pdp) return NULL; - pdraw->drawable = drawable; - pdraw->psc = psc; + memset(pdp, 0, sizeof *pdp); + pdp->base.drawable = drawable; + pdp->base.psc = &psc->base; - if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable)) { - Xfree(pdraw); + if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr, + drawable, &hwDrawable)) { + Xfree(pdp); return NULL; } /* Create a new drawable */ - pdraw->driDrawable = - (*psc->legacy->createNewDrawable) (psc->__driScreen, + pdp->driDrawable = + (*psc->legacy->createNewDrawable) (psc->driScreen, config->driConfig, hwDrawable, GLX_WINDOW_BIT, - empty_attribute_list, pdraw); + empty_attribute_list, pdp); - if (!pdraw->driDrawable) { - XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable); - Xfree(pdraw); + if (!pdp->driDrawable) { + XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable); + Xfree(pdp); return NULL; } - pdraw->destroyDrawable = driDestroyDrawable; + pdp->base.destroyDrawable = driDestroyDrawable; - return pdraw; + return &pdp->base; } static int64_t driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2, int64_t unused3) { - (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable); + struct dri_screen *psc = (struct dri_screen *) pdraw->psc; + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + + (*psc->core->swapBuffers) (pdp->driDrawable); return 0; } @@ -619,56 +677,189 @@ static void driCopySubBuffer(__GLXDRIdrawable * pdraw, int x, int y, int width, int height) { - (*pdraw->psc->driCopySubBuffer->copySubBuffer) (pdraw->driDrawable, - x, y, width, height); + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + struct dri_screen *psc = (struct dri_screen *) pdp->base.psc; + + (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable, + x, y, width, height); } static void -driDestroyScreen(__GLXscreenConfigs * psc) +driDestroyScreen(__GLXscreenConfigs *base) { + struct dri_screen *psc = (struct dri_screen *) base; + /* Free the direct rendering per screen data */ - if (psc->__driScreen) - (*psc->core->destroyScreen) (psc->__driScreen); - psc->__driScreen = NULL; + if (psc->driScreen) + (*psc->core->destroyScreen) (psc->driScreen); + driDestroyConfigs(psc->driver_configs); + psc->driScreen = NULL; if (psc->driver) dlclose(psc->driver); } -static const struct glx_context_vtable dri_context_vtable = { - NULL, - NULL, +#ifdef __DRI_SWAP_BUFFER_COUNTER + +static int +driDrawableGetMSC(__GLXscreenConfigs *base, __GLXDRIdrawable *pdraw, + int64_t *ust, int64_t *msc, int64_t *sbc) +{ + struct dri_screen *psc = (struct dri_screen *) base; + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + + if (pdp && psc->sbc && psc->msc) + return ( (*psc->msc->getMSC)(psc->driScreen, msc) == 0 && + (*psc->sbc->getSBC)(pdp->driDrawable, sbc) == 0 && + __glXGetUST(ust) == 0 ); +} + +static int +driWaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, + int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) +{ + struct dri_screen *psc = (struct dri_screen *) pdraw->psc; + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + + if (pdp != NULL && psc->msc != NULL) { + ret = (*psc->msc->waitForMSC) (pdp->driDrawable, target_msc, + divisor, remainder, msc, sbc); + + /* __glXGetUST returns zero on success and non-zero on failure. + * This function returns True on success and False on failure. + */ + return ret == 0 && __glXGetUST(ust) == 0; + } +} + +static int +driWaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, + int64_t *msc, int64_t *sbc) +{ + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + + if (pdp != NULL && psc->sbc != NULL) { + ret = + (*psc->sbc->waitForSBC) (pdp->driDrawable, target_sbc, msc, sbc); + + /* __glXGetUST returns zero on success and non-zero on failure. + * This function returns True on success and False on failure. + */ + return ((ret == 0) && (__glXGetUST(ust) == 0)); + } + + return DRI2WaitSBC(pdp->base.psc->dpy, + pdp->base.xDrawable, target_sbc, ust, msc, sbc); +} + +#endif + +static int +driSetSwapInterval(__GLXDRIdrawable *pdraw, int interval) +{ + GLXContext gc = __glXGetCurrentContext(); + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + struct dri_screen *psc; + + if (gc->driContext) { + psc = (struct dri_screen *) pdraw->psc; + + if (psc->swapControl != NULL && pdraw != NULL) { + psc->swapControl->setSwapInterval(pdp->driDrawable, interval); + return 0; + } + } + + return GLX_BAD_CONTEXT; +} + +static int +driGetSwapInterval(__GLXDRIdrawable *pdraw) +{ + GLXContext gc = __glXGetCurrentContext(); + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + struct dri_screen *psc; + + if (gc != NULL && gc->driContext) { + psc = (struct dri_screen *) pdraw->psc; + + if (psc->swapControl != NULL && pdraw != NULL) { + return psc->swapControl->getSwapInterval(pdp->driDrawable); + } + } + + return 0; +} + +/* Bind DRI1 specific extensions */ +static void +driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions) +{ + int i; + + for (i = 0; extensions[i]; i++) { + /* No DRI2 support for swap_control at the moment, since SwapBuffers + * is done by the X server */ + if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) { + psc->swapControl = (__DRIswapControlExtension *) extensions[i]; + __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); + __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); + } + + if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) { + psc->msc = (__DRImediaStreamCounterExtension *) extensions[i]; + __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync"); + } + + if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { + psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; + __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); + } + + if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { + __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); + } + /* Ignore unknown extensions */ + } +} + +static const struct glx_screen_vtable dri_screen_vtable = { + dri_create_context }; -static __GLXDRIscreen * -driCreateScreen(__GLXscreenConfigs * psc, int screen, - __GLXdisplayPrivate * priv) +static __GLXscreenConfigs * +driCreateScreen(int screen, __GLXdisplayPrivate *priv) { - __GLXDRIdisplayPrivate *pdp; + struct dri_display *pdp; __GLXDRIscreen *psp; const __DRIextension **extensions; + struct dri_screen *psc; char *driverName; int i; - psp = Xcalloc(1, sizeof *psp); - if (psp == NULL) + psc = Xcalloc(1, sizeof *psc); + if (psc == NULL) return NULL; + memset(psc, 0, sizeof *psc); + if (!glx_screen_init(&psc->base, screen, priv)) + return NULL; + if (!driGetDriverName(priv->dpy, screen, &driverName)) { - Xfree(psp); + Xfree(psc); return NULL; } psc->driver = driOpenDriver(driverName); Xfree(driverName); if (psc->driver == NULL) { - Xfree(psp); + Xfree(psc); return NULL; } extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); if (extensions == NULL) { ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); - Xfree(psp); + Xfree(psc); return NULL; } @@ -680,34 +871,42 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen, } if (psc->core == NULL || psc->legacy == NULL) { - Xfree(psp); + Xfree(psc); return NULL; } - pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay; - psc->__driScreen = CallCreateNewScreen(psc->dpy, screen, psc, pdp); - if (psc->__driScreen == NULL) { + pdp = (struct dri_display *) priv->driDisplay; + psc->driScreen = + CallCreateNewScreen(psc->base.dpy, screen, psc, pdp); + if (psc->driScreen == NULL) { dlclose(psc->driver); - Xfree(psp); + Xfree(psc); return NULL; } - driBindExtensions(psc); - driBindCommonExtensions(psc); + extensions = psc->core->getExtensions(psc->driScreen); + driBindExtensions(psc, extensions); + psc->base.vtable = &dri_screen_vtable; + psp = &psc->vtable; + psc->base.driScreen = psp; if (psc->driCopySubBuffer) psp->copySubBuffer = driCopySubBuffer; psp->destroyScreen = driDestroyScreen; - psp->createContext = driCreateContext; psp->createDrawable = driCreateDrawable; psp->swapBuffers = driSwapBuffers; - psp->waitX = NULL; - psp->waitGL = NULL; - psc->direct_context_vtable = &dri_context_vtable; +#ifdef __DRI_SWAP_BUFFER_COUNTER + psp->getDrawableMSC = driDrawableGetMSC; + psp->waitForMSC = driWaitForMSC; + psp->waitForSBC = driWaitForSBC; +#endif - return psp; + psp->setSwapInterval = driSetSwapInterval; + psp->getSwapInterval = driGetSwapInterval; + + return &psc->base; } /* Called from __glXFreeDisplayPrivate. @@ -726,7 +925,7 @@ driDestroyDisplay(__GLXDRIdisplay * dpy) _X_HIDDEN __GLXDRIdisplay * driCreateDisplay(Display * dpy) { - __GLXDRIdisplayPrivate *pdpyp; + struct dri_display *pdpyp; int eventBase, errorBase; int major, minor, patch; |