xserver: Branch 'master'

Kristian Høgsberg krh at kemper.freedesktop.org
Thu Sep 7 22:35:32 EEST 2006


 GL/glx/glxdri.c    |   36 ++++++++++++++++++++-
 GL/glx/glxext.c    |   90 +++++++++++++++++++++++++++++++++++++++--------------
 GL/glx/glxserver.h |    5 +-
 3 files changed, 104 insertions(+), 27 deletions(-)

New commits:
diff-tree 86450998da616e3d00d4d6293acc35eccc2061e7 (from 64479fffa22581cc7d753065c33eda5520b7db9a)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu Sep 7 15:35:16 2006 -0400

    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.

diff --git a/GL/glx/glxdri.c b/GL/glx/glxdri.c
index 41e49e2..b572304 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
 
 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 inter
 
 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 fdb8ea2..11fb7fc 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 *
     return True;
 }
 
+static __GLXcontext *glxPendingDestroyContexts;
+static int glxServerLeaveCount;
+static int glxBlockClients;
+
 /*
 ** Free a context.
 */
@@ -236,13 +237,14 @@ GLboolean __glXFreeContext(__GLXcontext 
      * __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(__GLXcli
 
 /************************************************************************/
 
-/*
-** 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 
 
 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 clien
 	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 clien
     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 8389737..49cad73 100644
--- a/GL/glx/glxserver.h
+++ b/GL/glx/glxserver.h
@@ -136,6 +136,9 @@ void __glXsetEnterLeaveServerFuncs(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[];
-
 /************************************************************************/
 
 /*



More information about the xorg-commit mailing list