glx: Use _Xglobal_lock for protecting extension display list
Avoids double locking glXLock in the X wire to event handlers.
This commit is contained in:
+2
-2
@@ -88,7 +88,7 @@ static Bool
|
||||
DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
|
||||
{
|
||||
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
|
||||
XExtDisplayInfo *glx_info = __glXFindDisplay(dpy);
|
||||
__GLXdisplayPrivate *glx_dpy = __glXInitialize(dpy);
|
||||
|
||||
XextCheckExtension(dpy, info, dri2ExtensionName, False);
|
||||
|
||||
@@ -107,7 +107,7 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
|
||||
return False;
|
||||
|
||||
aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
|
||||
aevent->type = glx_info->codes->first_event + GLX_BufferSwapComplete;
|
||||
aevent->type = glx_dpy->codes->first_event + GLX_BufferSwapComplete;
|
||||
aevent->send_event = (awire->type & 0x80) != 0;
|
||||
aevent->display = dpy;
|
||||
aevent->drawable = awire->drawable;
|
||||
|
||||
@@ -557,6 +557,10 @@ struct __GLXscreenConfigsRec
|
||||
*/
|
||||
struct __GLXdisplayPrivateRec
|
||||
{
|
||||
/* The extension protocol codes */
|
||||
XExtCodes *codes;
|
||||
struct __GLXdisplayPrivateRec *next;
|
||||
|
||||
/**
|
||||
* Back pointer to the display
|
||||
*/
|
||||
|
||||
+82
-126
@@ -68,13 +68,8 @@ _X_HIDDEN int __glXDebug = 0;
|
||||
|
||||
/* Extension required boiler plate */
|
||||
|
||||
static char *__glXExtensionName = GLX_EXTENSION_NAME;
|
||||
#ifdef GLX_USE_APPLEGL
|
||||
static XExtensionInfo __glXExtensionInfo_data;
|
||||
XExtensionInfo *__glXExtensionInfo = &__glXExtensionInfo_data;
|
||||
#else
|
||||
XExtensionInfo *__glXExtensionInfo = NULL;
|
||||
#endif
|
||||
static const char __glXExtensionName[] = GLX_EXTENSION_NAME;
|
||||
static __GLXdisplayPrivate *glx_displays;
|
||||
|
||||
static /* const */ char *error_list[] = {
|
||||
"GLXBadContext",
|
||||
@@ -92,21 +87,6 @@ static /* const */ char *error_list[] = {
|
||||
"GLXBadWindow",
|
||||
};
|
||||
|
||||
static int
|
||||
__glXCloseDisplay(Display * dpy, XExtCodes * codes)
|
||||
{
|
||||
GLXContext gc;
|
||||
|
||||
gc = __glXGetCurrentContext();
|
||||
if (dpy == gc->currentDpy) {
|
||||
__glXSetCurrentContextNull();
|
||||
__glXFreeContext(gc);
|
||||
}
|
||||
|
||||
return XextRemoveDisplay(__glXExtensionInfo, dpy);
|
||||
}
|
||||
|
||||
|
||||
#ifdef GLX_USE_APPLEGL
|
||||
static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
|
||||
char *buf, int n);
|
||||
@@ -115,29 +95,14 @@ static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
|
||||
static
|
||||
XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
|
||||
__GLX_NUMBER_ERRORS, error_list)
|
||||
|
||||
static int
|
||||
__glXCloseDisplay(Display * dpy, XExtCodes * codes);
|
||||
static Bool
|
||||
__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire);
|
||||
static Status
|
||||
__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire);
|
||||
|
||||
static /* const */ XExtensionHooks __glXExtensionHooks = {
|
||||
NULL, /* create_gc */
|
||||
NULL, /* copy_gc */
|
||||
NULL, /* flush_gc */
|
||||
NULL, /* free_gc */
|
||||
NULL, /* create_font */
|
||||
NULL, /* free_font */
|
||||
__glXCloseDisplay, /* close_display */
|
||||
__glXWireToEvent, /* wire_to_event */
|
||||
__glXEventToWire, /* event_to_wire */
|
||||
NULL, /* error */
|
||||
__glXErrorString, /* error_string */
|
||||
};
|
||||
|
||||
XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
|
||||
__glXExtensionName, &__glXExtensionHooks,
|
||||
__GLX_NUMBER_EVENTS, NULL)
|
||||
|
||||
/*
|
||||
* GLX events are a bit funky. We don't stuff the X event code into
|
||||
* our user exposed (via XNextEvent) structure. Instead we use the GLX
|
||||
@@ -150,11 +115,12 @@ XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
|
||||
static Bool
|
||||
__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
|
||||
{
|
||||
XExtDisplayInfo *info = __glXFindDisplay(dpy);
|
||||
__GLXdisplayPrivate *glx_dpy = __glXInitialize(dpy);
|
||||
|
||||
XextCheckExtension(dpy, info, __glXExtensionName, False);
|
||||
if (glx_dpy == NULL)
|
||||
return False;
|
||||
|
||||
switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
|
||||
switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) {
|
||||
case GLX_PbufferClobber:
|
||||
{
|
||||
GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
|
||||
@@ -209,9 +175,10 @@ __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
|
||||
static Status
|
||||
__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
|
||||
{
|
||||
XExtDisplayInfo *info = __glXFindDisplay(dpy);
|
||||
__GLXdisplayPrivate *glx_dpy = __glXInitialize(dpy);
|
||||
|
||||
XextCheckExtension(dpy, info, __glXExtensionName, False);
|
||||
if (glx_dpy == NULL)
|
||||
return False;
|
||||
|
||||
switch (event->type) {
|
||||
case GLX_DAMAGED:
|
||||
@@ -279,20 +246,32 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv)
|
||||
** structure. The caller will free the extension structure.
|
||||
*/
|
||||
static int
|
||||
__glXFreeDisplayPrivate(XExtData * extension)
|
||||
__glXCloseDisplay(Display * dpy, XExtCodes * codes)
|
||||
{
|
||||
__GLXdisplayPrivate *priv;
|
||||
__GLXdisplayPrivate *priv, **prev;
|
||||
GLXContext gc;
|
||||
|
||||
_XLockMutex(_Xglobal_lock);
|
||||
prev = &glx_displays;
|
||||
for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
|
||||
if (priv->dpy == dpy) {
|
||||
(*prev)->next = priv->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_XUnlockMutex(_Xglobal_lock);
|
||||
|
||||
gc = __glXGetCurrentContext();
|
||||
if (dpy == gc->currentDpy) {
|
||||
__glXSetCurrentContextNull();
|
||||
__glXFreeContext(gc);
|
||||
}
|
||||
|
||||
priv = (__GLXdisplayPrivate *) extension->private_data;
|
||||
FreeScreenConfigs(priv);
|
||||
if (priv->serverGLXvendor) {
|
||||
if (priv->serverGLXvendor)
|
||||
Xfree((char *) priv->serverGLXvendor);
|
||||
priv->serverGLXvendor = 0x0; /* to protect against double free's */
|
||||
}
|
||||
if (priv->serverGLXversion) {
|
||||
if (priv->serverGLXversion)
|
||||
Xfree((char *) priv->serverGLXversion);
|
||||
priv->serverGLXversion = 0x0; /* to protect against double free's */
|
||||
}
|
||||
|
||||
__glxHashDestroy(priv->drawHash);
|
||||
|
||||
@@ -312,10 +291,9 @@ __glXFreeDisplayPrivate(XExtData * extension)
|
||||
#endif
|
||||
|
||||
Xfree((char *) priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Query the version of the GLX extension. This procedure works even if
|
||||
@@ -819,68 +797,53 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
|
||||
_X_HIDDEN __GLXdisplayPrivate *
|
||||
__glXInitialize(Display * dpy)
|
||||
{
|
||||
XExtDisplayInfo *info = __glXFindDisplay(dpy);
|
||||
XExtData **privList, *private, *found;
|
||||
__GLXdisplayPrivate *dpyPriv;
|
||||
XEDataObject dataObj;
|
||||
int major, minor;
|
||||
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
||||
Bool glx_direct, glx_accel;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
/* The one and only long long lock */
|
||||
__glXLock();
|
||||
_XLockMutex(_Xglobal_lock);
|
||||
|
||||
if (!XextHasExtension(info)) {
|
||||
/* No GLX extension supported by this server. Oh well. */
|
||||
__glXUnlock();
|
||||
XMissingExtension(dpy, __glXExtensionName);
|
||||
return 0;
|
||||
for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
|
||||
if (dpyPriv->dpy == dpy) {
|
||||
_XUnlockMutex(_Xglobal_lock);
|
||||
return dpyPriv;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if a display private already exists. If so, return it */
|
||||
dataObj.display = dpy;
|
||||
privList = XEHeadOfExtensionList(dataObj);
|
||||
found = XFindOnExtensionList(privList, info->codes->extension);
|
||||
if (found) {
|
||||
__glXUnlock();
|
||||
return (__GLXdisplayPrivate *) found->private_data;
|
||||
dpyPriv = Xcalloc(1, sizeof *dpyPriv);
|
||||
if (!dpyPriv)
|
||||
return NULL;
|
||||
|
||||
dpyPriv->codes = XInitExtension(dpy, __glXExtensionName);
|
||||
if (!dpyPriv->codes) {
|
||||
Xfree(dpyPriv);
|
||||
_XUnlockMutex(_Xglobal_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* See if the versions are compatible */
|
||||
if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) {
|
||||
/* The client and server do not agree on versions. Punt. */
|
||||
__glXUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate memory for all the pieces needed for this buffer.
|
||||
*/
|
||||
private = (XExtData *) Xmalloc(sizeof(XExtData));
|
||||
if (!private) {
|
||||
__glXUnlock();
|
||||
return 0;
|
||||
}
|
||||
dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
|
||||
if (!dpyPriv) {
|
||||
__glXUnlock();
|
||||
Xfree((char *) private);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Init the display private and then read in the screen config
|
||||
** structures from the server.
|
||||
*/
|
||||
dpyPriv->majorOpcode = info->codes->major_opcode;
|
||||
dpyPriv->majorVersion = major;
|
||||
dpyPriv->minorVersion = minor;
|
||||
dpyPriv->dpy = dpy;
|
||||
|
||||
dpyPriv->majorOpcode = dpyPriv->codes->major_opcode;
|
||||
dpyPriv->serverGLXvendor = 0x0;
|
||||
dpyPriv->serverGLXversion = 0x0;
|
||||
|
||||
/* See if the versions are compatible */
|
||||
if (!QueryVersion(dpy, dpyPriv->majorOpcode,
|
||||
&dpyPriv->majorVersion, &dpyPriv->minorVersion)) {
|
||||
Xfree(dpyPriv);
|
||||
_XUnlockMutex(_Xglobal_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
|
||||
XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent);
|
||||
XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire);
|
||||
}
|
||||
|
||||
XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay);
|
||||
XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString);
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
||||
glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
|
||||
glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
|
||||
@@ -899,32 +862,25 @@ __glXInitialize(Display * dpy)
|
||||
if (glx_direct)
|
||||
dpyPriv->driswDisplay = driswCreateDisplay(dpy);
|
||||
#endif
|
||||
|
||||
#ifdef GLX_USE_APPLEGL
|
||||
if (apple_init_glx(dpy) || !AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
|
||||
#else
|
||||
if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
|
||||
if (apple_init_glx(dpy)) {
|
||||
Xfree(dpyPriv);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
__glXUnlock();
|
||||
Xfree((char *) dpyPriv);
|
||||
Xfree((char *) private);
|
||||
return 0;
|
||||
if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
|
||||
Xfree(dpyPriv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Fill in the private structure. This is the actual structure that
|
||||
** hangs off of the Display structure. Our private structure is
|
||||
** referred to by this structure. Got that?
|
||||
*/
|
||||
private->number = info->codes->extension;
|
||||
private->next = 0;
|
||||
private->free_private = __glXFreeDisplayPrivate;
|
||||
private->private_data = (char *) dpyPriv;
|
||||
XAddToExtensionList(privList, private);
|
||||
|
||||
if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) {
|
||||
if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1)
|
||||
__glXClientInfo(dpy, dpyPriv->majorOpcode);
|
||||
}
|
||||
__glXUnlock();
|
||||
|
||||
dpyPriv->next = glx_displays;
|
||||
glx_displays = dpyPriv;
|
||||
|
||||
_XUnlockMutex(_Xglobal_lock);
|
||||
|
||||
return dpyPriv;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user