summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2010-07-22 21:11:02 -0400
committerKristian Høgsberg <krh@bitplanet.net>2010-07-22 21:11:20 -0400
commitab434f6b7641a64d30725a9ac24929240362d466 (patch)
tree239ee2ff7b3078f5af5fd17b25f3cfec991af5e2
parentc20a3628c7c6b7c41efe309b712bf93eb4e92039 (diff)
glx: Use _Xglobal_lock for protecting extension display list
Avoids double locking glXLock in the X wire to event handlers.
-rw-r--r--src/glx/dri2.c4
-rw-r--r--src/glx/glxclient.h4
-rw-r--r--src/glx/glxext.c204
3 files changed, 86 insertions, 126 deletions
diff --git a/src/glx/dri2.c b/src/glx/dri2.c
index ab530baf0f6..d53431c19a6 100644
--- a/src/glx/dri2.c
+++ b/src/glx/dri2.c
@@ -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;
diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h
index 26f28852ce6..4f833057ffc 100644
--- a/src/glx/glxclient.h
+++ b/src/glx/glxclient.h
@@ -557,6 +557,10 @@ struct __GLXscreenConfigsRec
*/
struct __GLXdisplayPrivateRec
{
+ /* The extension protocol codes */
+ XExtCodes *codes;
+ struct __GLXdisplayPrivateRec *next;
+
/**
* Back pointer to the display
*/
diff --git a/src/glx/glxext.c b/src/glx/glxext.c
index 9c3c7a4840a..88e74c2a386 100644
--- a/src/glx/glxext.c
+++ b/src/glx/glxext.c
@@ -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,67 +797,52 @@ 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;
}
+ dpyPriv->dpy = dpy;
+ dpyPriv->majorOpcode = dpyPriv->codes->major_opcode;
+ dpyPriv->serverGLXvendor = 0x0;
+ dpyPriv->serverGLXversion = 0x0;
+
/* 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;
+ if (!QueryVersion(dpy, dpyPriv->majorOpcode,
+ &dpyPriv->majorVersion, &dpyPriv->minorVersion)) {
+ Xfree(dpyPriv);
+ _XUnlockMutex(_Xglobal_lock);
+ return NULL;
}
- /*
- ** 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;
+ for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
+ XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent);
+ XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire);
}
- /*
- ** 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->serverGLXvendor = 0x0;
- dpyPriv->serverGLXversion = 0x0;
+ 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);
@@ -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;
}