From 29eac4de82f52c8b76842616a0cfea52c7037062 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Fri, 25 Apr 2003 11:22:34 +0000 Subject: get client & server processes working properly --- src/mesa/drivers/dri/radeon/radeon_lock.c | 47 +-- src/mesa/drivers/dri/radeon/radeon_lock.h | 15 +- src/mesa/drivers/dri/radeon/radeon_subset_select.c | 114 ++++++- src/mesa/drivers/dri/radeon/server/radeon_dri.c | 143 ++++----- src/miniglx/dri_util.c | 24 +- src/miniglx/miniglx.c | 69 +---- src/miniglx/miniglxP.h | 33 ++- src/miniglx/miniglx_events.c | 329 +++++++++++++-------- 8 files changed, 436 insertions(+), 338 deletions(-) diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.c b/src/mesa/drivers/dri/radeon/radeon_lock.c index 5bc74836a5..f0ef672931 100644 --- a/src/mesa/drivers/dri/radeon/radeon_lock.c +++ b/src/mesa/drivers/dri/radeon/radeon_lock.c @@ -134,6 +134,12 @@ static void validate_drawable( radeonContextPtr rmesa ) fprintf(stderr, "%s\n", __FUNCTION__); + fprintf(stderr, + "rmesa->lastStamp %d dpriv->lastStamp %d *(dpriv->pStamp) %d\n", + rmesa->lastStamp, + dPriv->lastStamp, + *(dPriv->pStamp)); + /* The window might have moved, so we might need to get new clip * rects. * @@ -144,7 +150,8 @@ static void validate_drawable( radeonContextPtr rmesa ) */ DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv ); - if ( rmesa->lastStamp != dPriv->lastStamp ) { + if ( rmesa->lastStamp == 0 || + rmesa->lastStamp != dPriv->lastStamp ) { radeonUpdatePageFlipping( rmesa ); if (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT) @@ -171,21 +178,9 @@ void radeonGetLock( radeonContextPtr rmesa, GLuint flags ) int i; - while (1) { - drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags ); - - validate_drawable( rmesa ); - - fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->numClipRects); - - if (rmesa->numClipRects) - break; - - drmUnlock( rmesa->dri.fd, rmesa->dri.hwContext ); - - sleep(10); - } - + drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags ); + + validate_drawable( rmesa ); if ( sarea->ctxOwner != rmesa->dri.hwContext ) { sarea->ctxOwner = rmesa->dri.hwContext; @@ -200,23 +195,3 @@ void radeonGetLock( radeonContextPtr rmesa, GLuint flags ) } -extern void __miniglx_release_vt( void ); - -/* In the current miniglx, cliprects can change while the lock is - * held... Probably need to fix this. - */ -void radeonUnlock( radeonContextPtr rmesa ) -{ - fprintf(stderr, "%s\n", __FUNCTION__); - - drmUnlock( rmesa->dri.fd, rmesa->dri.hwContext ); - - validate_drawable( rmesa ); - - /* This only happens if the VT switch was requested inside the - * locked region. - */ - if (!rmesa->numClipRects) - __miniglx_release_vt(); - -} diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.h b/src/mesa/drivers/dri/radeon/radeon_lock.h index f8e35369ee..61b74eae11 100644 --- a/src/mesa/drivers/dri/radeon/radeon_lock.h +++ b/src/mesa/drivers/dri/radeon/radeon_lock.h @@ -38,7 +38,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define __RADEON_LOCK_H__ extern void radeonGetLock( radeonContextPtr rmesa, GLuint flags ); -extern void radeonUnlock( radeonContextPtr rmesa ); /* Turn DEBUG_LOCKING on to find locking conflicts. */ @@ -100,13 +99,13 @@ extern int prevLockLine; /* Unlock the hardware. */ -#define UNLOCK_HARDWARE( rmesa ) \ - do { \ - DRM_CAS_RESULT(__ret); \ - DRM_CAS( rmesa->dri.hwLock,DRM_LOCK_HELD|rmesa->dri.hwContext, \ - rmesa->dri.hwContext,__ret); \ - if (__ret) radeonUnlock( rmesa ); \ - DEBUG_RESET(); \ +#define UNLOCK_HARDWARE( rmesa ) \ + do { \ + DRM_UNLOCK( rmesa->dri.fd, \ + rmesa->dri.hwLock, \ + rmesa->dri.hwContext ); \ + DEBUG_RESET(); \ } while (0) + #endif /* __RADEON_LOCK_H__ */ diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_select.c b/src/mesa/drivers/dri/radeon/radeon_subset_select.c index bb491177bf..c1f3535f53 100644 --- a/src/mesa/drivers/dri/radeon/radeon_subset_select.c +++ b/src/mesa/drivers/dri/radeon/radeon_subset_select.c @@ -27,7 +27,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* $Id: radeon_subset_select.c,v 1.1.2.5 2003/03/17 21:23:00 keithw Exp $ */ +/* $Id: radeon_subset_select.c,v 1.1.2.6 2003/04/25 11:22:34 keithw Exp $ */ #include "glheader.h" @@ -955,6 +955,105 @@ void radeon_select_Install( GLcontext *ctx ) ctx->Driver.FlushVertices = radeonSelectFlushVertices; } +/*@}*/ + + +/**********************************************************************/ +/** \name Noop mode for operation without focus */ +/**********************************************************************/ +/*@{*/ + + +/** + * \brief Process glBegin(). + * + * \param mode primitive. + */ +static void radeon_noop_Begin(GLenum mode) +{ + GET_CURRENT_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (mode > GL_POLYGON) { + _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); + return; + } + + if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); + return; + } + + if (rmesa->dri.drawable->numClipRects) { + radeonVtxfmtInit( ctx ); + ctx->Exec->Begin( mode ); + return; + } + + fprintf(stderr, "%s\n", __FUNCTION__); + ctx->Driver.CurrentExecPrimitive = mode; +} + +/** + * \brief Process glEnd(). + */ +static void radeon_noop_End(void) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; +} + +/** + * \brief Discards all arguments. + */ +static void radeon_noop_Vertex2f(GLfloat x, GLfloat y) +{ +} + +/** + * \brief Discards all arguments. + */ +static void radeon_noop_Vertexfv(const GLfloat * v) +{ +} + +/** + * \brief Discards all arguments. + */ +static void radeon_noop_Vertex3f(GLfloat x, GLfloat y, GLfloat z) +{ +} + +/** + * \brief Install the noop callbacks. + * + * \param ctx GL context. + * + * Installs the noop callbacks into the glapi table. These functions + * will not attempt to emit any DMA vertices, but will keep internal + * GL state uptodate. Borrows heavily from the select code. + */ +static void radeon_noop_Install( GLcontext *ctx ) +{ + struct _glapi_table *exec = ctx->Exec; + + exec->Color3f = radeon_select_Color3f; + exec->Color3fv = radeon_select_Color3fv; + exec->Color4f = radeon_select_Color4f; + exec->Color4fv = radeon_select_Color4fv; + exec->TexCoord2f = radeon_select_TexCoord2f; + exec->TexCoord2fv = radeon_select_TexCoord2fv; + exec->Vertex2f = radeon_noop_Vertex2f; + exec->Vertex2fv = radeon_noop_Vertexfv; + exec->Vertex3f = radeon_noop_Vertex3f; + exec->Vertex3fv = radeon_noop_Vertexfv; + exec->Begin = radeon_noop_Begin; + exec->End = radeon_noop_End; + + ctx->Driver.FlushVertices = radeonSelectFlushVertices; +} + +/*@}*/ /** * \brief Set rasterization mode. @@ -962,14 +1061,21 @@ void radeon_select_Install( GLcontext *ctx ) * \param ctx GL context. * \param mode rasterization mode. Supports GL_RENDER or * - * Calls either radeonVtxfmtInit() or radeon_select_Install() according \p mode - * is GL_RENDER or GL_SELECT. + * If mode is GL_RENDER, calls either radeonVtxfmtInit() or + * radeon_noop_Install depending on whether the application has focus + * (ie a fullscreen-cliprect) or not. If mode is GL_SELECT, calls + * radeon_select_Install(). */ static void radeonRenderMode( GLcontext *ctx, GLenum mode ) { + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + switch (mode) { case GL_RENDER: - radeonVtxfmtInit( ctx ); + if (rmesa->dri.drawable->numClipRects) + radeonVtxfmtInit( ctx ); + else + radeon_noop_Install( ctx ); break; case GL_SELECT: radeon_select_Install( ctx ); diff --git a/src/mesa/drivers/dri/radeon/server/radeon_dri.c b/src/mesa/drivers/dri/radeon/server/radeon_dri.c index af3193d645..91b7aa4c17 100644 --- a/src/mesa/drivers/dri/radeon/server/radeon_dri.c +++ b/src/mesa/drivers/dri/radeon/server/radeon_dri.c @@ -161,17 +161,16 @@ static void RADEONEngineReset( struct MiniGLXDisplayRec *dpy ) * \brief Restore the drawing engine. * * \param dpy display handle - * \param info driver private data. * * Resets the graphics card and sets initial values for several registers of * the card's drawing engine. + * + * Turns on the radeon command processor engine (ie: the ringbuffer). */ -static void RADEONEngineRestore( struct MiniGLXDisplayRec *dpy, - RADEONInfoPtr info ) - +static int RADEONEngineRestore( struct MiniGLXDisplayRec *dpy ) { unsigned char *RADEONMMIO = dpy->MMIOAddress; - int pitch64, datatype, dp_gui_master_cntl; + int pitch64, datatype, dp_gui_master_cntl, err; OUTREG(RADEON_RB3D_CNTL, 0); RADEONEngineReset( dpy ); @@ -179,7 +178,7 @@ static void RADEONEngineRestore( struct MiniGLXDisplayRec *dpy, switch (dpy->bpp) { case 16: datatype = 4; break; case 32: datatype = 6; break; - default: return; + default: return 0; } dp_gui_master_cntl = @@ -216,6 +215,43 @@ static void RADEONEngineRestore( struct MiniGLXDisplayRec *dpy, /* RADEONWaitForIdleMMIO(dpy); */ usleep(100); + + + /* Initialize and start the CP if required */ + if ((err = drmCommandNone(dpy->drmFD, DRM_RADEON_CP_START)) != 0) { + fprintf(stderr, "%s: CP start %d\n", __FUNCTION__, err); + return 0; + } + + return True; +} + + +/** + * \brief Shutdown the drawing engine. + * + * \param dpy display handle + * + * Turns off the command processor engine & restores the graphics card + * to a state that fbdev understands. + */ +static int RADEONEngineShutdown( struct MiniGLXDisplayRec *dpy ) +{ + int err; + + /* Idle the CP engine */ + if ((err = drmCommandNone(dpy->drmFD, DRM_RADEON_CP_IDLE)) != 0) { + fprintf(stderr, "%s: CP idle %d\n", __FUNCTION__, err); + return 0; + } + + /* Stop the CP */ + if ((err = drmCommandNone(dpy->drmFD, DRM_RADEON_CP_STOP)) != 0) { + fprintf(stderr, "%s: CP stop %d\n", __FUNCTION__, err); + return 0; + } + + return True; } /** @@ -650,36 +686,6 @@ static int RADEONMemoryInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) return 1; } -static void print_client_msg( RADEONDRIPtr pRADEONDRI ) -{ - fprintf(stderr, "deviceID 0x%x\n", pRADEONDRI->deviceID); - fprintf(stderr, "width 0x%x\n", pRADEONDRI->width); - fprintf(stderr, "height 0x%x\n", pRADEONDRI->height); - fprintf(stderr, "depth 0x%x\n", pRADEONDRI->depth); - fprintf(stderr, "bpp 0x%x\n", pRADEONDRI->bpp); - fprintf(stderr, "IsPCI 0x%x\n", pRADEONDRI->IsPCI); - fprintf(stderr, "AGPMode 0x%x\n", pRADEONDRI->AGPMode); - fprintf(stderr, "frontOffset 0x%x\n", pRADEONDRI->frontOffset); - fprintf(stderr, "frontPitch 0x%x\n", pRADEONDRI->frontPitch); - fprintf(stderr, "backOffset 0x%x\n", pRADEONDRI->backOffset); - fprintf(stderr, "backPitch 0x%x\n", pRADEONDRI->backPitch); - fprintf(stderr, "depthOffset 0x%x\n", pRADEONDRI->depthOffset); - fprintf(stderr, "depthPitch 0x%x\n", pRADEONDRI->depthPitch); - fprintf(stderr, "textureOffset 0x%x\n", pRADEONDRI->textureOffset); - fprintf(stderr, "textureSize 0x%x\n", pRADEONDRI->textureSize); - fprintf(stderr, "log2TexGran 0x%x\n", pRADEONDRI->log2TexGran); - fprintf(stderr, "registerHandle 0x%x\n", (unsigned)pRADEONDRI->registerHandle); - fprintf(stderr, "registerSize 0x%x\n", pRADEONDRI->registerSize); - fprintf(stderr, "statusHandle 0x%x\n", (unsigned)pRADEONDRI->statusHandle); - fprintf(stderr, "statusSize 0x%x\n", pRADEONDRI->statusSize); - fprintf(stderr, "agpTexHandle 0x%x\n", (unsigned)pRADEONDRI->agpTexHandle); - fprintf(stderr, "agpTexMapSize 0x%x\n", pRADEONDRI->agpTexMapSize); - fprintf(stderr, "log2AGPTexGran 0x%x\n", pRADEONDRI->log2AGPTexGran); - fprintf(stderr, "agpTexOffset 0x%x\n", pRADEONDRI->agpTexOffset); - fprintf(stderr, "sarea_priv_offset 0x%x\n", pRADEONDRI->sarea_priv_offset); -} - - /** @@ -703,7 +709,6 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) { RADEONDRIPtr pRADEONDRI; int err; - unsigned int serverContext; usleep(100); assert(!dpy->IsClient); @@ -822,24 +827,24 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) /* Create a 'server' context so we can grab the lock for * initialization ioctls. */ - if ((err = drmCreateContext(dpy->drmFD, &serverContext)) != 0) { + if ((err = drmCreateContext(dpy->drmFD, &dpy->serverContext)) != 0) { fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); return 0; } - DRM_LOCK(dpy->drmFD, dpy->pSAREA, serverContext, 0); + DRM_LOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext, 0); /* Initialize the kernel data structures */ if (!RADEONDRIKernelInit(dpy, info)) { fprintf(stderr, "RADEONDRIKernelInit failed\n"); - DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, serverContext); + DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext); return 0; } /* Initialize the vertex buffers list */ if (!RADEONDRIBufInit(dpy, info)) { fprintf(stderr, "RADEONDRIBufInit failed\n"); - DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, serverContext); + DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext); return 0; } @@ -849,12 +854,9 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) /* Initialize kernel agp memory manager */ RADEONDRIAgpHeapInit(dpy, info); - RADEONEngineRestore( dpy, info ); - - /* Initialize and start the CP if required */ - if ((err = drmCommandNone(dpy->drmFD, DRM_RADEON_CP_START)) != 0) { - fprintf(stderr, "%s: CP start %d\n", __FUNCTION__, err); - DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, serverContext); + fprintf(stderr, "calling RADEONEngineRestore from %s\n", __FUNCTION__); + if (!RADEONEngineRestore( dpy )) { + DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext); return 0; } @@ -882,7 +884,7 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) /* Can release the lock now */ - DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, serverContext); + DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext); /* This is the struct passed to radeon_dri.so for its initialization */ dpy->driverClientMsg = malloc(sizeof(RADEONDRIRec)); @@ -914,8 +916,6 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) pRADEONDRI->agpTexOffset = info->agpTexStart; pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec); - print_client_msg( pRADEONDRI ); - return 1; } @@ -1202,46 +1202,6 @@ static void radeonHaltFBDev( struct MiniGLXDisplayRec *dpy ) } -/** - * \brief A VT release or aquire signal has been received, and - * requires some action. We deal with loosing the VT by setting the - * cliprects to zero and emitting an event to the application. - */ -static int radeonVTSwitchHandler( struct MiniGLXDisplayRec *dpy, int have_vt ) -{ - int *lock = (int *)dpy->pSAREA; - int old, new; - DRM_CAS_RESULT(ret); - GLXDrawable draw; - __DRIdrawable *pdraw; - __DRIdrawablePrivate *pdp; - - /* Indicate cliprects have changed - */ - draw = dpy->TheWindow; - if (!draw) return 1; - pdraw = &draw->driDrawable; - if (!pdraw) return 1; - pdp = (__DRIdrawablePrivate *) pdraw->private; - if (!pdp) return 1; - pdp->lastStamp++; - pdp->numClipRects = have_vt ? 1 : 0; - - /* Mark the lock contended. - */ - if (!dpy->pSAREA) return 0; - do { - old = *(int *)dpy->pSAREA; - new = old | _DRM_LOCK_CONT; - DRM_CAS( lock, old, new, ret ); - fprintf(stderr, "old %x new %x\n", old, new ); - } while (ret); - - if (have_vt) - return !(old & _DRM_LOCK_HELD); - else - return 1; -} /** * \brief Exported driver interface for Mini GLX. @@ -1254,5 +1214,6 @@ struct MiniGLXDriverRec __driMiniGLXDriver = { radeonPostValidateMode, radeonInitFBDev, radeonHaltFBDev, - radeonVTSwitchHandler + RADEONEngineShutdown, + RADEONEngineRestore }; diff --git a/src/miniglx/dri_util.c b/src/miniglx/dri_util.c index 994f16b177..2a3c2000ce 100644 --- a/src/miniglx/dri_util.c +++ b/src/miniglx/dri_util.c @@ -22,6 +22,8 @@ #include #include "GL/miniglx.h" #include "miniglxP.h" +#include +#include #include "sarea.h" @@ -282,8 +284,12 @@ static Bool driBindContext(Display *dpy, int scrn, */ void __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) { - fprintf(stderr, "%s\n", __FUNCTION__); - /* nothing to do */ + __DRIscreenPrivate *psp = pdp->driScreenPriv; + + pdp->numClipRects = psp->pSAREA->drawableTable[pdp->index].flags ? 1 : 0; + pdp->lastStamp = *(pdp->pStamp); + + fprintf(stderr, "%s: %d cliprects\n", __FUNCTION__, pdp->numClipRects); } @@ -362,11 +368,10 @@ static void *driCreateDrawable(Display *dpy, int scrn, return NULL; } + pdp->index = dpy->clientID; pdp->draw = draw; pdp->refcount = 0; - pdp->pStamp = &pdp->lastStamp; - pdp->lastStamp = 1; - pdp->index = 0; + pdp->lastStamp = -1; pdp->numBackClipRects = 0; pdp->pBackClipRects = NULL; pdp->display = dpy; @@ -411,6 +416,12 @@ static void *driCreateDrawable(Display *dpy, int scrn, pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */ pdp->swapBuffers = psp->DriverAPI.SwapBuffers; + fprintf(stderr, "%s index: %d stamp: %d\n", + __FUNCTION__, pdp->index, + psp->pSAREA->drawableTable[pdp->index].stamp); + + pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp); + __driUtilUpdateDrawableInfo( pdp ); return (void *) pdp; } @@ -790,4 +801,7 @@ __driUtilInitScreen( Display *dpy, int scrn, __DRIscreen *psc ) psc->getDrawable = driGetDrawable; } + + + /*@}*/ diff --git a/src/miniglx/miniglx.c b/src/miniglx/miniglx.c index 2b095f4140..a03978e81d 100644 --- a/src/miniglx/miniglx.c +++ b/src/miniglx/miniglx.c @@ -22,7 +22,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* $Id: miniglx.c,v 1.1.4.51 2003/04/17 15:46:42 keithw Exp $ */ +/* $Id: miniglx.c,v 1.1.4.52 2003/04/25 11:22:36 keithw Exp $ */ /** @@ -127,73 +127,26 @@ static GLXContext CurrentContext = NULL; -/* Called from signal handler context, runs atomically wrt - * XCheckWindowEvent. - */ -static void queue_event( Display *dpy, int aquire ) -{ - dpy->haveVT = aquire; - dpy->aquireVTCount += aquire; - dpy->releaseVTCount += !aquire; -} - static Display *SignalDisplay = 0; static void SwitchVT(int sig) { fprintf(stderr, "SwitchVT %d dpy %p\n", sig, SignalDisplay); - if (!SignalDisplay) { - fprintf(stderr, "No display!\n"); - return; - } - - switch( sig ) - { - case SIGUSR1: /* vt has been released */ - if (SignalDisplay->driver && - !SignalDisplay->driver->handleVTSwitch( SignalDisplay, 0 )) - return; - if (!SignalDisplay->haveVT) { - fprintf(stderr, "%s: Don't have VT\n", __FUNCTION__); - return; - } - __miniglx_release_vt(); - break; - case SIGUSR2: /* vt has been acquired */ - ioctl( SignalDisplay->ConsoleFD, VT_RELDISP, VT_ACTIVATE ); - sleep(1); - - if (SignalDisplay->driver && - !SignalDisplay->driver->handleVTSwitch( SignalDisplay, 1 )) - return; - - if (SignalDisplay->haveVT) { - fprintf(stderr, "%s: Already have VT\n", __FUNCTION__); - return; + if (SignalDisplay) { + SignalDisplay->vtSignalFlag = 1; + switch( sig ) + { + case SIGUSR1: /* vt has been released */ + SignalDisplay->haveVT = 0; + break; + case SIGUSR2: /* vt has been acquired */ + SignalDisplay->haveVT = 1; + break; } - - queue_event( SignalDisplay, 1 ); - break; } } -void __miniglx_release_vt( void ) -{ - if (!SignalDisplay) - return; - - if (!SignalDisplay->haveVT) { - fprintf(stderr, "%s: Don't have VT\n", __FUNCTION__); - return; - } - - sleep(1); - ioctl( SignalDisplay->ConsoleFD, VT_RELDISP, 1 ); - queue_event( SignalDisplay, 0 ); -} - - /**********************************************************************/ /** \name Framebuffer device functions */ /**********************************************************************/ diff --git a/src/miniglx/miniglxP.h b/src/miniglx/miniglxP.h index 052d896fd9..bbee5d6ae4 100644 --- a/src/miniglx/miniglxP.h +++ b/src/miniglx/miniglxP.h @@ -206,10 +206,16 @@ struct MiniGLXDriverRec { */ void (*haltFBDev)( struct MiniGLXDisplayRec *dpy ); + /** - * \brief Handle VT switch events. + * \brief Idle and shutdown hardware in preparation for a vt switch. */ - int (*handleVTSwitch)( struct MiniGLXDisplayRec *dpy, int have_vt ); + int (*shutdownHardware)( struct MiniGLXDisplayRec *dpy ); + + /** + * \brief Restore hardware state after regaining the vt. + */ + int (*restoreHardware)( struct MiniGLXDisplayRec *dpy ); }; @@ -316,22 +322,18 @@ struct MiniGLXDisplayRec { int ConsoleFD; /**< \brief console TTY device file descriptor */ int FrameBufferFD; /**< \brief framebuffer device file descriptor */ caddr_t FrameBuffer; /**< \brief start of the mmap'd framebuffer */ -/* int FrameBufferSize; */ /**< \brief size of the mmap'd framebuffer in bytes */ caddr_t MMIOAddress; /**< \brief start of the mmap'd MMIO region */ int MMIOSize; /**< \brief size of the mmap'd MMIO region in bytes */ int NumWindows; /**< \brief number of open windows */ Window TheWindow; /**< \brief open window - only allow one window for now */ int rotateMode; - int haveVT; - int aquireVTCount; - int releaseVTCount; - int exposeNotifyCount; - int mapNotifyCount; - int unmapNotifyCount; + + volatile int vtSignalFlag, haveVT; + int hwActive; - int IsClient; + int IsClient, clientID; int nrFds; struct MiniGLXConnection *fd; @@ -384,6 +386,13 @@ struct MiniGLXDisplayRec { /*@}*/ + /** + * \name Client configuration details + * + * These are computed on the server and sent to clients as part of + * the initial handshaking. + */ + /*@{*/ struct { unsigned long hSAREA; int SAREASize; @@ -394,6 +403,7 @@ struct MiniGLXDisplayRec { int virtualWidth; int virtualHeight; } shared; + /*@}*/ /** @@ -401,7 +411,8 @@ struct MiniGLXDisplayRec { */ /*@{*/ int drmFD; /**< \brief DRM device file descriptor */ - void *pSAREA; + struct _XF86DRISAREA *pSAREA; + unsigned int serverContext; /**< \brief DRM context only active on server */ /*@}*/ /** diff --git a/src/miniglx/miniglx_events.c b/src/miniglx/miniglx_events.c index 2e2e7d7c5e..6afa9be277 100644 --- a/src/miniglx/miniglx_events.c +++ b/src/miniglx/miniglx_events.c @@ -22,7 +22,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* $Id: miniglx_events.c,v 1.1.2.3 2003/04/22 14:29:53 keithw Exp $ */ +/* $Id: miniglx_events.c,v 1.1.2.4 2003/04/25 11:22:36 keithw Exp $ */ /** @@ -62,7 +62,8 @@ #include "miniglxP.h" -#include "glapi.h" +#include "xf86drm.h" +#include "sarea.h" #define MINIGLX_FIFO_NAME "/tmp/miniglx.fifo" @@ -95,7 +96,7 @@ static XEvent *queue_event( Display *dpy ) static int dequeue_event( Display *dpy, XEvent *event_return ) { if (dpy->eventqueue.tail == dpy->eventqueue.head) { - fprintf(stderr, "dequeue_event: queue empty\n"); +/* fprintf(stderr, "dequeue_event: queue empty\n"); */ return False; } else { @@ -196,6 +197,12 @@ static int welcome_message_part( Display *dpy, int i, void **msg, int sz ) static int welcome_message( Display *dpy, int i ) { void *tmp = &dpy->shared; + int *clientid = dpy->IsClient ? &dpy->clientID : &i; + + if (!welcome_message_part( dpy, i, (void **)&clientid, sizeof(*clientid))) + return False; + + fprintf(stderr, "**** CLIENT ID: %d\n", *clientid); if (!welcome_message_part( dpy, i, &tmp, sizeof(dpy->shared))) return False; @@ -261,133 +268,166 @@ static int handle_new_client( Display *dpy ) static int handle_fifo_read( Display *dpy, int i ) { - char id = dpy->fd[i].readbuf[0]; - XEvent *er; - int count = 1; - - if (dpy->IsClient) { - switch (id) { - /* The server has called 'XMapWindow' on a client window */ - case _YouveGotFocus: - fprintf(stderr, "_YouveGotFocus\n"); - er = queue_event(dpy); - if (!er) return False; - er->xmap.type = MapNotify; - er->xmap.serial = 0; - er->xmap.send_event = False; - er->xmap.display = dpy; - er->xmap.event = dpy->TheWindow; - er->xmap.window = dpy->TheWindow; - er->xmap.override_redirect = False; - break; - - /* The server has called 'XMapWindow' or 'X???' on a client - * window */ - case _RepaintPlease: - fprintf(stderr, "_RepaintPlease\n"); - er = queue_event(dpy); - if (!er) return False; - er->xexpose.type = Expose; - er->xexpose.serial = 0; - er->xexpose.send_event = False; - er->xexpose.display = dpy; - er->xexpose.window = dpy->TheWindow; - if (dpy->rotateMode) { - er->xexpose.x = dpy->TheWindow->y; - er->xexpose.y = dpy->TheWindow->x; - er->xexpose.width = dpy->TheWindow->h; - er->xexpose.height = dpy->TheWindow->w; - } - else { - er->xexpose.x = dpy->TheWindow->x; - er->xexpose.y = dpy->TheWindow->y; - er->xexpose.width = dpy->TheWindow->w; - er->xexpose.height = dpy->TheWindow->h; - } - er->xexpose.count = 0; - break; - - /* The server has called 'XUnmapWindow' on a client window */ - case _YouveLostFocus: - fprintf(stderr, "_YouveLostFocus\n"); - er = queue_event(dpy); - if (!er) return False; - er->xunmap.type = UnmapNotify; - er->xunmap.serial = 0; - er->xunmap.send_event = False; - er->xunmap.display = dpy; - er->xunmap.event = dpy->TheWindow; - er->xunmap.window = dpy->TheWindow; - er->xunmap.from_configure = False; - break; + while (dpy->fd[i].readbuf_count) { + char id = dpy->fd[i].readbuf[0]; + XEvent *er; + int count = 1; + + if (dpy->IsClient) { + switch (id) { + /* The server has called 'XMapWindow' on a client window */ + case _YouveGotFocus: + fprintf(stderr, "_YouveGotFocus\n"); + er = queue_event(dpy); + if (!er) return False; + er->xmap.type = MapNotify; + er->xmap.serial = 0; + er->xmap.send_event = False; + er->xmap.display = dpy; + er->xmap.event = dpy->TheWindow; + er->xmap.window = dpy->TheWindow; + er->xmap.override_redirect = False; + break; + + /* The server has called 'XMapWindow' or 'X???' on a client + * window */ + case _RepaintPlease: + fprintf(stderr, "_RepaintPlease\n"); + er = queue_event(dpy); + if (!er) return False; + er->xexpose.type = Expose; + er->xexpose.serial = 0; + er->xexpose.send_event = False; + er->xexpose.display = dpy; + er->xexpose.window = dpy->TheWindow; + if (dpy->rotateMode) { + er->xexpose.x = dpy->TheWindow->y; + er->xexpose.y = dpy->TheWindow->x; + er->xexpose.width = dpy->TheWindow->h; + er->xexpose.height = dpy->TheWindow->w; + } + else { + er->xexpose.x = dpy->TheWindow->x; + er->xexpose.y = dpy->TheWindow->y; + er->xexpose.width = dpy->TheWindow->w; + er->xexpose.height = dpy->TheWindow->h; + } + er->xexpose.count = 0; + break; + + /* The server has called 'XUnmapWindow' on a client window. + * + * Need to set lock contended and adjust cliprects (or the + * server does). + */ + case _YouveLostFocus: + fprintf(stderr, "_YouveLostFocus\n"); + er = queue_event(dpy); + if (!er) return False; + er->xunmap.type = UnmapNotify; + er->xunmap.serial = 0; + er->xunmap.send_event = False; + er->xunmap.display = dpy; + er->xunmap.event = dpy->TheWindow; + er->xunmap.window = dpy->TheWindow; + er->xunmap.from_configure = False; + break; - default: - fprintf(stderr, "Client received unhandled message type %d\n", id); - shut_fd(dpy, i); /* Actually shuts down the client */ - return False; + default: + fprintf(stderr, "Client received unhandled message type %d\n", id); + shut_fd(dpy, i); /* Actually shuts down the client */ + return False; + } } - } - else { - switch (id) { - /* Lets the server know that the client is ready to render - * (having called 'XMapWindow' locally). - */ - case _CanIHaveFocus: - fprintf(stderr, "_CanIHaveFocus\n"); - er = queue_event(dpy); - if (!er) return False; - er->xmaprequest.type = MapRequest; - er->xmaprequest.serial = 0; - er->xmaprequest.send_event = False; - er->xmaprequest.display = dpy; - er->xmaprequest.parent = 0; - er->xmaprequest.window = (Window)i; - fprintf(stderr, "queued MapRequest\n"); - break; - - /* Both _YouveLostFocus and _IDontWantFocus generate unmap - * events. The idea is that _YouveLostFocus lets the client - * know that it has had focus revoked by the server, whereas - * _IDontWantFocus lets the server know that the client has - * unmapped its own window. - */ - case _IDontWantFocus: - fprintf(stderr, "_IDontWantFocus\n"); - er = queue_event(dpy); - if (!er) return False; - er->xunmap.type = UnmapNotify; - er->xunmap.serial = 0; - er->xunmap.send_event = False; - er->xunmap.display = dpy; - er->xunmap.event = (Window)i; - er->xunmap.window = (Window)i; - er->xunmap.from_configure = False; - break; - - default: - fprintf(stderr, "Server received unhandled message type %d\n", id); - shut_fd(dpy, i); /* Generates DestroyNotify event */ - return False; + else { + switch (id) { + /* Lets the server know that the client is ready to render + * (having called 'XMapWindow' locally). + */ + case _CanIHaveFocus: + fprintf(stderr, "_CanIHaveFocus\n"); + er = queue_event(dpy); + if (!er) return False; + er->xmaprequest.type = MapRequest; + er->xmaprequest.serial = 0; + er->xmaprequest.send_event = False; + er->xmaprequest.display = dpy; + er->xmaprequest.parent = 0; + er->xmaprequest.window = (Window)i; + fprintf(stderr, "queued MapRequest\n"); + break; + + /* Both _YouveLostFocus and _IDontWantFocus generate unmap + * events. The idea is that _YouveLostFocus lets the client + * know that it has had focus revoked by the server, whereas + * _IDontWantFocus lets the server know that the client has + * unmapped its own window. + */ + case _IDontWantFocus: + fprintf(stderr, "_IDontWantFocus\n"); + er = queue_event(dpy); + if (!er) return False; + er->xunmap.type = UnmapNotify; + er->xunmap.serial = 0; + er->xunmap.send_event = False; + er->xunmap.display = dpy; + er->xunmap.event = (Window)i; + er->xunmap.window = (Window)i; + er->xunmap.from_configure = False; + break; + + default: + fprintf(stderr, "Server received unhandled message type %d\n", id); + shut_fd(dpy, i); /* Generates DestroyNotify event */ + return False; + } } - } - dpy->fd[i].readbuf_count -= count; + dpy->fd[i].readbuf_count -= count; - /* This probably never happens, but just in case: */ - if (dpy->fd[i].readbuf_count) { - fprintf(stderr, "count: %d memmove %p %p %d\n", count, - dpy->fd[i].readbuf + count, - dpy->fd[i].readbuf, - dpy->fd[i].readbuf_count); + if (dpy->fd[i].readbuf_count) { + fprintf(stderr, "count: %d memmove %p %p %d\n", count, + dpy->fd[i].readbuf, + dpy->fd[i].readbuf + count, + dpy->fd[i].readbuf_count); - memmove(dpy->fd[i].readbuf + count, - dpy->fd[i].readbuf, - dpy->fd[i].readbuf_count); + memmove(dpy->fd[i].readbuf, + dpy->fd[i].readbuf + count, + dpy->fd[i].readbuf_count); + } } return True; } +static void __driHandleVtSignals( Display *dpy ) +{ + dpy->vtSignalFlag = 0; + + if (!dpy->haveVT && dpy->hwActive) { + /* Need to get lock and shutdown hardware */ + DRM_LIGHT_LOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext ); +/* dpy->driver->shutdownHardware( dpy ); */ + + /* Can now give up control of the VT */ + ioctl( dpy->ConsoleFD, VT_RELDISP, 1 ); + dpy->hwActive = 0; + } + else if (dpy->haveVT && !dpy->hwActive) { + /* Get VT (wait??) */ + ioctl( dpy->ConsoleFD, VT_RELDISP, VT_ACTIVATE ); + + /* restore HW state, release lock */ +/* dpy->driver->restoreHardware( dpy ); */ + DRM_UNLOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext ); + dpy->hwActive = 1; + } + else + fprintf(stderr, "handle_vt_signals: haveVT %d hwActive %d\n", + dpy->haveVT, dpy->hwActive); +} + + #undef max #define max(x,y) ((x) > (y) ? (x) : (y)) @@ -432,7 +472,14 @@ __miniglx_Select( Display *dpy, int n, fd_set *rfds, fd_set *wfds, fd_set *xfds, } + if (dpy->vtSignalFlag) + __driHandleVtSignals( dpy ); + retval = select( n, rfds, wfds, xfds, tv ); + + if (dpy->vtSignalFlag) + __driHandleVtSignals( dpy ); + if (retval < 0) return retval; @@ -470,8 +517,8 @@ __miniglx_Select( Display *dpy, int n, fd_set *rfds, fd_set *wfds, fd_set *xfds, else { dpy->fd[i].writebuf_count -= r; if (dpy->fd[i].writebuf_count) { - memmove(dpy->fd[i].writebuf + r, - dpy->fd[i].writebuf, + memmove(dpy->fd[i].writebuf, + dpy->fd[i].writebuf + r, dpy->fd[i].writebuf_count); } } @@ -530,6 +577,8 @@ int __miniglx_open_connections( Display *dpy ) perror("unlink " MINIGLX_FIFO_NAME); return False; } + + umask( 0000 ); /* open to everybody ? */ } /* Create a unix socket -- Note this is *not* a network connection! @@ -553,8 +602,7 @@ int __miniglx_open_connections( Display *dpy ) return False; } - /* Wait for confirmation from the server, in the form of a _DriverInfo - * message. + /* Wait for configuration messages from the server. */ welcome_message( dpy, 0 ); } @@ -590,6 +638,29 @@ void __miniglx_close_connections( Display *dpy ) FREE(dpy->fd); } + +static void set_drawable_flag( Display *dpy, int w, int flag ) +{ + fprintf(stderr, "%s %d %d\n", __FUNCTION__, w, flag); + + if (dpy->pSAREA) { + DRM_LIGHT_LOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext ); + + dpy->pSAREA->drawableTable[w].stamp++; + dpy->pSAREA->drawableTable[w].flags = flag; + + fprintf(stderr, "%s: stamp now %d\n", + __FUNCTION__, + dpy->pSAREA->drawableTable[w].stamp); + + + DRM_UNLOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext ); + } +} + + + + /** * \brief Map Window. * @@ -607,6 +678,7 @@ XMapWindow( Display *dpy, Window w ) if (dpy->IsClient) send_char_msg( dpy, 0, _CanIHaveFocus ); else { + set_drawable_flag( dpy, (int)w, 1 ); send_char_msg( dpy, (int)w, _YouveGotFocus ); send_char_msg( dpy, (int)w, _RepaintPlease ); } @@ -622,11 +694,18 @@ XMapWindow( Display *dpy, Window w ) * it is impossible to force them to keep updating their contents & at * least this way there is notification that they've stopped. * + * The entrypoint is required for the server in any case. */ void -XUnmapWindow( Display *dpy, Window window ) +XUnmapWindow( Display *dpy, Window w ) { - send_char_msg( dpy, 0, dpy->IsClient ? _IDontWantFocus : _YouveLostFocus ); + if (dpy->IsClient) { + send_char_msg( dpy, 0, _IDontWantFocus ); + } + else { + set_drawable_flag( dpy, (int)w, 0 ); + send_char_msg( dpy, (int)w, _YouveLostFocus ); + } } -- cgit v1.2.3