summaryrefslogtreecommitdiff
path: root/GL
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2006-09-07 15:35:16 -0400
committerKristian Høgsberg <krh@redhat.com>2006-09-07 15:35:16 -0400
commit86450998da616e3d00d4d6293acc35eccc2061e7 (patch)
tree82566dd3597d6827d3699dab270463e32df5e143 /GL
parent64479fffa22581cc7d753065c33eda5520b7db9a (diff)
Fix AIGLX VT switching.
See https://bugs.freedesktop.org/show_bug.cgi?id=7916 There may be a simpler, less intrusive fix that involves just rearranging DRI locking between 2D and 3D drivers around VT switch.
Diffstat (limited to 'GL')
-rw-r--r--GL/glx/glxdri.c36
-rw-r--r--GL/glx/glxext.c90
-rw-r--r--GL/glx/glxserver.h5
3 files changed, 104 insertions, 27 deletions
diff --git a/GL/glx/glxdri.c b/GL/glx/glxdri.c
index 41e49e225..b5723049d 100644
--- a/GL/glx/glxdri.c
+++ b/GL/glx/glxdri.c
@@ -73,6 +73,9 @@ struct __GLXDRIscreen {
__DRIscreen driScreen;
void *driver;
+ xf86EnterVTProc *enterVT;
+ xf86LeaveVTProc *leaveVT;
+
unsigned char glx_enable_bits[__GLX_EXT_BYTES];
};
@@ -622,8 +625,7 @@ static __DRIfuncPtr getProcAddress(const char *proc_name)
static __DRIscreen *findScreen(__DRInativeDisplay *dpy, int scrn)
{
- __GLXDRIscreen *screen =
- (__GLXDRIscreen *) __glXgetActiveScreen(scrn);
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) __glXgetActiveScreen(scrn);
return &screen->driScreen;
}
@@ -817,6 +819,30 @@ static const __DRIinterfaceMethods interface_methods = {
static const char dri_driver_path[] = DRI_DRIVER_PATH;
+static Bool
+glxDRIEnterVT (int index, int flags)
+{
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) __glXgetActiveScreen(index);
+
+ LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
+
+ glxResumeClients();
+
+ return (*screen->enterVT) (index, flags);
+}
+
+static void
+glxDRILeaveVT (int index, int flags)
+{
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) __glXgetActiveScreen(index);
+
+ LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
+
+ glxSuspendClients();
+
+ return (*screen->leaveVT) (index, flags);
+}
+
static __GLXscreen *
__glXDRIscreenProbe(ScreenPtr pScreen)
{
@@ -842,6 +868,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
char filename[128];
Bool isCapable;
size_t buffer_size;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
if (!xf86LoaderCheckSymbol("DRIQueryDirectRenderingCapable")) {
LogMessage(X_ERROR, "AIGLX: DRI module not loaded\n");
@@ -1029,6 +1056,11 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
__glXsetEnterLeaveServerFuncs(__glXDRIenterServer, __glXDRIleaveServer);
+ screen->enterVT = pScrn->EnterVT;
+ pScrn->EnterVT = glxDRIEnterVT;
+ screen->leaveVT = pScrn->LeaveVT;
+ pScrn->LeaveVT = glxDRILeaveVT;
+
LogMessage(X_INFO,
"AIGLX: Loaded and initialized %s\n", filename);
diff --git a/GL/glx/glxext.c b/GL/glx/glxext.c
index fdb8ea262..11fb7fcaf 100644
--- a/GL/glx/glxext.c
+++ b/GL/glx/glxext.c
@@ -59,10 +59,7 @@ xGLXSingleReply __glXReply;
** A set of state for each client. The 0th one is unused because client
** indices start at 1, not 0.
*/
-__GLXclientState *__glXClients[MAXCLIENTS+1];
-
-
-static Bool inDispatch;
+static __GLXclientState *__glXClients[MAXCLIENTS + 1];
/*
** Forward declarations.
@@ -219,6 +216,10 @@ static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
return True;
}
+static __GLXcontext *glxPendingDestroyContexts;
+static int glxServerLeaveCount;
+static int glxBlockClients;
+
/*
** Free a context.
*/
@@ -236,13 +237,14 @@ GLboolean __glXFreeContext(__GLXcontext *cx)
* __glXDispatch() or as a callback from the resource manager. In
* the latter case we need to lift the DRI lock manually. */
- if (!inDispatch)
- __glXleaveServer();
-
- cx->destroy(cx);
-
- if (!inDispatch)
- __glXenterServer();
+ if (glxBlockClients) {
+ __glXleaveServer();
+ cx->destroy(cx);
+ __glXenterServer();
+ } else {
+ cx->next = glxPendingDestroyContexts;
+ glxPendingDestroyContexts = cx;
+ }
return GL_TRUE;
}
@@ -338,7 +340,7 @@ void GlxExtensionInit(void)
/*
** Initialize table of client state. There is never a client 0.
*/
- for (i=1; i <= MAXCLIENTS; i++) {
+ for (i = 1; i <= MAXCLIENTS; i++) {
__glXClients[i] = 0;
}
@@ -409,11 +411,43 @@ __GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
/************************************************************************/
-/*
-** Top level dispatcher; all commands are executed from here down.
-*/
+void glxSuspendClients(void)
+{
+ int i;
-/* I cried when I wrote this. Damn you XAA! */
+ for (i = 1; i <= MAXCLIENTS; i++) {
+ if (__glXClients[i] == NULL || !__glXClients[i]->inUse)
+ continue;
+
+ IgnoreClient(__glXClients[i]->client);
+ }
+
+ glxBlockClients = TRUE;
+}
+
+void glxResumeClients(void)
+{
+ __GLXcontext *cx, *next;
+ int i;
+
+ glxBlockClients = FALSE;
+
+ for (i = 1; i <= MAXCLIENTS; i++) {
+ if (__glXClients[i] == NULL || !__glXClients[i]->inUse)
+ continue;
+
+ AttendClient(__glXClients[i]->client);
+ }
+
+ __glXleaveServer();
+ for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
+ next = cx->next;
+
+ cx->destroy(cx);
+ }
+ glxPendingDestroyContexts = NULL;
+ __glXenterServer();
+}
static void
__glXnopEnterServer(void)
@@ -438,14 +472,19 @@ void __glXsetEnterLeaveServerFuncs(void (*enter)(void),
void __glXenterServer(void)
{
- (*__glXenterServerFunc)();
+ glxServerLeaveCount--;
+
+ if (glxServerLeaveCount == 0)
+ (*__glXenterServerFunc)();
}
void __glXleaveServer(void)
{
- (*__glXleaveServerFunc)();
-}
+ if (glxServerLeaveCount == 0)
+ (*__glXleaveServerFunc)();
+ glxServerLeaveCount++;
+}
/*
** Top level dispatcher; all commands are executed from here down.
@@ -491,6 +530,15 @@ static int __glXDispatch(ClientPtr client)
return __glXError(GLXBadLargeRequest);
}
+ /* If we're currently blocking GLX clients, just put this guy to
+ * sleep, reset the request and return. */
+ if (glxBlockClients) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ IgnoreClient(client);
+ return(client->noClientException);
+ }
+
/*
** Use the opcode to index into the procedure table.
*/
@@ -500,12 +548,8 @@ static int __glXDispatch(ClientPtr client)
if (proc != NULL) {
__glXleaveServer();
- inDispatch = True;
-
retval = (*proc)(cl, (GLbyte *) stuff);
- inDispatch = False;
-
__glXenterServer();
}
else {
diff --git a/GL/glx/glxserver.h b/GL/glx/glxserver.h
index 838973731..49cad7328 100644
--- a/GL/glx/glxserver.h
+++ b/GL/glx/glxserver.h
@@ -136,6 +136,9 @@ void __glXsetEnterLeaveServerFuncs(void (*enter)(void),
void __glXenterServer(void);
void __glXleaveServer(void);
+void glxSuspendClients(void);
+void glxResumeClients(void);
+
/*
** State kept per client.
*/
@@ -176,8 +179,6 @@ struct __GLXclientStateRec {
char *GLClientextensions;
};
-extern __GLXclientState *__glXClients[];
-
/************************************************************************/
/*