diff --git a/GL/glx/glxdri.c b/GL/glx/glxdri.c index cfa9996..77fa4bf 100644 --- a/GL/glx/glxdri.c +++ b/GL/glx/glxdri.c @@ -63,27 +63,30 @@ #include "dispatch.h" #define STRINGIFY(macro_or_string) STRINGIFY_ARG (macro_or_string) #define STRINGIFY_ARG(contents) #contents -typedef struct __GLXDRIscreen __GLXDRIscreen; -typedef struct __GLXDRIcontext __GLXDRIcontext; +typedef struct __GLXDRIscreen __GLXDRIscreen; +typedef struct __GLXDRIcontext __GLXDRIcontext; typedef struct __GLXDRIdrawable __GLXDRIdrawable; struct __GLXDRIscreen { - __GLXscreen base; + __GLXscreen base; - __DRIscreen driScreen; - void *driver; + xf86EnterVTProc *enterVT; + xf86LeaveVTProc *leaveVT; + + __DRIscreen driScreen; + void *driver; }; struct __GLXDRIcontext { - __GLXcontext base; + __GLXcontext base; - __DRIcontext driContext; + __DRIcontext driContext; }; struct __GLXDRIdrawable { - __GLXdrawable base; + __GLXdrawable base; - __DRIdrawable *driDrawable; + __DRIdrawable *driDrawable; }; /* History: @@ -594,8 +597,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; } @@ -789,6 +791,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) { @@ -813,6 +839,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen) void *dev_priv = NULL; char filename[128]; Bool isCapable; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; if (!xf86LoaderCheckSymbol("DRIQueryDirectRenderingCapable")) { LogMessage(X_ERROR, "AIGLX: DRI module not loaded\n"); @@ -983,6 +1010,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 8bbb83f..edc257c 100644 --- a/GL/glx/glxext.c +++ b/GL/glx/glxext.c @@ -234,13 +231,11 @@ 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(); + __glXleaveServer(); cx->destroy(cx); - if (!inDispatch) - __glXenterServer(); + __glXenterServer(); return GL_TRUE; } @@ -336,7 +331,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; } @@ -407,11 +402,36 @@ __GLXcontext *__glXForceCurrent(__GLXcli /************************************************************************/ -/* -** Top level dispatcher; all commands are executed from here down. -*/ +static int glxServerLeaveCount; +static int glxBlockClients; -/* I cried when I wrote this. Damn you XAA! */ +void glxSuspendClients(void) +{ + int i; + + for (i = 1; i <= MAXCLIENTS; i++) { + if (__glXClients[i] == NULL || !__glXClients[i]->inUse) + continue; + + IgnoreClient(__glXClients[i]->client); + } + + glxBlockClients = TRUE; +} + +void glxResumeClients(void) +{ + int i; + + glxBlockClients = FALSE; + + for (i = 1; i <= MAXCLIENTS; i++) { + if (__glXClients[i] == NULL || !__glXClients[i]->inUse) + continue; + + AttendClient(__glXClients[i]->client); + } +} static void __glXnopEnterServer(void) @@ -436,14 +456,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. @@ -496,6 +521,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. */ @@ -506,12 +540,8 @@ static int __glXDispatch(ClientPtr clien __glXleaveServer(); - inDispatch = True; - retval = proc(cl, (GLbyte *) stuff); - inDispatch = False; - __glXenterServer(); return retval; diff --git a/GL/glx/glxserver.h b/GL/glx/glxserver.h index 8ece1e2..9eed1bc 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. */