#include "glxclient.h"
#include "xf86dri.h"
#include "dri2.h"
-#include "sarea.h"
+#include "dri_sarea.h"
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/mman.h>
__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).
+ * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
* Return True for success, False for failure.
*/
static Bool
Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
if (ret)
- Xfree(dev);
+ free(dev);
return ret;
}
* 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];
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 = 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).
*
*
* 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)
}
static const __DRIdamageExtension damageExtension = {
- {__DRI_DAMAGE, __DRI_DAMAGE_VERSION},
- __glXReportDamage,
-};
+ .base = {__DRI_DAMAGE, 1 },
-#endif
+ .reportDamage = __glXReportDamage,
+};
static GLboolean
__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[] = {
drm_handle_t hFB;
int junk;
const __DRIconfig **driver_configs;
- struct glx_config *visual;
+ struct glx_config *visual, *configs = NULL, *visuals = NULL;
/* DRI protocol version. */
dri_version.major = driDpy->driMajor;
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));
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,
goto handle_error;
}
- Xfree(driverName); /* No longer needed. */
+ free(driverName); /* No longer needed. */
/*
* Get device-specific info. pDevPriv will point to a struct
&framebuffer.size, &framebuffer.stride,
&framebuffer.dev_priv_size,
&framebuffer.dev_priv)) {
- ErrorMessageF("XF86DRIGetDeviceInfo failed");
+ ErrorMessageF("XF86DRIGetDeviceInfo failed\n");
goto handle_error;
}
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;
}
*/
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;
}
&driver_configs, psc);
if (psp == NULL) {
- ErrorMessageF("Calling driver entry point failed");
+ ErrorMessageF("Calling driver entry point failed\n");
goto handle_error;
}
- psc->base.configs =
- driConvertConfigs(psc->core, psc->base.configs, driver_configs);
- psc->base.visuals =
- driConvertConfigs(psc->core, psc->base.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;
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);
driReleaseDrawables(&pcp->base);
- if (context->xid)
- glx_send_destroy_context(psc->base.dpy, context->xid);
-
- if (context->extensions)
- XFree((char *) context->extensions);
+ free((char *) context->extensions);
(*psc->core->destroyContext) (pcp->driContext);
XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
- Xfree(pcp);
+ free(pcp);
}
static int
}
static const struct glx_context_vtable dri_context_vtable = {
- dri_destroy_context,
- dri_bind_context,
- dri_unbind_context,
- NULL,
- NULL,
- DRI_glXUseXFont,
- NULL,
- NULL,
+ .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 *
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.
+ */
+ 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;
- memset(pcp, 0, sizeof *pcp);
if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
- Xfree(pcp);
+ 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;
}
renderType, shared, hwContext, pcp);
if (pcp->driContext == NULL) {
XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
- Xfree(pcp);
+ free(pcp);
return NULL;
}
(*psc->core->destroyDrawable) (pdp->driDrawable);
XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable);
- Xfree(pdraw);
+ free(pdraw);
}
static __GLXDRIdrawable *
if (xDrawable != drawable)
return NULL;
- pdp = Xmalloc(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;
if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr,
drawable, &hwDrawable)) {
- Xfree(pdp);
+ free(pdp);
return NULL;
}
if (!pdp->driDrawable) {
XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable);
- Xfree(pdp);
+ free(pdp);
return NULL;
}
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);
}
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;
}
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;
}
}
static const struct glx_screen_vtable dri_screen_vtable = {
- dri_create_context
+ .create_context = dri_create_context,
+ .create_context_attribs = NULL,
+ .query_renderer_integer = NULL,
+ .query_renderer_string = NULL,
};
static struct glx_screen *
char *driverName;
int i;
- psc = Xcalloc(1, sizeof *psc);
+ psc = calloc(1, sizeof *psc);
if (psc == NULL)
return NULL;
- memset(psc, 0, sizeof *psc);
if (!glx_screen_init(&psc->base, screen, priv)) {
- Xfree(psc);
+ free(psc);
return NULL;
}
}
psc->driver = driOpenDriver(driverName);
- Xfree(driverName);
if (psc->driver == NULL)
goto cleanup;
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);
- Xfree(psc);
+ free(psc);
return NULL;
}
static void
driDestroyDisplay(__GLXDRIdisplay * dpy)
{
- Xfree(dpy);
+ free(dpy);
}
/*
return NULL;
}
- pdpyp = Xmalloc(sizeof *pdpyp);
+ pdpyp = malloc(sizeof *pdpyp);
if (!pdpyp) {
return NULL;
}