SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
-/* $XFree86: xc/lib/GL/dri/dri_glx.c,v 1.14 2003/07/16 00:54:00 dawes Exp $ */
/*
* Authors:
#ifdef GLX_DIRECT_RENDERING
-#include <unistd.h>
-#include <X11/Xlibint.h>
-#include <X11/extensions/Xext.h>
-#include <X11/extensions/extutil.h>
-#include "glheader.h"
+#include <X11/Xlib.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/Xdamage.h>
#include "glxclient.h"
+#include "glcontextmodes.h"
#include "xf86dri.h"
#include "sarea.h"
-#include <stdio.h>
#include <dlfcn.h>
-#include "dri_glx.h"
#include <sys/types.h>
-#include <stdarg.h>
-#include "glcontextmodes.h"
#include <sys/mman.h>
#include "xf86drm.h"
+#include "dri_common.h"
+typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
+typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
-#ifndef RTLD_NOW
-#define RTLD_NOW 0
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-
-#ifndef DEFAULT_DRIVER_DIR
-/* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */
-#define DEFAULT_DRIVER_DIR "/usr/X11R6/lib/modules/dri"
-#endif
-
-static void InfoMessageF(const char *f, ...)
-{
- va_list args;
- const char *env;
-
- if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) {
- fprintf(stderr, "libGL: ");
- va_start(args, f);
- vfprintf(stderr, f, args);
- va_end(args);
- }
-}
-
-/**
- * Print error to stderr, unless LIBGL_DEBUG=="quiet".
- */
-static void ErrorMessageF(const char *f, ...)
-{
- va_list args;
- const char *env;
-
- if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) {
- fprintf(stderr, "libGL error: ");
- va_start(args, f);
- vfprintf(stderr, f, args);
- va_end(args);
- }
-}
-
-
-/**
- * Extract the ith directory path out of a colon-separated list of paths. No
- * more than \c dirLen characters, including the terminating \c NUL, will be
- * written to \c dir.
- *
- * \param index Index of path to extract (starting at zero)
- * \param paths The colon-separated list of paths
- * \param dirLen Maximum length of result to store in \c dir
- * \param dir Buffer to hold the extracted directory path
- *
- * \returns
- * The number of characters that would have been written to \c dir had there
- * been enough room. This does not include the terminating \c NUL. When
- * extraction fails, zero will be returned.
- *
- * \todo
- * It seems like this function could be rewritten to use \c strchr.
- */
-static size_t
-ExtractDir(int index, const char *paths, int dirLen, char *dir)
-{
- int i, len;
- const char *start, *end;
-
- /* find ith colon */
- start = paths;
- i = 0;
- while (i < index) {
- if (*start == ':') {
- i++;
- start++;
- }
- else if (*start == 0) {
- /* end of string and couldn't find ith colon */
- dir[0] = 0;
- return 0;
- }
- else {
- start++;
- }
- }
-
- while (*start == ':')
- start++;
-
- /* find next colon, or end of string */
- end = start + 1;
- while (*end != ':' && *end != 0) {
- end++;
- }
-
- /* copy string between <start> and <end> into result string */
- len = end - start;
- if (len > dirLen - 1)
- len = dirLen - 1;
- strncpy(dir, start, len);
- dir[len] = 0;
+struct __GLXDRIdisplayPrivateRec {
+ __GLXDRIdisplay base;
- return( end - start );
-}
-
-
-/**
- * Versioned name of the expected \c __driCreateNewScreen function.
- *
- * The version of the last incompatible loader/driver inteface change is
- * appended to the name of the \c __driCreateNewScreen function. This
- * prevents loaders from trying to load drivers that are too old.
- */
-static const char createNewScreenName[] = __DRI_CREATE_NEW_SCREEN_STRING;
-
-
-/**
- * Try to \c dlopen the named driver.
- *
- * This function adds the "_dri.so" suffix to the driver name and searches the
- * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
- * order to find the driver.
- *
- * \param driverName - a name like "tdfx", "i810", "mga", etc.
- *
- * \returns
- * A handle from \c dlopen, or \c NULL if driver file not found.
- */
-static void *OpenDriver(const char *driverName)
-{
- void *glhandle = NULL;
- char *libPaths = NULL;
- char libDir[1000];
- char realDriverName[200];
- void *handle = NULL;
- int i;
-
- /* Attempt to make sure libGL symbols will be visible to the driver */
- glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL);
-
- if (geteuid() == getuid()) {
- /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
- libPaths = getenv("LIBGL_DRIVERS_PATH");
- if (!libPaths)
- libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
- }
- if (!libPaths)
- libPaths = DEFAULT_DRIVER_DIR;
-
- for ( i = 0 ; ExtractDir(i, libPaths, 1000, libDir) != 0 ; i++ ) {
- /* If TLS support is enabled, try to open the TLS version of the driver
- * binary first. If that fails, try the non-TLS version.
- */
-#ifdef GLX_USE_TLS
- snprintf(realDriverName, 200, "%s/tls/%s_dri.so", libDir, driverName);
- InfoMessageF("OpenDriver: trying %s\n", realDriverName);
- handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
-#endif
-
- if ( handle == NULL ) {
- snprintf(realDriverName, 200, "%s/%s_dri.so", libDir, driverName);
- InfoMessageF("OpenDriver: trying %s\n", realDriverName);
- handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
- }
-
- if ( handle != NULL )
- break;
- else
- ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
- }
-
- if (!handle)
- ErrorMessageF("unable to load driver: %s_dri.so\n", driverName);
-
- if (glhandle)
- dlclose(glhandle);
-
- return handle;
-}
+ /*
+ ** XFree86-DRI version information
+ */
+ int driMajor;
+ int driMinor;
+ int driPatch;
+};
+struct __GLXDRIcontextPrivateRec {
+ __GLXDRIcontext base;
+ __DRIcontext *driContext;
+ XID hwContextID;
+ __GLXscreenConfigs *psc;
+};
/*
* Given a display pointer and screen number, determine the name of
* the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
* Return True for success, False for failure.
*/
-static Bool GetDriverName(Display *dpy, int scrNum, char **driverName)
+static Bool driGetDriverName(Display *dpy, int scrNum, char **driverName)
{
int directCapable;
Bool b;
return True;
}
-
-/*
- * Given a display pointer and screen number, return a __DRIdriver handle.
- * Return NULL if anything goes wrong.
- */
-static void *driGetDriver(Display *dpy, int scrNum)
-{
- char *driverName;
- void *ret;
-
- if (GetDriverName(dpy, scrNum, &driverName)) {
- ret = OpenDriver(driverName);
- if (driverName)
- Xfree(driverName);
- return ret;
- }
- return NULL;
-}
-
/*
* Exported function for querying the DRI driver for a given screen.
*
PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) {
static char ret[32];
char *driverName;
- if (GetDriverName(dpy, scrNum, &driverName)) {
+ if (driGetDriverName(dpy, scrNum, &driverName)) {
int len;
if (!driverName)
return NULL;
return NULL;
}
-
/*
* Exported function for obtaining a driver's option list (UTF-8 encoded XML).
*
*
* Note: The driver remains opened after this function returns.
*/
-PUBLIC const char *glXGetDriverConfig (const char *driverName) {
- void *handle = OpenDriver (driverName);
+PUBLIC const char *glXGetDriverConfig (const char *driverName)
+{
+ void *handle = driOpenDriver (driverName);
if (handle)
return dlsym (handle, "__driConfigOptions");
else
return NULL;
}
-static void
-filter_modes( __GLcontextModes ** server_modes,
- const __GLcontextModes * driver_modes )
-{
- __GLcontextModes * m;
- __GLcontextModes ** prev_next;
- const __GLcontextModes * check;
-
- if (driver_modes == NULL) {
- fprintf(stderr, "libGL warning: 3D driver returned no fbconfigs.\n");
- return;
- }
-
- /* For each mode in server_modes, check to see if a matching mode exists
- * in driver_modes. If not, then the mode is not available.
- */
-
- prev_next = server_modes;
- for ( m = *prev_next ; m != NULL ; m = *prev_next ) {
- GLboolean do_delete = GL_TRUE;
-
- for ( check = driver_modes ; check != NULL ; check = check->next ) {
- if ( _gl_context_modes_are_same( m, check ) ) {
- do_delete = GL_FALSE;
- break;
- }
- }
-
- /* The 3D has to support all the modes that match the GLX visuals
- * sent from the X server.
- */
- if ( do_delete && (m->visualID != 0) ) {
- do_delete = GL_FALSE;
-
- /* don't warn for this visual (Novell #247471 / X.Org #6689) */
- if (m->visualRating != GLX_NON_CONFORMANT_CONFIG) {
- fprintf(stderr, "libGL warning: 3D driver claims to not "
- "support visual 0x%02x\n", m->visualID);
- }
- }
-
- if ( do_delete ) {
- *prev_next = m->next;
-
- m->next = NULL;
- _gl_context_modes_destroy( m );
- }
- else {
- prev_next = & m->next;
- }
- }
-}
-
#ifdef XDAMAGE_1_1_INTERFACE
+
static GLboolean has_damage_post(Display *dpy)
{
static GLboolean inited = GL_FALSE;
return has_damage;
}
-#endif /* XDAMAGE_1_1_INTERFACE */
static void __glXReportDamage(__DRIdrawable *driDraw,
int x, int y,
drm_clip_rect_t *rects, int num_rects,
- GLboolean front_buffer)
+ GLboolean front_buffer,
+ void *loaderPrivate)
{
-#ifdef XDAMAGE_1_1_INTERFACE
XRectangle *xrects;
XserverRegion region;
int i;
int x_off, y_off;
- __GLXdrawable *glxDraw =
- containerOf(driDraw, __GLXdrawable, driDrawable);
+ __GLXDRIdrawable *glxDraw = loaderPrivate;
__GLXscreenConfigs *psc = glxDraw->psc;
Display *dpy = psc->dpy;
Drawable drawable;
} else{
x_off = 0;
y_off = 0;
- drawable = glxDraw->drawable;
+ drawable = glxDraw->xDrawable;
}
xrects = malloc(sizeof(XRectangle) * num_rects);
free(xrects);
XDamageAdd(dpy, drawable, region);
XFixesDestroyRegion(dpy, region);
-#endif
}
+static const __DRIdamageExtension damageExtension = {
+ { __DRI_DAMAGE, __DRI_DAMAGE_VERSION },
+ __glXReportDamage,
+};
+
+#endif
+
static GLboolean
__glXDRIGetDrawableInfo(__DRIdrawable *drawable,
unsigned int *index, unsigned int *stamp,
int *X, int *Y, int *W, int *H,
int *numClipRects, drm_clip_rect_t ** pClipRects,
int *backX, int *backY,
- int *numBackClipRects, drm_clip_rect_t **pBackClipRects)
+ int *numBackClipRects, drm_clip_rect_t **pBackClipRects,
+ void *loaderPrivate)
{
- __GLXdrawable *glxDraw =
- containerOf(drawable, __GLXdrawable, driDrawable);
+ __GLXDRIdrawable *glxDraw = loaderPrivate;
__GLXscreenConfigs *psc = glxDraw->psc;
Display *dpy = psc->dpy;
numBackClipRects, pBackClipRects);
}
-
-/**
- * Table of functions exported by the loader to the driver.
- */
-static const __DRIcontextModesExtension contextModesExtension = {
- { __DRI_CONTEXT_MODES, __DRI_CONTEXT_MODES_VERSION },
- _gl_context_modes_create,
- _gl_context_modes_destroy,
-};
-
-static const __DRIsystemTimeExtension systemTimeExtension = {
- { __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION },
- __glXGetUST,
- __driGetMscRateOML,
-};
-
static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
{ __DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION },
__glXDRIGetDrawableInfo
};
-static const __DRIdamageExtension damageExtension = {
- { __DRI_DAMAGE, __DRI_DAMAGE_VERSION },
- __glXReportDamage,
-};
-
static const __DRIextension *loader_extensions[] = {
- &contextModesExtension.base,
&systemTimeExtension.base,
&getDrawableInfoExtension.base,
+#ifdef XDAMAGE_1_1_INTERFACE
&damageExtension.base,
+#endif
NULL
};
+#ifndef GLX_USE_APPLEGL
/**
* Perform the required libGL-side initialization and call the client-side
* \c __driCreateNewScreen function.
* \returns A pointer to the \c __DRIscreenPrivate structure returned by
* the client-side driver on success, or \c NULL on failure.
- *
- * \todo This function needs to be modified to remove context-modes from the
- * list stored in the \c __GLXscreenConfigsRec to match the list
- * returned by the client-side driver.
*/
static void *
CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
- __DRIdisplay * driDpy,
- PFNCREATENEWSCREENFUNC createNewScreen)
+ __GLXDRIdisplayPrivate * driDpy)
{
- __DRIscreenPrivate *psp = NULL;
-#ifndef GLX_USE_APPLEGL
+ void *psp = NULL;
drm_handle_t hSAREA;
drmAddress pSAREA = MAP_FAILED;
char *BusID;
__DRIframebuffer framebuffer;
int fd = -1;
int status;
- const char * err_msg;
- const char * err_extra;
- dri_version.major = driDpy->private->driMajor;
- dri_version.minor = driDpy->private->driMinor;
- dri_version.patch = driDpy->private->driPatch;
+ drm_magic_t magic;
+ drmVersionPtr version;
+ int newlyopened;
+ char *driverName;
+ drm_handle_t hFB;
+ int junk;
+ const __DRIconfig **driver_configs;
-
- err_msg = "XF86DRIOpenConnection";
- err_extra = NULL;
+ /* DRI protocol version. */
+ dri_version.major = driDpy->driMajor;
+ dri_version.minor = driDpy->driMinor;
+ dri_version.patch = driDpy->driPatch;
framebuffer.base = MAP_FAILED;
framebuffer.dev_priv = NULL;
- if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
- int newlyopened;
- fd = drmOpenOnce(NULL,BusID, &newlyopened);
- Xfree(BusID); /* No longer needed */
-
- err_msg = "open DRM";
- err_extra = strerror( -fd );
-
- if (fd >= 0) {
- drm_magic_t magic;
-
- err_msg = "drmGetMagic";
- err_extra = NULL;
-
- if (!drmGetMagic(fd, &magic)) {
- drmVersionPtr version = drmGetVersion(fd);
- if (version) {
- drm_version.major = version->version_major;
- drm_version.minor = version->version_minor;
- drm_version.patch = version->version_patchlevel;
- drmFreeVersion(version);
- }
- else {
- drm_version.major = -1;
- drm_version.minor = -1;
- drm_version.patch = -1;
- }
-
- err_msg = "XF86DRIAuthConnection";
- if (!newlyopened || XF86DRIAuthConnection(dpy, scrn, magic)) {
- char *driverName;
-
- /*
- * Get device name (like "tdfx") and the ddx version
- * numbers. We'll check the version in each DRI driver's
- * "createNewScreen" function.
- */
- err_msg = "XF86DRIGetClientDriverName";
- if (XF86DRIGetClientDriverName(dpy, scrn,
- &ddx_version.major,
- &ddx_version.minor,
- &ddx_version.patch,
- &driverName)) {
- drm_handle_t hFB;
- int junk;
-
- /* No longer needed. */
- Xfree( driverName );
-
-
- /*
- * Get device-specific info. pDevPriv will point to a struct
- * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
- * that has information about the screen size, depth, pitch,
- * ancilliary buffers, DRM mmap handles, etc.
- */
- err_msg = "XF86DRIGetDeviceInfo";
- if (XF86DRIGetDeviceInfo(dpy, scrn,
- &hFB,
- &junk,
- &framebuffer.size,
- &framebuffer.stride,
- &framebuffer.dev_priv_size,
- &framebuffer.dev_priv)) {
- framebuffer.width = DisplayWidth(dpy, scrn);
- framebuffer.height = DisplayHeight(dpy, scrn);
-
- /*
- * Map the framebuffer region.
- */
- status = drmMap(fd, hFB, framebuffer.size,
- (drmAddressPtr)&framebuffer.base);
-
- err_msg = "drmMap of framebuffer";
- err_extra = strerror( -status );
-
- if ( status == 0 ) {
- /*
- * Map the SAREA region. Further mmap regions
- * may be setup in each DRI driver's
- * "createNewScreen" function.
- */
- status = drmMap(fd, hSAREA, SAREA_MAX,
- &pSAREA);
-
- err_msg = "drmMap of sarea";
- err_extra = strerror( -status );
-
- if ( status == 0 ) {
- __GLcontextModes * driver_modes = NULL;
-
- err_msg = "InitDriver";
- err_extra = NULL;
- psp = (*createNewScreen)(scrn,
- &psc->driScreen,
- & ddx_version,
- & dri_version,
- & drm_version,
- & framebuffer,
- pSAREA,
- fd,
- loader_extensions,
- & driver_modes );
-
- filter_modes(&psc->configs, driver_modes);
- filter_modes(&psc->visuals, driver_modes);
- _gl_context_modes_destroy(driver_modes);
- }
- }
- }
- }
- }
- }
- }
+ if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
+ ErrorMessageF("XF86DRIOpenConnection failed\n");
+ goto handle_error;
}
- if ( psp == NULL ) {
- if ( pSAREA != MAP_FAILED ) {
- (void)drmUnmap(pSAREA, SAREA_MAX);
- }
+ fd = drmOpenOnce(NULL, BusID, &newlyopened);
- if ( framebuffer.base != MAP_FAILED ) {
- (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
- }
+ Xfree(BusID); /* No longer needed */
- if ( framebuffer.dev_priv != NULL ) {
- Xfree(framebuffer.dev_priv);
- }
+ if (fd < 0) {
+ ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
+ goto handle_error;
+ }
- if ( fd >= 0 ) {
- (void)drmCloseOnce(fd);
- }
+ if (drmGetMagic(fd, &magic)) {
+ ErrorMessageF("drmGetMagic failed\n");
+ goto handle_error;
+ }
- (void)XF86DRICloseConnection(dpy, scrn);
+ version = drmGetVersion(fd);
+ if (version) {
+ drm_version.major = version->version_major;
+ drm_version.minor = version->version_minor;
+ drm_version.patch = version->version_patchlevel;
+ drmFreeVersion(version);
+ }
+ else {
+ drm_version.major = -1;
+ drm_version.minor = -1;
+ drm_version.patch = -1;
+ }
- if ( err_extra != NULL ) {
- fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
- err_extra);
- }
- else {
- fprintf(stderr, "libGL error: %s failed\n", err_msg );
- }
+ if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
+ ErrorMessageF("XF86DRIAuthConnection failed\n");
+ goto handle_error;
+ }
- fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
+ /* Get device name (like "tdfx") and the ddx version numbers.
+ * We'll check the version in each DRI driver's "createNewScreen"
+ * function. */
+ if (!XF86DRIGetClientDriverName(dpy, scrn,
+ &ddx_version.major,
+ &ddx_version.minor,
+ &ddx_version.patch,
+ &driverName)) {
+ ErrorMessageF("XF86DRIGetClientDriverName failed\n");
+ goto handle_error;
+ }
+
+ Xfree(driverName); /* No longer needed. */
+
+ /*
+ * Get device-specific info. pDevPriv will point to a struct
+ * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
+ * has information about the screen size, depth, pitch, ancilliary
+ * buffers, DRM mmap handles, etc.
+ */
+ if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
+ &framebuffer.size, &framebuffer.stride,
+ &framebuffer.dev_priv_size, &framebuffer.dev_priv)) {
+ ErrorMessageF("XF86DRIGetDeviceInfo failed");
+ goto handle_error;
+ }
+
+ framebuffer.width = DisplayWidth(dpy, scrn);
+ framebuffer.height = DisplayHeight(dpy, scrn);
+
+ /* Map the framebuffer region. */
+ status = drmMap(fd, hFB, framebuffer.size,
+ (drmAddressPtr)&framebuffer.base);
+ if (status != 0) {
+ ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
+ goto handle_error;
+ }
+
+ /* Map the SAREA region. Further mmap regions may be setup in
+ * each DRI driver's "createNewScreen" function.
+ */
+ status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
+ if (status != 0) {
+ ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
+ goto handle_error;
}
-#endif /* !GLX_USE_APPLEGL */
+
+ psp = (*psc->legacy->createNewScreen)(scrn,
+ &ddx_version,
+ &dri_version,
+ &drm_version,
+ &framebuffer,
+ pSAREA,
+ fd,
+ loader_extensions,
+ &driver_configs,
+ psc);
+
+ if (psp == NULL) {
+ ErrorMessageF("Calling driver entry point failed");
+ goto handle_error;
+ }
+
+ psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
+ psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
return psp;
+
+ handle_error:
+ 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);
+
+ if (fd >= 0)
+ drmCloseOnce(fd);
+
+ XF86DRICloseConnection(dpy, scrn);
+
+ ErrorMessageF("reverting to software direct rendering\n");
+
+ return NULL;
}
-void
-driCreateScreen(__GLXscreenConfigs *psc, int screen,
- __GLXdisplayPrivate *priv)
+#else /* !GLX_USE_APPLEGL */
+
+static void *
+CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
+ __GLXDRIdisplayPrivate * driDpy)
{
- PFNCREATENEWSCREENFUNC createNewScreen;
+ return NULL;
+}
- if (priv->driDisplay.private == NULL)
- return;
+#endif /* !GLX_USE_APPLEGL */
- /* Create drawable hash */
- psc->drawHash = __glxHashCreate();
- if ( psc->drawHash == NULL )
- return;
+static void driDestroyContext(__GLXDRIcontext *context,
+ __GLXscreenConfigs *psc, Display *dpy)
+{
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+
+ (*psc->core->destroyContext)(pcp->driContext);
- /* Initialize per screen dynamic client GLX extensions */
- psc->ext_list_first_time = GL_TRUE;
+ XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+ Xfree(pcp);
+}
- psc->driver = driGetDriver(priv->dpy, screen);
- createNewScreen = dlsym(psc->driver, createNewScreenName);
- if (createNewScreenName == NULL)
- return;
+static Bool driBindContext(__GLXDRIcontext *context,
+ __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
+{
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+ const __DRIcoreExtension *core = pcp->psc->core;
- psc->driScreen.private =
- CallCreateNewScreen(psc->dpy, screen, psc,
- &priv->driDisplay, createNewScreen);
- if (psc->driScreen.private != NULL)
- __glXScrEnableDRIExtension(psc);
+ return (*core->bindContext)(pcp->driContext,
+ draw->driDrawable,
+ read->driDrawable);
}
-void driDestroyScreen(__GLXscreenConfigs *psc)
+static void driUnbindContext(__GLXDRIcontext *context)
+{
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+ const __DRIcoreExtension *core = pcp->psc->core;
+
+ (*core->unbindContext)(pcp->driContext);
+}
+
+static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc,
+ const __GLcontextModes *mode,
+ GLXContext gc,
+ GLXContext shareList, int renderType)
+{
+ __GLXDRIcontextPrivate *pcp, *pcp_shared;
+ drm_context_t hwContext;
+ __DRIcontext *shared = NULL;
+ __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
+
+ if (!psc || !psc->driScreen)
+ return NULL;
+
+ if (shareList) {
+ pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
+ shared = pcp_shared->driContext;
+ }
+
+ pcp = Xmalloc(sizeof *pcp);
+ if (pcp == NULL)
+ return NULL;
+
+ pcp->psc = psc;
+ if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
+ mode->visualID,
+ &pcp->hwContextID, &hwContext)) {
+ Xfree(pcp);
+ return NULL;
+ }
+
+ pcp->driContext =
+ (*psc->legacy->createNewContext)(psc->__driScreen,
+ config->driConfig,
+ renderType,
+ shared,
+ hwContext,
+ pcp);
+ if (pcp->driContext == NULL) {
+ XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+ Xfree(pcp);
+ return NULL;
+ }
+
+ pcp->base.destroyContext = driDestroyContext;
+ pcp->base.bindContext = driBindContext;
+ pcp->base.unbindContext = driUnbindContext;
+
+ return &pcp->base;
+}
+
+static void driDestroyDrawable(__GLXDRIdrawable *pdraw)
+{
+ __GLXscreenConfigs *psc = pdraw->psc;
+
+ (*psc->core->destroyDrawable)(pdraw->driDrawable);
+ XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
+ Xfree(pdraw);
+}
+
+static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc,
+ XID xDrawable,
+ GLXDrawable drawable,
+ const __GLcontextModes *modes)
+{
+ __GLXDRIdrawable *pdraw;
+ drm_drawable_t hwDrawable;
+ void *empty_attribute_list = NULL;
+ __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+
+ /* Old dri can't handle GLX 1.3+ drawable constructors. */
+ if (xDrawable != drawable)
+ return NULL;
+
+ pdraw = Xmalloc(sizeof(*pdraw));
+ if (!pdraw)
+ return NULL;
+
+ pdraw->drawable = drawable;
+ pdraw->psc = psc;
+
+ if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable))
+ return NULL;
+
+ /* Create a new drawable */
+ pdraw->driDrawable =
+ (*psc->legacy->createNewDrawable)(psc->__driScreen,
+ config->driConfig,
+ hwDrawable,
+ GLX_WINDOW_BIT,
+ empty_attribute_list,
+ pdraw);
+
+ if (!pdraw->driDrawable) {
+ XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
+ Xfree(pdraw);
+ return NULL;
+ }
+
+ pdraw->destroyDrawable = driDestroyDrawable;
+
+ return pdraw;
+}
+
+static void driSwapBuffers(__GLXDRIdrawable *pdraw)
+{
+ (*pdraw->psc->core->swapBuffers)(pdraw->driDrawable);
+}
+
+static void driDestroyScreen(__GLXscreenConfigs *psc)
{
/* Free the direct rendering per screen data */
- if (psc->driScreen.private)
- (*psc->driScreen.destroyScreen)(&psc->driScreen);
- psc->driScreen.private = NULL;
- if (psc->drawHash)
- __glxHashDestroy(psc->drawHash);
+ if (psc->__driScreen)
+ (*psc->core->destroyScreen)(psc->__driScreen);
+ psc->__driScreen = NULL;
if (psc->driver)
dlclose(psc->driver);
}
-/* Called from __glXFreeDisplayPrivate.
- */
-static void driDestroyDisplay(Display *dpy, void *private)
+static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen,
+ __GLXdisplayPrivate *priv)
{
- __DRIdisplayPrivate *pdpyp = (__DRIdisplayPrivate *)private;
+ __GLXDRIdisplayPrivate *pdp;
+ __GLXDRIscreen *psp;
+ const __DRIextension **extensions;
+ char *driverName;
+ int i;
- if (pdpyp)
- Xfree(pdpyp);
+ psp = Xmalloc(sizeof *psp);
+ if (psp == NULL)
+ return NULL;
+
+ /* Initialize per screen dynamic client GLX extensions */
+ psc->ext_list_first_time = GL_TRUE;
+
+ if (!driGetDriverName(priv->dpy, screen, &driverName)) {
+ Xfree(psp);
+ return NULL;
+ }
+
+ psc->driver = driOpenDriver(driverName);
+ Xfree(driverName);
+ if (psc->driver == NULL) {
+ Xfree(psp);
+ return NULL;
+ }
+
+ extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
+ if (extensions == NULL) {
+ ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
+ Xfree(psp);
+ return NULL;
+ }
+
+ for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
+ psc->core = (__DRIcoreExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
+ psc->legacy = (__DRIlegacyExtension *) extensions[i];
+ }
+
+ if (psc->core == NULL || psc->legacy == NULL) {
+ Xfree(psp);
+ return NULL;
+ }
+
+ pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
+ psc->__driScreen =
+ CallCreateNewScreen(psc->dpy, screen, psc, pdp);
+ if (psc->__driScreen == NULL) {
+ dlclose(psc->driver);
+ Xfree(psp);
+ return NULL;
+ }
+
+ driBindExtensions(psc, 0);
+
+ psp->destroyScreen = driDestroyScreen;
+ psp->createContext = driCreateContext;
+ psp->createDrawable = driCreateDrawable;
+ psp->swapBuffers = driSwapBuffers;
+
+ return psp;
}
+/* Called from __glXFreeDisplayPrivate.
+ */
+static void driDestroyDisplay(__GLXDRIdisplay *dpy)
+{
+ Xfree(dpy);
+}
/*
* Allocate, initialize and return a __DRIdisplayPrivate object.
* This is called from __glXInitialize() when we are given a new
* display pointer.
*/
-void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
+_X_HIDDEN __GLXDRIdisplay *driCreateDisplay(Display *dpy)
{
- __DRIdisplayPrivate *pdpyp;
+ __GLXDRIdisplayPrivate *pdpyp;
int eventBase, errorBase;
int major, minor, patch;
- /* Initialize these fields to NULL in case we fail.
- * If we don't do this we may later get segfaults trying to free random
- * addresses when the display is closed.
- */
- pdisp->private = NULL;
- pdisp->destroyDisplay = NULL;
-
if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
return NULL;
}
return NULL;
}
- pdpyp = (__DRIdisplayPrivate *)Xmalloc(sizeof(__DRIdisplayPrivate));
+ pdpyp = Xmalloc(sizeof *pdpyp);
if (!pdpyp) {
return NULL;
}
pdpyp->driMinor = minor;
pdpyp->driPatch = patch;
- pdisp->destroyDisplay = driDestroyDisplay;
+ pdpyp->base.destroyDisplay = driDestroyDisplay;
+ pdpyp->base.createScreen = driCreateScreen;
- return (void *)pdpyp;
+ return &pdpyp->base;
}
#endif /* GLX_DIRECT_RENDERING */