Michael wrote: > > On Tue, May 21, 2002 at 12:14:45AM +0100, Keith Whitwell wrote: > > I have a .XF86config-radeon that sets ModulesPath to that directory, and maybe > > I need to set an env var or two... I guess the magic is adding up. > > Yeah, I should have rtfm'd, ModulesPath into .../exports/lib/modules > fixes it, thanks. > > glxgears > 5229 frames in 5.0 seconds = 1045.800 FPS > 5210 frames in 5.0 seconds = 1042.000 FPS > > 200fps+ at least there
I've done some more work & will probably commit shortly. This is good stuff, I think. Changes since last time: - Deprecate the Open/Close Fullscreen foo. - Automatically turn pageflipping on when there is exactly one 3d client -- There may be situations where this isn't a good idea, perhaps many many cliprects? - 2D driver copes with situations where the pages are left wrong-way-round after last client exits - Separate out the 'flip' and 'swap' functions to separate ioctls. (D'oh) - A little testing It's looking pretty good now. Multiple 3d clients coordinate amoungst themselves, pageflipping comes on whenever possible. There are only a couple of small glitches to fix before I commit. Keith
Index: lib/GL/mesa/src/drv/radeon/radeon_context.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v retrieving revision 1.7.2.19 diff -u -r1.7.2.19 radeon_context.c --- lib/GL/mesa/src/drv/radeon/radeon_context.c 2 May 2002 13:28:07 -0000 1.7.2.19 +++ lib/GL/mesa/src/drv/radeon/radeon_context.c 21 May 2002 11:40:31 -0000 @@ -694,58 +694,19 @@ return GL_TRUE; } -/* Initialize the fullscreen mode. +/* Fullscreen mode isn't used for much -- could be a way to shrink + * front/back buffers & get more texture memory if the client has + * changed the video resolution. + * + * Pageflipping is now done automatically whenever there is a single + * 3d client. */ static GLboolean -radeonOpenFullScreen( __DRIcontextPrivate *driContextPriv ) +radeonOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv ) { - fprintf(stderr, "%s\n", __FUNCTION__); -#if 0 - radeonContextPtr rmesa = (radeonContextPtr)driContextPriv->driverPrivate; - GLint ret; - - /* FIXME: Do we need to check this? - */ - if ( !rmesa->glCtx->Visual.doubleBufferMode ) - return GL_TRUE; - - LOCK_HARDWARE( rmesa ); - radeonWaitForIdleLocked( rmesa ); - - /* Ignore errors. If this fails, we simply don't do page flipping. - */ - ret = drmRadeonFullScreen( rmesa->driFd, GL_TRUE ); - - UNLOCK_HARDWARE( rmesa ); - - rmesa->doPageFlip = ( ret == 0 ); -#endif return GL_TRUE; } -/* Shut down the fullscreen mode. - */ -static GLboolean -radeonCloseFullScreen( __DRIcontextPrivate *driContextPriv ) -{ - fprintf(stderr, "%s\n", __FUNCTION__); -#if 0 - radeonContextPtr rmesa = (radeonContextPtr)driContextPriv->driverPrivate; - - LOCK_HARDWARE( rmesa ); - radeonWaitForIdleLocked( rmesa ); - - /* Don't care if this fails, we're not page flipping anymore. - */ - drmRadeonFullScreen( rmesa->driFd, GL_FALSE ); - - UNLOCK_HARDWARE( rmesa ); - - rmesa->doPageFlip = GL_FALSE; - rmesa->currentPage = 0; -#endif - return GL_TRUE; -} /* This function is called by libGL.so as soon as libGL.so is loaded. @@ -768,8 +729,8 @@ radeonSwapBuffers, radeonMakeCurrent, radeonUnbindContext, - radeonOpenFullScreen, - radeonCloseFullScreen + radeonOpenCloseFullScreen, + radeonOpenCloseFullScreen }; Index: lib/GL/mesa/src/drv/radeon/radeon_ioctl.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v retrieving revision 1.11.2.20 diff -u -r1.11.2.20 radeon_ioctl.c --- lib/GL/mesa/src/drv/radeon/radeon_ioctl.c 10 May 2002 13:28:51 -0000 1.11.2.20 +++ lib/GL/mesa/src/drv/radeon/radeon_ioctl.c 21 May 2002 11:40:40 -0000 @@ -693,8 +693,8 @@ rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; if ( RADEON_DEBUG & DEBUG_IOCTL ) { - fprintf( stderr, "\n%s( %p ): page=%d\n\n", - __FUNCTION__, rmesa->glCtx, rmesa->currentPage ); + fprintf(stderr, "%s %d/%d\n", __FUNCTION__, rmesa->currentPage, + rmesa->sarea->pfCurrentPage ); } RADEON_FIREVERTICES( rmesa ); @@ -710,15 +710,12 @@ rmesa->hardwareWentIdle = 0; } - /* The kernel will have been initialized to perform page flipping - * on a swapbuffers ioctl. - */ - ret = drmRadeonSwapBuffers( rmesa->dri.fd ); + ret = drmRadeonFlipBuffers( rmesa->dri.fd ); UNLOCK_HARDWARE( rmesa ); if ( ret ) { - fprintf( stderr, "drmRadeonSwapBuffers: return = %d\n", ret ); + fprintf( stderr, "drmRadeonFlipBuffers: return = %d\n", ret ); exit( 1 ); } @@ -732,6 +729,7 @@ rmesa->currentPage = 0; } + assert( rmesa->currentPage == rmesa->sarea->pfCurrentPage ); RADEON_STATECHANGE( rmesa, ctx ); rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset; rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch; Index: lib/GL/mesa/src/drv/radeon/radeon_lock.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c,v retrieving revision 1.7.2.2 diff -u -r1.7.2.2 radeon_lock.c --- lib/GL/mesa/src/drv/radeon/radeon_lock.c 20 Feb 2002 17:27:33 -0000 1.7.2.2 +++ lib/GL/mesa/src/drv/radeon/radeon_lock.c 21 May 2002 11:40:40 -0000 @@ -44,6 +44,21 @@ int prevLockLine = 0; #endif +/* Turn on/off page flipping according to the flags in the sarea: + */ +static void +radeonUpdatePageFlipping( radeonContextPtr rmesa ) +{ + + rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip; + rmesa->currentPage = rmesa->sarea->pfCurrentPage; + + fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__, + rmesa->doPageFlip, + rmesa->currentPage ); +} + + /* Update the hardware state. This is called if another context has * grabbed the hardware lock, which includes the X server. This @@ -73,6 +88,7 @@ DRI_VALIDATE_DRAWABLE_INFO( rmesa->dri.display, sPriv, dPriv ); if ( rmesa->lastStamp != dPriv->lastStamp ) { + radeonUpdatePageFlipping( rmesa ); radeonSetCliprects( rmesa, rmesa->glCtx->Color.DriverDrawBuffer ); radeonUpdateViewportOffset( rmesa->glCtx ); rmesa->lastStamp = dPriv->lastStamp; Index: lib/GL/mesa/src/drv/radeon/radeon_span.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v retrieving revision 1.11.2.4 diff -u -r1.11.2.4 radeon_span.c --- lib/GL/mesa/src/drv/radeon/radeon_span.c 25 Mar 2002 10:27:15 -0000 1.11.2.4 +++ lib/GL/mesa/src/drv/radeon/radeon_span.c 21 May 2002 11:40:40 -0000 @@ -292,12 +292,22 @@ switch ( mode ) { case GL_FRONT_LEFT: - rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset; - rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch; + if ( rmesa->doPageFlip && rmesa->currentPage == 0 ) { + rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + } else { + rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + } break; case GL_BACK_LEFT: - rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset; - rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch; + if ( rmesa->doPageFlip && rmesa->currentPage == 1 ) { + rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + } else { + rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + } break; default: assert(0); Index: lib/GL/mesa/src/drv/radeon/radeon_state.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v retrieving revision 1.10.2.23 diff -u -r1.10.2.23 radeon_state.c --- lib/GL/mesa/src/drv/radeon/radeon_state.c 10 May 2002 14:38:59 -0000 1.10.2.23 +++ lib/GL/mesa/src/drv/radeon/radeon_state.c 21 May 2002 11:40:40 -0000 @@ -1508,7 +1508,9 @@ rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects; break; case GL_BACK_LEFT: - if ( dPriv->numBackClipRects == 0 ) { + /* Can't ignore 2d windows if we are page flipping. + */ + if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) { rmesa->numClipRects = dPriv->numClipRects; rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects; } @@ -1540,14 +1542,24 @@ switch ( mode ) { case GL_FRONT_LEFT: FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); - rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + if ( rmesa->doPageFlip && rmesa->currentPage == 0 ) { + rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + } else { + rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + } radeonSetCliprects( rmesa, GL_FRONT_LEFT ); break; case GL_BACK_LEFT: FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); - rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + if ( rmesa->doPageFlip && rmesa->currentPage == 1 ) { + rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + } else { + rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + } radeonSetCliprects( rmesa, GL_BACK_LEFT ); break; default: Index: programs/Xserver/GL/dri/dri.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/GL/dri/dri.c,v retrieving revision 1.37 diff -u -r1.37 dri.c --- programs/Xserver/GL/dri/dri.c 27 Jan 2002 20:05:25 -0000 1.37 +++ programs/Xserver/GL/dri/dri.c 21 May 2002 11:40:50 -0000 @@ -844,14 +844,26 @@ static void DRITransitionToSharedBuffers(ScreenPtr pScreen) { + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionSingleToMulti3D) + pDRIInfo->TransitionSingleToMulti3D( pScreen ); } static void DRITransitionToPrivateBuffers(ScreenPtr pScreen) { + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionMultiToSingle3D) + pDRIInfo->TransitionMultiToSingle3D( pScreen ); } Index: programs/Xserver/GL/dri/dri.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/GL/dri/dri.h,v retrieving revision 1.18 diff -u -r1.18 dri.h --- programs/Xserver/GL/dri/dri.h 9 Apr 2001 21:56:18 -0000 1.18 +++ programs/Xserver/GL/dri/dri.h 21 May 2002 11:40:50 -0000 @@ -121,6 +121,9 @@ CARD32 indx); void (*TransitionTo3d)(ScreenPtr pScreen); void (*TransitionTo2d)(ScreenPtr pScreen); + void (*TransitionSingleToMulti3D)(ScreenPtr pScreen); + void (*TransitionMultiToSingle3D)(ScreenPtr pScreen); + void (*SetDrawableIndex)(WindowPtr pWin, CARD32 indx); Bool (*OpenFullScreen)(ScreenPtr pScreen); Bool (*CloseFullScreen)(ScreenPtr pScreen); Index: programs/Xserver/hw/xfree86/drivers/ati/Imakefile =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/Imakefile,v retrieving revision 1.7 diff -u -r1.7 Imakefile --- programs/Xserver/hw/xfree86/drivers/ati/Imakefile 27 Jan 2002 20:05:30 -0000 1.7 +++ programs/Xserver/hw/xfree86/drivers/ati/Imakefile 21 May 2002 11:40:50 -0000 @@ -185,6 +185,7 @@ -I$(XF86SRC)/vgahw -I$(XF86SRC)/fbdevhw \ -I$(SERVERSRC)/cfb -I$(SERVERSRC)/mfb \ -I$(SERVERSRC)/fb -I$(SERVERSRC)/mi \ + -I$(SERVERSRC)/miext/shadow \ -I$(SERVERSRC)/render -I$(SERVERSRC)/Xext -I$(SERVERSRC)/include \ $(DRIINCLUDES) -I$(FONTINCSRC) -I$(EXTINCSRC) -I$(XINCLUDESRC) #endif Index: programs/Xserver/hw/xfree86/drivers/ati/radeon.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v retrieving revision 1.19.2.1 diff -u -r1.19.2.1 radeon.h --- programs/Xserver/hw/xfree86/drivers/ati/radeon.h 25 Mar 2002 10:35:48 -0000 1.19.2.1 +++ programs/Xserver/hw/xfree86/drivers/ati/radeon.h 21 May 2002 11:40:51 -0000 @@ -368,6 +368,9 @@ unsigned char *PCI; /* Map */ Bool depthMoves; /* Enable depth moves -- slow! */ + + Bool allowPageFlip; /* Enable 3d page flipping */ + int drmMinor; drmSize agpSize; drmHandle agpMemHandle; /* Handle from drmAgpAlloc */ Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v retrieving revision 1.21.2.3 diff -u -r1.21.2.3 radeon_dri.c --- programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c 25 Mar 2002 10:35:48 -0000 1.21.2.3 +++ programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c 21 May 2002 11:40:51 +-0000 @@ -46,6 +46,8 @@ #include "xf86.h" #include "windowstr.h" + +#include "shadow.h" /* GLX/DRI/DRM definitions */ #define _XF86DRI_SERVER_ #include "GL/glxtokens.h" @@ -68,6 +70,16 @@ # define DRM_PAGE_SIZE 4096 #endif + +static Bool RADEONDRICloseFullScreen(ScreenPtr pScreen); +static Bool RADEONDRIOpenFullScreen(ScreenPtr pScreen); +static void RADEONDRITransitionTo2d(ScreenPtr pScreen); +static void RADEONDRITransitionTo3d(ScreenPtr pScreen); +static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen); +static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen); + +static void RADEONDRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf); + /* Initialize the visual configs that are supported by the hardware. These are combined with the visual configs that the indirect rendering core supports, and the intersection is exported to the @@ -663,6 +675,9 @@ info->accel->NeedToSync = TRUE; } + + + /* Initialize the AGP state. Request memory for use in AGP space, and initialize the Radeon registers to point to that memory. */ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) @@ -1301,6 +1316,12 @@ pDRIInfo->InitBuffers = RADEONDRIInitBuffers; pDRIInfo->MoveBuffers = RADEONDRIMoveBuffers; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; + pDRIInfo->OpenFullScreen = RADEONDRIOpenFullScreen; + pDRIInfo->CloseFullScreen = RADEONDRICloseFullScreen; + pDRIInfo->TransitionTo2d = RADEONDRITransitionTo2d; + pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d; + pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d; + pDRIInfo->TransitionMultiToSingle3D = RADEONDRITransitionMultiToSingle3d; pDRIInfo->createDummyCtx = TRUE; pDRIInfo->createDummyCtxPriv = FALSE; @@ -1331,6 +1352,15 @@ RADEONDRICloseScreen(pScreen); return FALSE; } + if (version->version_minor < 3) { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[dri] Some DRI features disabled because of version mismatch.\n" + "[dri] radeon.o kernel module version is %d.%d.%d but 1.1.3 is +preferred.\n", + version->version_major, + version->version_minor, + version->version_patchlevel); + info->drmMinor = version->version_minor; + } drmFreeVersion(version); } @@ -1460,6 +1490,16 @@ pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec); + + /* Have shadow run only while there is 3d active. + */ + if (info->allowPageFlip /* && info->drmMinor >= 3 */) { + shadowSetup (pScreen); + shadowAdd( pScreen, 0, RADEONDRIShadowUpdate, 0, 0, 0 ); + } + else + info->allowPageFlip = 0; + return TRUE; } @@ -1533,3 +1573,158 @@ info->pVisualConfigsPriv = NULL; } } + + + +/* Fullscreen hooks. The DRI fullscreen mode can probably be removed + * as it adds little or nothing above the mechanism below. (and isn't + * widely used) + */ +static Bool +RADEONDRIOpenFullScreen(ScreenPtr pScreen) +{ + return TRUE; +} + +static Bool +RADEONDRICloseFullScreen(ScreenPtr pScreen) +{ + return TRUE; +} + + + +/* Use callbacks from dri.c to support pageflipping mode for a single + * 3d context without need for any specific full-screen extension. + * + * Also see tdfx driver for example of using these callbacks to + * allocate and free 3d-specific memory on demand. + */ + + +/* Use the miext/shadow module to maintain a list of dirty rectangles. + * These are blitted to the back buffer to keep both buffers clean + * during page-flipping when the 3d application isn't fullscreen. + * + * Unlike most use of the shadow code, both buffers are in video + * memory. + * + * An alternative to this would be to organize for all on-screen + * drawing operations to be duplicated for the two buffers. That + * might be faster, but seems like a lot more work... + */ + + +/* This should be done *before* XAA syncs or fires its buffer. + * Otherwise will have to fire it again??? + */ +static void +RADEONDRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + RegionPtr damage = &pBuf->damage; + int i, num = REGION_NUM_RECTS(damage); + BoxPtr pbox = REGION_RECTS(damage); + RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + /* Don't want to do this when no 3d is active and pages are + * right-way-round : + */ + if (!info->allowPageFlip) + return; + + (*info->accel->SetupForScreenToScreenCopy)(pScrn, + 1, 1, GXcopy, + (CARD32)(-1), -1); + + for (i = 0 ; i < num ; i++, pbox++) { + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, + pbox->x1, + pbox->y1, + pbox->x1 + info->backX, + pbox->y1 + info->backY, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + + } +} + + +static void +RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen) +{ + /* Tell the clients not to pageflip. How? + * -- Field in sarea, plus bumping the window counters. + * -- DRM needs to cope with Front-to-Back swapbuffers. + */ + RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + pSAREAPriv->pfAllowPageFlip = 0; +} + +static void +RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen) +{ + /* Let the remaining 3d app start page flipping again. + */ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + if (info->allowPageFlip) + pSAREAPriv->pfAllowPageFlip = 1; +} + + +static void +RADEONDRITransitionTo3d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + if (info->allowPageFlip && !pSAREAPriv->pfAllowPageFlip) { + /* Duplicate the frontbuffer to the backbuffer: + */ + (*info->accel->SetupForScreenToScreenCopy)(pScrn, + 1, 1, GXcopy, + (CARD32)(-1), -1); + + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, + 0, + 0, + info->backX, + info->backY, + pScrn->virtualX, + pScrn->virtualY); + + pSAREAPriv->pfAllowPageFlip = 1; + } +} + + +static void +RADEONDRITransitionTo2d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + /* Go back to the front buffer if things were left in a flipped state. + */ + if (pSAREAPriv->pfCurrentPage != 0) { + drmRadeonFlipBuffers( info->drmFD ); + } + + /* Shut down shadowing if we've made it back to the front page: + */ + if (pSAREAPriv->pfCurrentPage == 0) { + pSAREAPriv->pfAllowPageFlip = 0; + } + else + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] RADEONDRITransitionTo2d failed to unflip buffers.\n"); + +} + + Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v retrieving revision 1.19 diff -u -r1.19 radeon_driver.c --- programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 27 Jan 2002 20:05:31 -0000 1.19 +++ programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 21 May 2002 11:40:52 +-0000 @@ -52,7 +52,7 @@ * This server does not yet support these XFree86 4.0 features: * !!!! FIXME !!!! * DDC1 & DDC2 - * shadowfb + * shadowfb (Note: dri uses shadow for another purpose in radeon_dri_shadow.c) * overlay planes * * Modified by Marc Aurele La France ([EMAIL PROTECTED]) for ATI driver merge. @@ -130,6 +130,7 @@ OPTION_RING_SIZE, OPTION_BUFFER_SIZE, OPTION_DEPTH_MOVE, + OPTION_NO_PAGE_FLIP, #endif OPTION_CRT_SCREEN, OPTION_PANEL_SIZE, @@ -150,6 +151,7 @@ { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_DEPTH_MOVE, "EnableDepthMoves", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NO_PAGE_FLIP, "DisablePageFlip", OPTV_BOOLEAN, {0}, FALSE }, #endif { OPTION_CRT_SCREEN, "CrtScreen", OPTV_BOOLEAN, {0}, FALSE}, { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, @@ -293,6 +295,11 @@ "GlxSetVisualConfigs", NULL }; + +static const char *driShadowSymbols[] = { + "shadowInit", + NULL +}; #endif static const char *vbeSymbols[] = { @@ -1980,6 +1987,22 @@ "Depth moves disabled by default\n"); } + if ((info->allowPageFlip = !xf86ReturnOptValBool(info->Options, + OPTION_NO_PAGE_FLIP, + FALSE))) { + if (!xf86LoadSubModule(pScrn, "shadow")) { + info->allowPageFlip = 0; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling page flipping\n"); + } + else { + xf86LoaderReqSymLists(driShadowSymbols, NULL); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping enabled\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Disabling page flipping\n"); + } + + return TRUE; } #endif @@ -2637,7 +2660,7 @@ * pixmap cache. Should be enough for a fullscreen background * image plus some leftovers. */ - info->textureSize = info->FbMapSize - 6 * bufferSize; + info->textureSize = info->FbMapSize - 4 * bufferSize; /* If that gives us less than half the available memory, let's * be greedy and grab some more. Sorry, I care more about 3D @@ -2700,6 +2723,9 @@ scanlines = info->backOffset / width_bytes - 1; if (scanlines > 8191) scanlines = 8191; + + info->backY = scanlines; + info->backX = (info->backOffset - (scanlines * width_bytes - 1)) / cpp; MemBox.x1 = 0; MemBox.y1 = 0; Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h,v retrieving revision 1.5.2.1 diff -u -r1.5.2.1 radeon_sarea.h --- programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h 12 Mar 2002 12:11:59 -0000 1.5.2.1 +++ programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h 21 May 2002 11:40:55 +-0000 @@ -236,6 +236,8 @@ int texAge[RADEON_NR_TEX_HEAPS]; int ctxOwner; /* last context to upload state */ + int pfAllowPageFlip; /* set by the 2d driver, read by the client */ + int pfCurrentPage; /* set by kernel, read by others */ } RADEONSAREAPriv, *RADEONSAREAPrivPtr; #endif Index: programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/Attic/xf86drmRadeon.h,v retrieving revision 1.10.2.3 diff -u -r1.10.2.3 xf86drmRadeon.h --- programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h 25 Mar 2002 10:30:41 -0000 1.10.2.3 +++ programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h 21 May 2002 11:40:56 +-0000 @@ -227,6 +227,8 @@ extern int drmRadeonFullScreen( int fd, int enable ); extern int drmRadeonSwapBuffers( int fd ); +extern int drmRadeonFlipBuffers( int fd ); + extern int drmRadeonClear( int fd, unsigned int flags, unsigned int clear_color, unsigned int clear_depth, unsigned int color_mask, unsigned int stencil, Index: programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/Attic/xf86drmRadeon.c,v retrieving revision 1.11.2.2 diff -u -r1.11.2.2 xf86drmRadeon.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c 25 Mar 2002 10:30:41 -0000 1.11.2.2 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c 21 May 2002 +11:40:56 -0000 @@ -237,6 +237,15 @@ } } +int drmRadeonFlipBuffers( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_RADEON_FLIP, NULL ) ) { + return -errno; + } else { + return 0; + } +} + int drmRadeonClear( int fd, unsigned int flags, unsigned int clear_color, unsigned int clear_depth, unsigned int color_mask, unsigned int stencil, Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h,v retrieving revision 1.35.2.2 diff -u -r1.35.2.2 drm.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h 25 Mar 2002 10:29:12 -0000 1.35.2.2 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h 21 May 2002 +11:40:56 -0000 @@ -492,6 +492,7 @@ #define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) #define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) +#define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52) /* Gamma specific ioctls */ #define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t) Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c,v retrieving revision 1.20.2.5 diff -u -r1.20.2.5 radeon_cp.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c 3 May 2002 20:51:04 -0000 1.20.2.5 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c 21 May 2002 +11:40:59 -0000 @@ -1144,60 +1144,12 @@ * Fullscreen mode */ -static int radeon_do_init_pageflip( drm_device_t *dev ) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - dev_priv->crtc_offset = RADEON_READ( RADEON_CRTC_OFFSET ); - dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); - - RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset ); - RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, - dev_priv->crtc_offset_cntl | - RADEON_CRTC_OFFSET_FLIP_CNTL ); - - dev_priv->page_flipping = 1; - dev_priv->current_page = 0; - - return 0; -} - -int radeon_do_cleanup_pageflip( drm_device_t *dev ) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->crtc_offset ); - RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); - - dev_priv->page_flipping = 0; - dev_priv->current_page = 0; - - return 0; -} - +/* KW: Deprecated to say the least: + */ int radeon_fullscreen( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_radeon_fullscreen_t fs; - - LOCK_TEST_WITH_RETURN( dev ); - - if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg, - sizeof(fs) ) ) - return -EFAULT; - - switch ( fs.func ) { - case RADEON_INIT_FULLSCREEN: - return radeon_do_init_pageflip( dev ); - case RADEON_CLEANUP_FULLSCREEN: - return radeon_do_cleanup_pageflip( dev ); - } - - return -EINVAL; + return 0; } Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h,v retrieving revision 1.9.2.4 diff -u -r1.9.2.4 radeon_drm.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h 25 Mar 2002 10:29:12 -0000 1.9.2.4 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h 21 May +2002 11:41:01 -0000 @@ -291,6 +291,8 @@ drm_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1]; int tex_age[RADEON_NR_TEX_HEAPS]; int ctx_owner; + int pfState; /* number of 3d windows (0,1,2ormore) */ + int pfCurrentPage; /* which buffer is being displayed? */ } drm_radeon_sarea_t; Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c,v retrieving revision 1.13.2.4 diff -u -r1.13.2.4 radeon_drv.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c 8 Apr 2002 16:12:20 -0000 1.13.2.4 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c 21 May +2002 11:41:01 -0000 @@ -51,6 +51,8 @@ * - Increase MAX_TEXTURE_LEVELS (brian) * 1.3 - Add cmdbuf ioctl (keith) * - Add support for new radeon packets (keith) + * - Add getparam ioctl (keith) + * - Add flip-buffers ioctl, deprecate fullscreen foo (keith). */ #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ @@ -70,7 +72,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 }, #include "drm_agpsupport.h" Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h,v retrieving revision 1.13.2.4 diff -u -r1.13.2.4 radeon_drv.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h 25 Mar 2002 10:29:12 -0000 1.13.2.4 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h 21 May +2002 11:41:01 -0000 @@ -171,6 +171,8 @@ unsigned int cmd, unsigned long arg ); extern int radeon_cp_getparam( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int radeon_cp_flip( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c,v retrieving revision 1.12.2.8 diff -u -r1.12.2.8 radeon_state.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c 25 Mar 2002 10:29:12 -0000 1.12.2.8 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c 21 May +2002 11:41:01 -0000 @@ -51,7 +51,8 @@ OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) ); OUT_RING( (box->y1 << 16) | box->x1 ); OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) ); - OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) ); +/* OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );*/ + OUT_RING( (box->y2 << 16) | box->x2 ); ADVANCE_RING(); } @@ -543,9 +544,17 @@ RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS ); - - OUT_RING( dev_priv->back_pitch_offset ); - OUT_RING( dev_priv->front_pitch_offset ); + + /* Make this work even if front & back are flipped: + */ + if (dev_priv->current_page == 0) { + OUT_RING( dev_priv->back_pitch_offset ); + OUT_RING( dev_priv->front_pitch_offset ); + } + else { + OUT_RING( dev_priv->front_pitch_offset ); + OUT_RING( dev_priv->back_pitch_offset ); + } OUT_RING( (x << 16) | y ); OUT_RING( (x << 16) | y ); @@ -580,11 +589,12 @@ radeon_cp_performance_boxes( dev_priv ); #endif - BEGIN_RING( 6 ); + BEGIN_RING( 4 ); RADEON_WAIT_UNTIL_3D_IDLE(); +/* RADEON_WAIT_UNTIL_PAGE_FLIPPED(); - +*/ OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) ); if ( dev_priv->current_page == 0 ) { @@ -602,6 +612,7 @@ * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; BEGIN_RING( 2 ); @@ -1045,25 +1056,71 @@ sarea_priv->nbox * sizeof(depth_boxes[0]) ) ) return -EFAULT; - /* Needed for depth clears via triangles??? - */ - if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeon_emit_state( dev_priv, - &sarea_priv->context_state, - sarea_priv->tex_state, - sarea_priv->dirty ); - - sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | - RADEON_UPLOAD_TEX1IMAGES | - RADEON_UPLOAD_TEX2IMAGES | - RADEON_REQUIRE_QUIESCENCE); - } - radeon_cp_dispatch_clear( dev, &clear, depth_boxes ); return 0; } + + +/* Not sure why this isn't set all the time: + */ +static int radeon_do_init_pageflip( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + dev_priv->crtc_offset = RADEON_READ( RADEON_CRTC_OFFSET ); + dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); + + RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset ); + RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, + dev_priv->crtc_offset_cntl | + RADEON_CRTC_OFFSET_FLIP_CNTL ); + + dev_priv->page_flipping = 1; + dev_priv->current_page = 0; + + return 0; +} + +int radeon_do_cleanup_pageflip( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->crtc_offset ); + RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); + + dev_priv->page_flipping = 0; + dev_priv->current_page = 0; + + return 0; +} + +/* Swapping and flipping are different operations, need different ioctls. + * They can & should be intermixed to support multiple 3d windows. + */ +int radeon_cp_flip( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + LOCK_TEST_WITH_RETURN( dev ); + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + + if (!dev_priv->page_flipping) + radeon_do_init_pageflip( dev ); + + radeon_cp_dispatch_flip( dev ); + + return 0; +} + int radeon_cp_swap( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { @@ -1080,12 +1137,8 @@ if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - if ( !dev_priv->page_flipping ) { - radeon_cp_dispatch_swap( dev ); - dev_priv->sarea_priv->ctx_owner = 0; - } else { - radeon_cp_dispatch_flip( dev ); - } + radeon_cp_dispatch_swap( dev ); + dev_priv->sarea_priv->ctx_owner = 0; return 0; }