#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., "i965", "radeon", "nouveau", etc).
* 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];
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).
*
*
* 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[] = {
&systemTimeExtension.base,
&getDrawableInfoExtension.base,
-#ifdef XDAMAGE_1_1_INTERFACE
&damageExtension.base,
-#endif
NULL
};
&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;
}
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;
* 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))
}
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 *
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.
return NULL;
}
+ pcp->base.renderType = renderType;
+
if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr,
config->base.visualID,
&pcp->hwContextID, &hwContext)) {
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,
- NULL
+ .create_context = dri_create_context,
+ .create_context_attribs = NULL,
+ .query_renderer_integer = NULL,
+ .query_renderer_string = NULL,
};
static struct glx_screen *
goto cleanup;
}
- psc->driver = driOpenDriver(driverName);
- if (psc->driver == NULL)
- 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());
goto cleanup;