X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglx%2Fdri_glx.c;h=5c4346cec0d8f09591290b2b6722e00e08f73326;hb=478fc2d2a1a392108f48a3ed9aa21b10be72b4a2;hp=b2fced95222fe096e2c00725b1170e73f82268e8;hpb=7c7b7b068b1d0dc8e14b87dab5dbd4108f874f74;p=mesa.git diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c index b2fced95222..5c4346cec0d 100644 --- a/src/glx/dri_glx.c +++ b/src/glx/dri_glx.c @@ -40,7 +40,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "glxclient.h" #include "xf86dri.h" #include "dri2.h" -#include "sarea.h" +#include "dri_sarea.h" #include #include #include @@ -90,8 +90,6 @@ struct dri_drawable __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., "i965", "radeon", "nouveau", etc). @@ -150,7 +148,7 @@ driGetDriverName(Display * dpy, int scrNum, char **driverName) * The returned char pointer points to a static array that will be * overwritten by subsequent calls. */ -_X_EXPORT const char * +_GLX_PUBLIC const char * glXGetScreenDriver(Display * dpy, int scrNum) { static char ret[32]; @@ -169,6 +167,76 @@ glXGetScreenDriver(Display * dpy, int scrNum) return NULL; } +/* glXGetDriverConfig must return a pointer with a static lifetime. To avoid + * keeping drivers loaded and other leaks, we keep a cache of results here that + * is cleared by an atexit handler. + */ +struct driver_config_entry { + struct driver_config_entry *next; + char *driverName; + char *config; +}; + +static pthread_mutex_t driver_config_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct driver_config_entry *driver_config_cache = NULL; + +/* Called as an atexit function. Otherwise, this would have to be called with + * driver_config_mutex locked. + */ +static void +clear_driver_config_cache() +{ + while (driver_config_cache) { + struct driver_config_entry *e = driver_config_cache; + driver_config_cache = e->next; + + free(e->driverName); + free(e->config); + free(e); + } +} + +static char * +get_driver_config(const char *driverName) +{ + void *handle = driOpenDriver(driverName); + const __DRIextension **extensions; + + if (!handle) + return NULL; + + char *config = NULL; + + extensions = driGetDriverExtensions(handle, driverName); + if (extensions) { + for (int i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_CONFIG_OPTIONS) != 0) + continue; + + __DRIconfigOptionsExtension *ext = + (__DRIconfigOptionsExtension *)extensions[i]; + + if (ext->base.version >= 2) + config = ext->getXml(driverName); + else + config = strdup(ext->xml); + + break; + } + } + + if (!config) { + /* Fall back to the old method */ + config = dlsym(handle, "__driConfigOptions"); + if (config) + config = strdup(config); + } + + dlclose(handle); + + return config; +} + /* * Exported function for obtaining a driver's option list (UTF-8 encoded XML). * @@ -177,20 +245,44 @@ glXGetScreenDriver(Display * dpy, int scrNum) * * If the driver was not found or does not support configuration NULL is * returned. - * - * Note: The driver remains opened after this function returns. */ -_X_EXPORT const char * +_GLX_PUBLIC const char * glXGetDriverConfig(const char *driverName) { - void *handle = driOpenDriver(driverName); - if (handle) - return dlsym(handle, "__driConfigOptions"); - else - return NULL; -} + struct driver_config_entry *e; -#ifdef XDAMAGE_1_1_INTERFACE + pthread_mutex_lock(&driver_config_mutex); + + for (e = driver_config_cache; e; e = e->next) { + if (strcmp(e->driverName, driverName) == 0) + goto out; + } + + e = malloc(sizeof(*e)); + if (!e) + goto out; + + e->config = get_driver_config(driverName); + e->driverName = strdup(driverName); + if (!e->config || !e->driverName) { + free(e->config); + free(e->driverName); + free(e); + e = NULL; + goto out; + } + + e->next = driver_config_cache; + driver_config_cache = e; + + if (!e->next) + atexit(clear_driver_config_cache); + +out: + pthread_mutex_unlock(&driver_config_mutex); + + return e ? e->config : NULL; +} static GLboolean has_damage_post(Display * dpy) @@ -260,11 +352,10 @@ __glXReportDamage(__DRIdrawable * driDraw, } static const __DRIdamageExtension damageExtension = { - {__DRI_DAMAGE, __DRI_DAMAGE_VERSION}, - __glXReportDamage, -}; + .base = {__DRI_DAMAGE, 1 }, -#endif + .reportDamage = __glXReportDamage, +}; static GLboolean __glXDRIGetDrawableInfo(__DRIdrawable * drawable, @@ -288,8 +379,9 @@ __glXDRIGetDrawableInfo(__DRIdrawable * drawable, } static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = { - {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION}, - __glXDRIGetDrawableInfo + .base = {__DRI_GET_DRAWABLE_INFO, 1 }, + + .getDrawableInfo = __glXDRIGetDrawableInfo }; static const __DRIextension *loader_extensions[] = { @@ -407,7 +499,7 @@ CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, &framebuffer.size, &framebuffer.stride, &framebuffer.dev_priv_size, &framebuffer.dev_priv)) { - ErrorMessageF("XF86DRIGetDeviceInfo failed"); + ErrorMessageF("XF86DRIGetDeviceInfo failed\n"); goto handle_error; } @@ -418,7 +510,7 @@ CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, status = drmMap(fd, hFB, framebuffer.size, (drmAddressPtr) & framebuffer.base); if (status != 0) { - ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status)); + ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status)); goto handle_error; } @@ -427,7 +519,7 @@ CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, */ status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); if (status != 0) { - ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status)); + ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status)); goto handle_error; } @@ -442,15 +534,17 @@ CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, &driver_configs, psc); if (psp == NULL) { - ErrorMessageF("Calling driver entry point failed"); + ErrorMessageF("Calling driver entry point failed\n"); goto handle_error; } configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); - if (!configs || !visuals) + if (!configs || !visuals) { + ErrorMessageF("No matching fbConfigs or visuals found\n"); goto handle_error; + } glx_config_destroy_list(psc->base.configs); psc->base.configs = configs; @@ -464,14 +558,14 @@ CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, * non-conformant to prevent apps from picking them up accidentally. */ for (visual = psc->base.visuals; visual; visual = visual->next) { - XVisualInfo template; + XVisualInfo templ; XVisualInfo *visuals; int num_visuals; long mask; - template.visualid = visual->visualID; + templ.visualid = visual->visualID; mask = VisualIDMask; - visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals); + visuals = XGetVisualInfo(dpy, mask, &templ, &num_visuals); if (visuals) { if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn)) @@ -495,8 +589,7 @@ CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, if (framebuffer.base != MAP_FAILED) drmUnmap((drmAddress) framebuffer.base, framebuffer.size); - if (framebuffer.dev_priv != NULL) - free(framebuffer.dev_priv); + free(framebuffer.dev_priv); if (fd >= 0) drmCloseOnce(fd); @@ -516,8 +609,7 @@ dri_destroy_context(struct glx_context * context) driReleaseDrawables(&pcp->base); - if (context->extensions) - free((char *) context->extensions); + free((char *) context->extensions); (*psc->core->destroyContext) (pcp->driContext); @@ -558,15 +650,15 @@ dri_unbind_context(struct glx_context *context, struct glx_context *new) } static const struct glx_context_vtable dri_context_vtable = { - dri_destroy_context, - dri_bind_context, - dri_unbind_context, - NULL, - NULL, - DRI_glXUseXFont, - NULL, - NULL, - NULL, /* get_proc_address */ + .destroy = dri_destroy_context, + .bind = dri_bind_context, + .unbind = dri_unbind_context, + .wait_gl = NULL, + .wait_x = NULL, + .use_x_font = DRI_glXUseXFont, + .bind_tex_image = NULL, + .release_tex_image = NULL, + .get_proc_address = NULL, }; static struct glx_context * @@ -583,6 +675,10 @@ dri_create_context(struct glx_screen *base, if (!psc->base.driScreen) return NULL; + /* Check the renderType value */ + if (!validate_renderType_against_config(config_base, renderType)) + return NULL; + if (shareList) { /* If the shareList context is not a DRI context, we cannot possibly * create a DRI context that shares it. @@ -595,16 +691,17 @@ dri_create_context(struct glx_screen *base, shared = pcp_shared->driContext; } - pcp = malloc(sizeof *pcp); + pcp = calloc(1, sizeof *pcp); if (pcp == NULL) return NULL; - memset(pcp, 0, sizeof *pcp); if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { free(pcp); return NULL; } + pcp->base.renderType = renderType; + if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr, config->base.visualID, &pcp->hwContextID, &hwContext)) { @@ -653,11 +750,10 @@ driCreateDrawable(struct glx_screen *base, if (xDrawable != drawable) return NULL; - pdp = malloc(sizeof *pdp); + pdp = calloc(1, sizeof *pdp); if (!pdp) return NULL; - memset(pdp, 0, sizeof *pdp); pdp->base.drawable = drawable; pdp->base.psc = &psc->base; @@ -688,22 +784,30 @@ driCreateDrawable(struct glx_screen *base, static int64_t driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2, - int64_t unused3) + int64_t unused3, Bool flush) { struct dri_screen *psc = (struct dri_screen *) pdraw->psc; struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + if (flush) { + glFlush(); + } + (*psc->core->swapBuffers) (pdp->driDrawable); return 0; } static void driCopySubBuffer(__GLXDRIdrawable * pdraw, - int x, int y, int width, int height) + int x, int y, int width, int height, Bool flush) { struct dri_drawable *pdp = (struct dri_drawable *) pdraw; struct dri_screen *psc = (struct dri_screen *) pdp->base.psc; + if (flush) { + glFlush(); + } + (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable, x, y, width, height); } @@ -722,72 +826,19 @@ driDestroyScreen(struct glx_screen *base) dlclose(psc->driver); } -#ifdef __DRI_SWAP_BUFFER_COUNTER - -static int -driDrawableGetMSC(struct glx_screen *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) { struct dri_drawable *pdp = (struct dri_drawable *) pdraw; - struct dri_screen *psc = (struct dri_screen *) pdraw->psc; - if (psc->swapControl != NULL && pdraw != NULL) { - psc->swapControl->setSwapInterval(pdp->driDrawable, interval); - return 0; - } + if (pdraw != NULL) { + struct dri_screen *psc = (struct dri_screen *) pdraw->psc; + if (psc->swapControl != NULL) { + psc->swapControl->setSwapInterval(pdp->driDrawable, interval); + return 0; + } + } return GLX_BAD_CONTEXT; } @@ -795,11 +846,13 @@ static int driGetSwapInterval(__GLXDRIdrawable *pdraw) { struct dri_drawable *pdp = (struct dri_drawable *) pdraw; - struct dri_screen *psc = (struct dri_screen *) pdraw->psc; - if (psc->swapControl != NULL && pdraw != NULL) - return psc->swapControl->getSwapInterval(pdp->driDrawable); + if (pdraw != NULL) { + struct dri_screen *psc = (struct dri_screen *) pdraw->psc; + if (psc->swapControl != NULL) + return psc->swapControl->getSwapInterval(pdp->driDrawable); + } return 0; } @@ -836,8 +889,10 @@ driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions) } static const struct glx_screen_vtable dri_screen_vtable = { - dri_create_context, - NULL + .create_context = dri_create_context, + .create_context_attribs = NULL, + .query_renderer_integer = NULL, + .query_renderer_string = NULL, }; static struct glx_screen * @@ -854,7 +909,6 @@ driCreateScreen(int screen, struct glx_display *priv) if (psc == NULL) return NULL; - memset(psc, 0, sizeof *psc); if (!glx_screen_init(&psc->base, screen, priv)) { free(psc); return NULL; @@ -865,7 +919,6 @@ driCreateScreen(int screen, struct glx_display *priv) } psc->driver = driOpenDriver(driverName); - free(driverName); if (psc->driver == NULL) goto cleanup; @@ -904,20 +957,18 @@ driCreateScreen(int screen, struct glx_display *priv) psp->createDrawable = driCreateDrawable; psp->swapBuffers = driSwapBuffers; -#ifdef __DRI_SWAP_BUFFER_COUNTER - psp->getDrawableMSC = driDrawableGetMSC; - psp->waitForMSC = driWaitForMSC; - psp->waitForSBC = driWaitForSBC; -#endif - psp->setSwapInterval = driSetSwapInterval; psp->getSwapInterval = driGetSwapInterval; + free(driverName); + return &psc->base; cleanup: CriticalErrorMessageF("failed to load driver: %s\n", driverName); + free(driverName); + if (psc->driver) dlclose(psc->driver); glx_screen_cleanup(&psc->base);