Commit d29b795c authored by Kristian Høgsberg's avatar Kristian Høgsberg
Browse files

Remove XIDs from DRI interface (see #5714).

parent 3c59483e
......@@ -48,16 +48,16 @@
* side library and the DRI (direct rendering infrastructure).
*/
/*@{*/
typedef struct __DRIdisplayRec __DRIdisplay;
typedef struct __DRIscreenRec __DRIscreen;
typedef struct __DRIcontextRec __DRIcontext;
typedef struct __DRIdrawableRec __DRIdrawable;
typedef struct __DRIdriverRec __DRIdriver;
typedef struct __DRIframebufferRec __DRIframebuffer;
typedef struct __DRIversionRec __DRIversion;
typedef struct __DRIinterfaceMethodsRec __DRIinterfaceMethods;
typedef unsigned long __DRIid;
typedef void __DRInativeDisplay;
typedef struct __DRIdisplayRec __DRIdisplay;
typedef struct __DRIscreenRec __DRIscreen;
typedef struct __DRIcontextRec __DRIcontext;
typedef struct __DRIdrawableRec __DRIdrawable;
typedef struct __DRIdriverRec __DRIdriver;
typedef struct __DRIframebufferRec __DRIframebuffer;
typedef struct __DRIversionRec __DRIversion;
typedef struct __DRIinterfaceMethodsRec __DRIinterfaceMethods;
typedef unsigned long __DRIid;
typedef void __DRInativeDisplay;
/*@}*/
......@@ -106,7 +106,7 @@ typedef void *(CREATENEWSCREENFUNC)(__DRInativeDisplay *dpy, int scrn,
const __DRIinterfaceMethods * interface,
__GLcontextModes ** driver_modes);
typedef CREATENEWSCREENFUNC* PFNCREATENEWSCREENFUNC;
extern CREATENEWSCREENFUNC __driCreateNewScreen_20050727;
extern CREATENEWSCREENFUNC __driCreateNewScreen_20070105;
/**
......@@ -170,16 +170,6 @@ struct __DRIinterfaceMethodsRec {
* the wire protocol (e.g., EGL) will implement glorified no-op functions.
*/
/*@{*/
/**
* Determine if the specified window ID still exists.
*
* \note
* Implementations may assume that the driver will only pass an ID into
* this function that actually corresponds to a window. On
* implementations where windows can only be destroyed by the DRI driver
* (e.g., EGL), this function is allowed to always return \c GL_TRUE.
*/
GLboolean (*windowExists)(__DRInativeDisplay *dpy, __DRIid draw);
/**
* Create the server-side portion of the GL context.
......@@ -306,12 +296,6 @@ struct __DRIscreenRec {
__DRIid draw, __DRIdrawable *pdraw,
int renderType, const int *attrs);
/**
* Method to return a pointer to the DRI drawable data.
*/
__DRIdrawable *(*getDrawable)(__DRInativeDisplay *dpy, __DRIid draw,
void *drawablePrivate);
/**
* Opaque pointer to private per screen direct rendering data. \c NULL
* if direct rendering is not supported on this screen. Never
......@@ -380,28 +364,23 @@ struct __DRIcontextRec {
*/
void *private;
/**
* Pointer to the mode used to create this context.
*
* \since Internal API version 20040317.
*/
const __GLcontextModes * mode;
/**
* Method to bind a DRI drawable to a DRI graphics context.
*
* \since Internal API version 20050727.
*/
GLboolean (*bindContext)(__DRInativeDisplay *dpy, int scrn, __DRIid draw,
__DRIid read, __DRIcontext *ctx);
GLboolean (*bindContext)(__DRInativeDisplay *dpy, int scrn,
__DRIdrawable *pdraw,
__DRIdrawable *pread,
__DRIcontext *ctx);
/**
* Method to unbind a DRI drawable from a DRI graphics context.
*
* \since Internal API version 20050727.
*/
GLboolean (*unbindContext)(__DRInativeDisplay *dpy, int scrn, __DRIid draw,
__DRIid read, __DRIcontext *ctx);
GLboolean (*unbindContext)(__DRInativeDisplay *dpy, int scrn,
__DRIcontext *ctx);
};
/**
......
......@@ -427,16 +427,37 @@ PUBLIC GLboolean XF86DRICreateDrawable( __DRInativeDisplay * ndpy, int screen,
return True;
}
static int noopErrorHandler(Display *dpy, XErrorEvent *xerr)
{
return 0;
}
PUBLIC GLboolean XF86DRIDestroyDrawable( __DRInativeDisplay * ndpy, int screen,
__DRIid drawable )
{
Display * const dpy = (Display *) ndpy;
XExtDisplayInfo *info = find_display (dpy);
xXF86DRIDestroyDrawableReq *req;
int (*oldXErrorHandler)(Display *, XErrorEvent *);
TRACE("DestroyDrawable...");
XF86DRICheckExtension (dpy, info, False);
/* This is called from the DRI driver, which used call it like this
*
* if (windowExists(drawable))
* destroyDrawable(drawable);
*
* which is a textbook race condition - the window may disappear
* from the server between checking for its existance and
* destroying it. Instead we change the semantics of
* __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if
* the windows is gone, by wrapping the destroy call in an error
* handler. */
XSync(dpy, GL_FALSE);
oldXErrorHandler = XSetErrorHandler(noopErrorHandler);
LockDisplay(dpy);
GetReq(XF86DRIDestroyDrawable, req);
req->reqType = info->codes->major_opcode;
......@@ -445,6 +466,9 @@ PUBLIC GLboolean XF86DRIDestroyDrawable( __DRInativeDisplay * ndpy, int screen,
req->drawable = drawable;
UnlockDisplay(dpy);
SyncHandle();
XSetErrorHandler(oldXErrorHandler);
TRACE("DestroyDrawable... return True");
return True;
}
......
......@@ -166,7 +166,7 @@ ExtractDir(int index, const char *paths, int dirLen, char *dir)
* \todo
* Create a macro or something so that this is automatically updated.
*/
static const char createNewScreenName[] = "__driCreateNewScreen_20050727";
static const char createNewScreenName[] = "__driCreateNewScreen_20070105";
/**
......
......@@ -349,6 +349,11 @@ struct __GLXcontextRec {
* Per context direct rendering interface functions and data.
*/
__DRIcontext driContext;
/**
* Pointer to the mode used to create this context.
*/
const __GLcontextModes * mode;
#endif
/**
......@@ -456,6 +461,7 @@ typedef struct __GLXscreenConfigsRec {
* Per screen direct rendering interface functions and data.
*/
__DRIscreen driScreen;
void *drawHash;
#endif
/**
......
......@@ -61,41 +61,92 @@ static const char __glXGLXClientVersion[] = "1.4";
/****************************************************************************/
#ifdef GLX_DIRECT_RENDERING
static Bool windowExistsFlag;
static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
{
if (xerr->error_code == BadWindow) {
windowExistsFlag = GL_FALSE;
}
return 0;
}
/**
* Find drawables in the local hash that have been destroyed on the
* server.
*
* \param dpy Display to destroy drawables for
* \param screen Screen number to destroy drawables for
*/
static void GarbageCollectDRIDrawables(Display *dpy, int screen)
{
__GLXdisplayPrivate * const priv = __glXInitialize(dpy);
__GLXscreenConfigs *sc;
__DRIid draw;
__DRIdrawable *pdraw;
XWindowAttributes xwa;
int (*oldXErrorHandler)(Display *, XErrorEvent *);
if (priv == NULL || priv->driDisplay.private == NULL)
return;
/* Set no-op error handler so Xlib doesn't bail out if the windows
* has alreay been destroyed on the server. */
XSync(dpy, GL_FALSE);
oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
sc = &priv->screenConfigs[screen];
if (drmHashFirst(sc->drawHash, &draw, (void *)&pdraw) == 1) {
do {
windowExistsFlag = GL_TRUE;
XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
if (!windowExistsFlag) {
/* Destroy the local drawable data, if the drawable no
longer exists in the Xserver */
(*pdraw->destroyDrawable)(dpy, pdraw->private);
Xfree(pdraw);
}
} while (drmHashNext(sc->drawHash, &draw, (void *)&pdraw) == 1);
}
XSetErrorHandler(oldXErrorHandler);
}
/**
* Get the __DRIdrawable for the drawable associated with a GLXContext
*
* \param dpy The display associated with \c drawable.
* \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved.
* \param scrn_num If non-NULL, the drawables screen is stored there
* \returns A pointer to the context's __DRIdrawable on success, or NULL if
* the drawable is not associated with a direct-rendering context.
*/
#ifdef GLX_DIRECT_RENDERING
static __DRIdrawable *
GetDRIDrawable( Display *dpy, GLXDrawable drawable, int * const scrn_num )
{
__GLXdisplayPrivate * const priv = __glXInitialize(dpy);
__DRIdrawable * const pdraw;
const unsigned screen_count = ScreenCount(dpy);
unsigned i;
__GLXscreenConfigs *sc;
if ( (priv != NULL) && (priv->driDisplay.private != NULL) ) {
const unsigned screen_count = ScreenCount(dpy);
unsigned i;
for ( i = 0 ; i < screen_count ; i++ ) {
__DRIscreen * const psc = &priv->screenConfigs[i].driScreen;
__DRIdrawable * const pdraw = (psc->private != NULL)
? (*psc->getDrawable)(dpy, drawable, psc->private) : NULL;
if ( pdraw != NULL ) {
if ( scrn_num != NULL ) {
*scrn_num = i;
}
return pdraw;
}
if (priv == NULL || priv->driDisplay.private == NULL)
return NULL;
for (i = 0; i < screen_count; i++) {
sc = &priv->screenConfigs[i];
if (drmHashLookup(sc->drawHash, drawable, (void *) &pdraw) == 0) {
if (scrn_num != NULL)
*scrn_num = i;
return pdraw;
}
}
return NULL;
}
#endif
......@@ -359,7 +410,7 @@ CreateContext(Display *dpy, XVisualInfo *vis,
gc->screen = mode->screen;
gc->vid = mode->visualID;
gc->fbconfigID = mode->fbconfigID;
gc->driContext.mode = mode;
gc->mode = mode;
}
}
}
......@@ -473,6 +524,7 @@ DestroyContext(Display *dpy, GLXContext gc)
gc->driContext.private);
gc->driContext.private = NULL;
}
GarbageCollectDRIDrawables(dpy, gc->screen);
}
#endif
......@@ -1730,9 +1782,7 @@ static int __glXSwapIntervalMESA(unsigned int interval)
if ( (psc != NULL) && (psc->driScreen.private != NULL)
&& __glXExtensionBitIsEnabled( psc, MESA_swap_control_bit ) ) {
__DRIdrawable * const pdraw =
(*psc->driScreen.getDrawable)(gc->currentDpy,
gc->currentDrawable,
psc->driScreen.private);
GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
if ( pdraw != NULL ) {
pdraw->swap_interval = interval;
return 0;
......@@ -1759,9 +1809,7 @@ static int __glXGetSwapIntervalMESA(void)
if ( (psc != NULL) && (psc->driScreen.private != NULL)
&& __glXExtensionBitIsEnabled( psc, MESA_swap_control_bit ) ) {
__DRIdrawable * const pdraw =
(*psc->driScreen.getDrawable)(gc->currentDpy,
gc->currentDrawable,
psc->driScreen.private);
GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
if ( pdraw != NULL ) {
return pdraw->swap_interval;
}
......@@ -1919,9 +1967,7 @@ static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count
if ( __glXExtensionBitIsEnabled( psc, SGI_video_sync_bit )
&& psc->driScreen.private ) {
__DRIdrawable * const pdraw =
(*psc->driScreen.getDrawable)(gc->currentDpy,
gc->currentDrawable,
psc->driScreen.private);
GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
if ( (pdraw != NULL) && (pdraw->waitForMSC != NULL) ) {
int ret;
int64_t msc;
......@@ -2140,11 +2186,10 @@ Bool __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
int i;
GetDRIDrawable( dpy, drawable, & screen_num );
if ( (screen_num != -1)
&& XF86VidModeQueryVersion( dpy, & i, & i )
&& XF86VidModeGetModeLine( dpy, screen_num, & dot_clock,
& mode_line ) ) {
if (GetDRIDrawable( dpy, drawable, & screen_num) != NULL
&& XF86VidModeQueryVersion( dpy, & i, & i )
&& XF86VidModeGetModeLine( dpy, screen_num, & dot_clock,
& mode_line ) ) {
unsigned n = dot_clock * 1000;
unsigned d = mode_line.vtotal * mode_line.htotal;
......@@ -2889,50 +2934,6 @@ int __glXGetInternalVersion(void)
}
static Bool windowExistsFlag;
static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
{
if (xerr->error_code == BadWindow) {
windowExistsFlag = GL_FALSE;
}
return 0;
}
/**
* Determine if a window associated with a \c GLXDrawable exists on the
* X-server. This function is not used internally by libGL. It is provided
* as a utility function for DRI drivers.
* Drivers should not call this function directly. They should instead use
* \c glXGetProcAddress to obtain a pointer to the function.
*
* \param dpy Display associated with the drawable to be queried.
* \param draw \c GLXDrawable to test.
*
* \returns \c GL_TRUE if a window exists that is associated with \c draw,
* otherwise \c GL_FALSE is returned.
*
* \warning This function is not currently thread-safe.
*
* \sa glXGetProcAddress
*
* \since Internal API version 20021128.
*/
Bool __glXWindowExists(Display *dpy, GLXDrawable draw)
{
XWindowAttributes xwa;
int (*oldXErrorHandler)(Display *, XErrorEvent *);
XSync(dpy, GL_FALSE);
windowExistsFlag = GL_TRUE;
oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
XSetErrorHandler(oldXErrorHandler);
return windowExistsFlag;
}
/**
* Get the unadjusted system time (UST). Currently, the UST is measured in
* microseconds since Epoc. The actual resolution of the UST may vary from
......
......@@ -61,6 +61,7 @@
#include <inttypes.h>
#include <sys/mman.h>
#include "xf86dri.h"
#include "xf86drm.h"
#include "sarea.h"
#include "dri_glx.h"
#endif
......@@ -366,6 +367,7 @@ static void FreeScreenConfigs(__GLXdisplayPrivate *priv)
(*psc->driScreen.destroyScreen)(priv->dpy, i,
psc->driScreen.private);
psc->driScreen.private = NULL;
drmHashDestroy(psc->drawHash);
#endif
}
XFree((char*) priv->screenConfigs);
......@@ -773,7 +775,6 @@ static const __DRIinterfaceMethods interface_methods = {
_gl_context_modes_destroy,
__glXFindDRIScreen,
__glXWindowExists,
XF86DRICreateContextWithConfig,
XF86DRIDestroyContext,
......@@ -808,7 +809,7 @@ static const __DRIinterfaceMethods interface_methods = {
* returned by the client-side driver.
*/
static void *
CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
__DRIdisplay * driDpy,
PFNCREATENEWSCREENFUNC createNewScreen)
{
......@@ -929,13 +930,12 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
if ( status == 0 ) {
__GLcontextModes * driver_modes = NULL;
__GLXscreenConfigs *configs = psc->screenConfigs;
err_msg = "InitDriver";
err_extra = NULL;
psp = (*createNewScreen)(dpy, scrn,
psc,
configs->configs,
&psc->driScreen,
psc->configs,
& ddx_version,
& dri_version,
& drm_version,
......@@ -946,7 +946,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
& interface_methods,
& driver_modes );
filter_modes( & configs->configs,
filter_modes( & psc->configs,
driver_modes );
_gl_context_modes_destroy( driver_modes );
}
......@@ -1161,6 +1161,14 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv)
UnlockDisplay(dpy);
#ifdef GLX_DIRECT_RENDERING
/* Create drawable hash */
psc->drawHash = drmHashCreate();
if ( psc->drawHash == NULL ) {
SyncHandle();
FreeScreenConfigs(priv);
return GL_FALSE;
}
/* Initialize per screen dynamic client GLX extensions */
psc->ext_list_first_time = GL_TRUE;
/* Initialize the direct rendering per screen data and functions */
......@@ -1173,7 +1181,7 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv)
psc->driScreen.screenConfigs = (void *)psc;
psc->driScreen.private =
CallCreateNewScreen(dpy, i, & psc->driScreen,
CallCreateNewScreen(dpy, i, psc,
& priv->driDisplay,
priv->driDisplay.createNewScreen[i] );
}
......@@ -1614,20 +1622,64 @@ static Bool SendMakeCurrentRequest(Display *dpy, CARD8 opcode,
#ifdef GLX_DIRECT_RENDERING
static __DRIdrawable *
FetchDRIDrawable( Display *dpy, GLXDrawable drawable, GLXContext gc)
{
__GLXdisplayPrivate * const priv = __glXInitialize(dpy);
__DRIdrawable *pdraw;
__GLXscreenConfigs *sc;
void *empty_attribute_list = NULL;
if (priv == NULL || priv->driDisplay.private == NULL)
return NULL;
sc = &priv->screenConfigs[gc->screen];
if (drmHashLookup(sc->drawHash, drawable, (void *) &pdraw) == 0)
return pdraw;
/* Allocate a new drawable */
pdraw = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
if (!pdraw)
return NULL;
/* Create a new drawable */
pdraw->private =
(*sc->driScreen.createNewDrawable)(dpy,
gc->mode,
drawable, pdraw,
GLX_WINDOW_BIT,
empty_attribute_list);
if (!pdraw->private) {
/* ERROR!!! */
Xfree(pdraw);
return NULL;
}
if (drmHashInsert(sc->drawHash, drawable, pdraw)) {
(*pdraw->destroyDrawable)(dpy, pdraw->private);
Xfree(pdraw);
return NULL;
}
return pdraw;
}
static Bool BindContextWrapper( Display *dpy, GLXContext gc,
GLXDrawable draw, GLXDrawable read )
{
return (*gc->driContext.bindContext)(dpy, gc->screen, draw, read,
__DRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc);
__DRIdrawable *pread = FetchDRIDrawable(dpy, read, gc);
return (*gc->driContext.bindContext)(dpy, gc->screen, pdraw, pread,
& gc->driContext);
}
static Bool UnbindContextWrapper( GLXContext gc )
{
return (*gc->driContext.unbindContext)(gc->currentDpy, gc->screen,
gc->currentDrawable,
gc->currentReadable,
& gc->driContext );
return (*gc->driContext.unbindContext)(gc->currentDpy, gc->screen,
&gc->driContext );
}
#endif /* GLX_DIRECT_RENDERING */
......
......@@ -50,9 +50,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* 4.0.0: Original
* 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
* 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
* 5.0.0: Drop XIDs from DRI interface.
*/
#define XF86DRI_MAJOR_VERSION 4
#define XF86DRI_MINOR_VERSION 1
#define XF86DRI_MAJOR_VERSION 5
#define XF86DRI_MINOR_VERSION 0
#define XF86DRI_PATCH_VERSION 0
typedef struct _XF86DRIQueryVersion {
......
......@@ -88,63 +88,6 @@ __driUtilMessage(const char *f, ...)
}
/*****************************************************************/
/** \name Drawable list management */
/*****************************************************************/
/*@{*/
static GLboolean __driAddDrawable(void *drawHash, __DRIdrawable *pdraw)
{
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
if (drmHashInsert(drawHash, pdp->draw, pdraw))
return GL_FALSE;
return GL_TRUE;
}
static __DRIdrawable *__driFindDrawable(void *drawHash, __DRIid draw)
{
int retcode;
__DRIdrawable *pdraw;
retcode = drmHashLookup(drawHash, draw, (void *)&pdraw);
if (retcode)
return NULL;
return pdraw;
}
/**
* Find drawables in the local hash that have been destroyed on the
* server.
*
* \param drawHash Hash-table containing all know drawables.
*/
static void __driGarbageCollectDrawables(void *drawHash)
{
__DRIid draw;
__DRInativeDisplay *dpy;
__DRIdrawable *pdraw;
if (drmHashFirst(drawHash, &draw, (void *)&pdraw) == 1) {
do {
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
dpy = pdp->driScreenPriv->display;
if (! (*dri_interface->windowExists)(dpy, draw)) {
/* Destroy the local drawable data, if the drawable no
longer exists in the Xserver */
(*pdraw->destroyDrawable)(dpy, pdraw->private);
_mesa_free(pdraw);
}
} while (drmHashNext(drawHash, &draw, (void *)&pdraw) == 1);
}
}