X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglx%2Fdri_glx.c;h=6e9412d3fb179b67d174be806a9b581ebabe64ee;hb=9f37c9903b87f86a533bfaffa72f0ecb285b02b2;hp=e47db82b70f64f59c1a55e3a5fc61e765c6336b3;hpb=0c96690a5b6e1c2d114e7ec5f1e9d60a4ff2a330;p=mesa.git diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c index e47db82b70f..6e9412d3fb1 100644 --- a/src/glx/dri_glx.c +++ b/src/glx/dri_glx.c @@ -32,7 +32,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#ifdef GLX_DIRECT_RENDERING +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) #include #include @@ -40,17 +40,14 @@ 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 #include "xf86drm.h" #include "dri_common.h" -typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; -typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; - -struct __GLXDRIdisplayPrivateRec +struct dri_display { __GLXDRIdisplay base; @@ -62,17 +59,40 @@ struct __GLXDRIdisplayPrivateRec int driPatch; }; -struct __GLXDRIcontextPrivateRec +struct dri_screen +{ + struct glx_screen 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; + struct glx_context base; __DRIcontext *driContext; XID hwContextID; - __GLXscreenConfigs *psc; +}; + +struct dri_drawable +{ + __GLXDRIdrawable base; + + __DRIdrawable *driDrawable; }; /* * Given a display pointer and screen number, determine the name of - * the DRI driver for the screen. (I.e. "r128", "tdfx", etc). + * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc). * Return True for success, False for failure. */ static Bool @@ -114,7 +134,7 @@ driGetDriverName(Display * dpy, int scrNum, char **driverName) Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev); if (ret) - Xfree(dev); + free(dev); return ret; } @@ -128,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. */ -PUBLIC const char * +_GLX_PUBLIC const char * glXGetScreenDriver(Display * dpy, int scrNum) { static char ret[32]; @@ -141,12 +161,76 @@ glXGetScreenDriver(Display * dpy, int scrNum) if (len >= 31) return NULL; memcpy(ret, driverName, len + 1); - Xfree(driverName); + free(driverName); return ret; } 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; + char *config = NULL; + const __DRIextension **extensions = driOpenDriver(driverName, &handle); + 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). * @@ -155,20 +239,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. */ -PUBLIC 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) @@ -203,7 +311,7 @@ __glXReportDamage(__DRIdrawable * driDraw, int i; int x_off, y_off; __GLXDRIdrawable *glxDraw = loaderPrivate; - __GLXscreenConfigs *psc = glxDraw->psc; + struct glx_screen *psc = glxDraw->psc; Display *dpy = psc->dpy; Drawable drawable; @@ -238,11 +346,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, @@ -255,7 +362,7 @@ __glXDRIGetDrawableInfo(__DRIdrawable * drawable, void *loaderPrivate) { __GLXDRIdrawable *glxDraw = loaderPrivate; - __GLXscreenConfigs *psc = glxDraw->psc; + struct glx_screen *psc = glxDraw->psc; Display *dpy = psc->dpy; return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable, @@ -266,8 +373,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[] = { @@ -293,8 +401,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; @@ -314,7 +422,7 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, drm_handle_t hFB; int junk; const __DRIconfig **driver_configs; - __GLcontextModes *visual; + struct glx_config *visual, *configs = NULL, *visuals = NULL; /* DRI protocol version. */ dri_version.major = driDpy->driMajor; @@ -332,7 +440,7 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, fd = drmOpenOnce(NULL, BusID, &newlyopened); - Xfree(BusID); /* No longer needed */ + free(BusID); /* No longer needed */ if (fd < 0) { ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd)); @@ -362,7 +470,7 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, goto handle_error; } - /* Get device name (like "tdfx") and the ddx version numbers. + /* Get device name (like "radeon") and the ddx version numbers. * We'll check the version in each DRI driver's "createNewScreen" * function. */ if (!XF86DRIGetClientDriverName(dpy, scrn, @@ -373,7 +481,7 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, goto handle_error; } - Xfree(driverName); /* No longer needed. */ + free(driverName); /* No longer needed. */ /* * Get device-specific info. pDevPriv will point to a struct @@ -385,7 +493,7 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, &framebuffer.size, &framebuffer.stride, &framebuffer.dev_priv_size, &framebuffer.dev_priv)) { - ErrorMessageF("XF86DRIGetDeviceInfo failed"); + ErrorMessageF("XF86DRIGetDeviceInfo failed\n"); goto handle_error; } @@ -396,7 +504,7 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * 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; } @@ -405,7 +513,7 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * 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; } @@ -420,12 +528,22 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, &driver_configs, psc); if (psp == NULL) { - ErrorMessageF("Calling driver entry point failed"); + ErrorMessageF("Calling driver entry point failed\n"); goto handle_error; } - psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); - psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); + configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); + visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); + + 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; + glx_config_destroy_list(psc->base.visuals); + psc->base.visuals = visuals; psc->driver_configs = driver_configs; @@ -433,35 +551,39 @@ 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) { - XVisualInfo template; + for (visual = psc->base.visuals; visual; visual = visual->next) { + 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)) visual->visualRating = GLX_NON_CONFORMANT_CONFIG; - XFree(visuals); + free(visuals); } } return psp; handle_error: + if (configs) + glx_config_destroy_list(configs); + if (visuals) + glx_config_destroy_list(visuals); + 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); + free(framebuffer.dev_priv); if (fd >= 0) drmCloseOnce(fd); @@ -474,80 +596,124 @@ CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, } static void -driDestroyContext(__GLXDRIcontext * context, - __GLXscreenConfigs * psc, Display * dpy) +dri_destroy_context(struct glx_context * context) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + struct dri_context *pcp = (struct dri_context *) context; + struct dri_screen *psc = (struct dri_screen *) context->psc; + + driReleaseDrawables(&pcp->base); + + free((char *) context->extensions); (*psc->core->destroyContext) (pcp->driContext); - XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); - Xfree(pcp); + XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID); + free(pcp); } -static Bool -driBindContext(__GLXDRIcontext * context, - __GLXDRIdrawable * draw, __GLXDRIdrawable * read) +static int +dri_bind_context(struct glx_context *context, struct glx_context *old, + GLXDrawable draw, GLXDrawable 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 *pdraw, *pread; - return (*core->bindContext) (pcp->driContext, - draw->driDrawable, read->driDrawable); + pdraw = (struct dri_drawable *) driFetchDrawable(context, draw); + pread = (struct dri_drawable *) driFetchDrawable(context, read); + + driReleaseDrawables(&pcp->base); + + if (pdraw == NULL || pread == NULL) + return GLXBadDrawable; + + if ((*psc->core->bindContext) (pcp->driContext, + pdraw->driDrawable, pread->driDrawable)) + return Success; + + return GLXBadContext; } static void -driUnbindContext(__GLXDRIcontext * context) +dri_unbind_context(struct glx_context *context, struct glx_context *new) { - __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 = { + .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 * +dri_create_context(struct glx_screen *base, + struct glx_config *config_base, + struct glx_context *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; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; - if (!psc || !psc->driScreen) + if (!psc->base.driScreen) return NULL; + /* Check the renderType value */ + if (!validate_renderType_against_config(config_base, renderType)) + return NULL; + if (shareList) { - pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; + /* If the shareList context is not a DRI context, we cannot possibly + * create a DRI context that shares it. + */ + if (shareList->vtable->destroy != dri_destroy_context) { + return NULL; + } + + pcp_shared = (struct dri_context *) shareList; shared = pcp_shared->driContext; } - pcp = Xmalloc(sizeof *pcp); + pcp = calloc(1, sizeof *pcp); if (pcp == NULL) return NULL; - pcp->psc = psc; - if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr, - mode->visualID, + 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)) { - Xfree(pcp); + free(pcp); return NULL; } 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); - Xfree(pcp); + XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID); + free(pcp); return NULL; } - pcp->base.destroyContext = driDestroyContext; - pcp->base.bindContext = driBindContext; - pcp->base.unbindContext = driUnbindContext; + pcp->base.vtable = &dri_context_vtable; return &pcp->base; } @@ -555,116 +721,201 @@ 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); - Xfree(pdraw); + (*psc->core->destroyDrawable) (pdp->driDrawable); + XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable); + free(pdraw); } static __GLXDRIdrawable * -driCreateDrawable(__GLXscreenConfigs * psc, +driCreateDrawable(struct glx_screen *base, XID xDrawable, - GLXDrawable drawable, const __GLcontextModes * modes) + GLXDrawable drawable, struct glx_config *config_base) { - __GLXDRIdrawable *pdraw; drm_drawable_t hwDrawable; void *empty_attribute_list = NULL; - __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; + 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 = calloc(1, sizeof *pdp); + if (!pdp) return NULL; - pdraw->drawable = drawable; - pdraw->psc = psc; + 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)) { + free(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); + free(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) + int64_t unused3, Bool flush) { - (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable); + 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) { - (*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; + + if (flush) { + glFlush(); + } + + (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable, + x, y, width, height); } static void -driDestroyScreen(__GLXscreenConfigs * psc) +driDestroyScreen(struct glx_screen *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 __GLXDRIscreen * -driCreateScreen(__GLXscreenConfigs * psc, int screen, - __GLXdisplayPrivate * priv) +static int +driSetSwapInterval(__GLXDRIdrawable *pdraw, int interval) +{ + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + + 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; +} + +static int +driGetSwapInterval(__GLXDRIdrawable *pdraw) +{ + struct dri_drawable *pdp = (struct dri_drawable *) pdraw; + + if (pdraw != NULL) { + struct dri_screen *psc = (struct dri_screen *) pdraw->psc; + + if (psc->swapControl != NULL) + return psc->swapControl->getSwapInterval(pdp->driDrawable); + } + return 0; +} + +/* Bind DRI1 specific extensions */ +static void +driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions) { - __GLXDRIdisplayPrivate *pdp; + 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 = { + .create_context = dri_create_context, + .create_context_attribs = NULL, + .query_renderer_integer = NULL, + .query_renderer_string = NULL, +}; + +static struct glx_screen * +driCreateScreen(int screen, struct glx_display *priv) +{ + 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 = calloc(1, sizeof *psc); + if (psc == NULL) return NULL; - if (!driGetDriverName(priv->dpy, screen, &driverName)) { - Xfree(psp); + if (!glx_screen_init(&psc->base, screen, priv)) { + free(psc); return NULL; } - psc->driver = driOpenDriver(driverName); - Xfree(driverName); - if (psc->driver == NULL) { - Xfree(psp); - return NULL; + if (!driGetDriverName(priv->dpy, screen, &driverName)) { + goto cleanup; } - extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); + extensions = driOpenDriver(driverName, &psc->driver); if (extensions == NULL) { ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); - Xfree(psp); - return NULL; + goto cleanup; } for (i = 0; extensions[i]; i++) { @@ -674,33 +925,46 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen, psc->legacy = (__DRIlegacyExtension *) extensions[i]; } - if (psc->core == NULL || psc->legacy == NULL) { - Xfree(psp); - return NULL; - } + if (psc->core == NULL || psc->legacy == NULL) + goto cleanup; - pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay; - psc->__driScreen = CallCreateNewScreen(psc->dpy, screen, psc, pdp); - if (psc->__driScreen == NULL) { - dlclose(psc->driver); - Xfree(psp); - return NULL; - } + pdp = (struct dri_display *) priv->driDisplay; + psc->driScreen = + CallCreateNewScreen(psc->base.dpy, screen, psc, pdp); + if (psc->driScreen == NULL) + goto cleanup; - 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; - return psp; + 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); + free(psc); + + return NULL; } /* Called from __glXFreeDisplayPrivate. @@ -708,7 +972,7 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen, static void driDestroyDisplay(__GLXDRIdisplay * dpy) { - Xfree(dpy); + free(dpy); } /* @@ -719,7 +983,7 @@ driDestroyDisplay(__GLXDRIdisplay * dpy) _X_HIDDEN __GLXDRIdisplay * driCreateDisplay(Display * dpy) { - __GLXDRIdisplayPrivate *pdpyp; + struct dri_display *pdpyp; int eventBase, errorBase; int major, minor, patch; @@ -731,7 +995,7 @@ driCreateDisplay(Display * dpy) return NULL; } - pdpyp = Xmalloc(sizeof *pdpyp); + pdpyp = malloc(sizeof *pdpyp); if (!pdpyp) { return NULL; }