Index: xc/lib/GL/mesa/src/drv/r128/r128_context.h =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r128/r128_context.h,v retrieving revision 1.33 diff -u -r1.33 r128_context.h --- xc/lib/GL/mesa/src/drv/r128/r128_context.h 25 Mar 2003 12:48:16 -0000 1.33 +++ xc/lib/GL/mesa/src/drv/r128/r128_context.h 6 Apr 2003 22:07:31 -0000 @@ -177,7 +177,6 @@ /* Page flipping */ GLuint doPageFlip; - GLuint currentPage; /* Drawable, cliprect and scissor information */ Index: xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c,v retrieving revision 1.23 diff -u -r1.23 r128_ioctl.c --- xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c 25 Mar 2003 12:48:17 -0000 1.23 +++ xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c 6 Apr 2003 22:07:31 -0000 @@ -333,8 +333,8 @@ rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate; if ( R128_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "\n%s( %p ): page=%d\n\n", - __FUNCTION__, rmesa->glCtx, rmesa->currentPage ); + fprintf(stderr, "%s %d\n", __FUNCTION__, + rmesa->sarea->pfCurrentPage ); } FLUSH_BATCH( rmesa ); @@ -355,23 +355,21 @@ /* The kernel will have been initialized to perform page flipping * on a swapbuffers ioctl. */ - ret = drmCommandNone( rmesa->driFd, DRM_R128_SWAP ); + ret = drmCommandNone( rmesa->driFd, DRM_R128_FLIP ); UNLOCK_HARDWARE( rmesa ); if ( ret ) { - fprintf( stderr, "DRM_R128_SWAP: return = %d\n", ret ); + fprintf( stderr, "DRM_R128_FLIP: return = %d\n", ret ); exit( 1 ); } - if ( rmesa->currentPage == 0 ) { + if ( rmesa->sarea->pfCurrentPage == 1 ) { rmesa->drawOffset = rmesa->r128Screen->frontOffset; rmesa->drawPitch = rmesa->r128Screen->frontPitch; - rmesa->currentPage = 1; } else { rmesa->drawOffset = rmesa->r128Screen->backOffset; rmesa->drawPitch = rmesa->r128Screen->backPitch; - rmesa->currentPage = 0; } rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) | Index: xc/lib/GL/mesa/src/drv/r128/r128_lock.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r128/r128_lock.c,v retrieving revision 1.13 diff -u -r1.13 r128_lock.c --- xc/lib/GL/mesa/src/drv/r128/r128_lock.c 25 Mar 2003 12:48:18 -0000 1.13 +++ xc/lib/GL/mesa/src/drv/r128/r128_lock.c 6 Apr 2003 22:07:31 -0000 @@ -35,6 +35,7 @@ #include "r128_context.h" #include "r128_lock.h" #include "r128_tex.h" +#include "r128_state.h" #if DEBUG_LOCKING char *prevLockFile = NULL; @@ -42,6 +43,36 @@ #endif +/* Turn on/off page flipping according to the flags in the sarea: + */ +static void +r128UpdatePageFlipping( r128ContextPtr rmesa ) +{ + int use_back; + + rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip; + + use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT); + use_back ^= (rmesa->sarea->pfCurrentPage == 1); + + if ( R128_DEBUG & DEBUG_VERBOSE_API ) + fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__, + rmesa->doPageFlip, + rmesa->sarea->pfCurrentPage ); + + if ( use_back ) { + rmesa->drawOffset = rmesa->r128Screen->backOffset; + rmesa->drawPitch = rmesa->r128Screen->backPitch; + } else { + rmesa->drawOffset = rmesa->r128Screen->frontOffset; + rmesa->drawPitch = rmesa->r128Screen->frontPitch; + } + + rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) | + (rmesa->drawOffset >> 5)); + rmesa->new_state |= R128_NEW_WINDOW; +} + /* Update the hardware state. This is called if another context has * grabbed the hardware lock, which includes the X server. This * function also updates the driver's window state after the X server @@ -70,8 +101,9 @@ DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv ); if ( rmesa->lastStamp != dPriv->lastStamp ) { + r128UpdatePageFlipping( rmesa ); rmesa->lastStamp = dPriv->lastStamp; - rmesa->new_state |= R128_NEW_WINDOW | R128_NEW_CLIP; + rmesa->new_state |= R128_NEW_CLIP; rmesa->SetupNewInputs = ~0; } Index: xc/lib/GL/mesa/src/drv/r128/r128_screen.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r128/r128_screen.c,v retrieving revision 1.22 diff -u -r1.22 r128_screen.c --- xc/lib/GL/mesa/src/drv/r128/r128_screen.c 25 Mar 2003 12:48:18 -0000 1.22 +++ xc/lib/GL/mesa/src/drv/r128/r128_screen.c 6 Apr 2003 22:07:31 -0000 @@ -197,61 +197,16 @@ } -/* 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 -r128OpenFullScreen( __DRIcontextPrivate *driContextPriv ) +r128OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv ) { -#if 0 - r128ContextPtr rmesa = (r128ContextPtr)driContextPriv->driverPrivate; - drmR128Fullscreen fullscreen; - GLint ret; - - /* FIXME: Do we need to check this? - */ - if ( !r128Ctx->glCtx->Visual.doubleBufferMode ) - return GL_TRUE; - - LOCK_HARDWARE( rmesa ); - r128WaitForIdleLocked( rmesa ); - - /* Ignore errors. If this fails, we simply don't do page flipping. - */ - fullscreen.func = DRM_R128_INIT_FULLSCREEN; - ret = drmCommandWrite( rmesa->driFd, DRM_R128_FULLSCREEN, - &fullscreen, sizeof(drmR128Fullscreen) ); - - UNLOCK_HARDWARE( rmesa ); - - rmesa->doPageFlip = ( ret == 0 ); -#endif - - return GL_TRUE; -} - -/* Shut down the fullscreen mode. - */ -static GLboolean -r128CloseFullScreen( __DRIcontextPrivate *driContextPriv ) -{ -#if 0 - r128ContextPtr rmesa = (r128ContextPtr)driContextPriv->driverPrivate; - drmR128Fullscreen fullscreen; - LOCK_HARDWARE( rmesa ); - r128WaitForIdleLocked( rmesa ); - - /* Don't care if this fails, we're not page flipping anymore. - */ - fullscreen.func = DRM_R128_CLEANUP_FULLSCREEN; - drmCommandWrite( rmesa->driFd, DRM_R128_FULLSCREEN, - &fullscreen, sizeof(drmR128Fullscreen) ); - - UNLOCK_HARDWARE( rmesa ); - - rmesa->doPageFlip = GL_FALSE; - rmesa->currentPage = 0; -#endif - return GL_TRUE; } @@ -368,8 +323,8 @@ r128SwapBuffers, r128MakeCurrent, r128UnbindContext, - r128OpenFullScreen, - r128CloseFullScreen + r128OpenCloseFullScreen, + r128OpenCloseFullScreen }; Index: xc/lib/GL/mesa/src/drv/r128/r128_span.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r128/r128_span.c,v retrieving revision 1.21 diff -u -r1.21 r128_span.c --- xc/lib/GL/mesa/src/drv/r128/r128_span.c 25 Mar 2003 12:48:18 -0000 1.21 +++ xc/lib/GL/mesa/src/drv/r128/r128_span.c 6 Apr 2003 22:07:31 -0000 @@ -391,12 +391,22 @@ switch ( bufferBit ) { case FRONT_LEFT_BIT: - rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset; - rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch; + if ( rmesa->sarea->pfCurrentPage == 1 ) { + rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset; + rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch; + } else { + rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset; + rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch; + } break; case BACK_LEFT_BIT: - rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset; - rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch; + if ( rmesa->sarea->pfCurrentPage == 1 ) { + rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset; + rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch; + } else { + rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset; + rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch; + } break; default: break; Index: xc/lib/GL/mesa/src/drv/r128/r128_state.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r128/r128_state.c,v retrieving revision 1.28 diff -u -r1.28 r128_state.c --- xc/lib/GL/mesa/src/drv/r128/r128_state.c 25 Mar 2003 13:59:49 -0000 1.28 +++ xc/lib/GL/mesa/src/drv/r128/r128_state.c 6 Apr 2003 22:07:31 -0000 @@ -1082,7 +1082,7 @@ rmesa->Fallback = 0; - if ( rmesa->glCtx->Visual.doubleBufferMode ) { + if ( rmesa->glCtx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) { rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset; rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch; } else { Index: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v retrieving revision 1.22 diff -u -r1.22 r128.h --- xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h 25 Mar 2003 11:19:45 -0000 1.22 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h 6 Apr 2003 22:07:36 -0000 @@ -304,6 +304,10 @@ drmHandle pciMemHandle; unsigned char *PCI; /* Map */ + Bool allowPageFlip; /* Enable 3d page flipping */ + Bool have3DWindows; /* Are there any 3d clients? */ + int drmMinor; + drmSize agpSize; drmHandle agpMemHandle; /* Handle from drmAgpAlloc */ unsigned long agpOffset; Index: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_common.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_common.h,v retrieving revision 1.4 diff -u -r1.4 r128_common.h --- xc/programs/Xserver/hw/xfree86/drivers/ati/r128_common.h 31 Oct 2002 00:49:54 -0000 1.4 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128_common.h 6 Apr 2003 22:07:36 -0000 @@ -67,6 +67,7 @@ #define DRM_R128_FULLSCREEN 0x10 #define DRM_R128_CLEAR2 0x11 #define DRM_R128_GETPARAM 0x12 +#define DRM_R128_FLIP 0x13 #define DRM_R128_FRONT_BUFFER 0x1 #define DRM_R128_BACK_BUFFER 0x2 Index: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v retrieving revision 1.34 diff -u -r1.34 r128_dri.c --- xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c 25 Mar 2003 11:19:45 -0000 1.34 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c 6 Apr 2003 22:07:36 -0000 @@ -49,6 +49,7 @@ #include "windowstr.h" #include "xf86PciInfo.h" +#include "shadowfb.h" /* GLX/DRI/DRM definitions */ #define _XF86DRI_SERVER_ #include "GL/glxtokens.h" @@ -64,6 +65,13 @@ # define DRM_PAGE_SIZE 4096 #endif +static void R128DRITransitionTo2d(ScreenPtr pScreen); +static void R128DRITransitionTo3d(ScreenPtr pScreen); +static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen); +static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen); + +static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); + /* 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 @@ -355,7 +363,11 @@ int nbox, nboxSave; int depth; - /* FIXME: Use accel when CCE 2D code is written */ + /* FIXME: Use accel when CCE 2D code is written + * EA: What is this code kept for? Radeon doesn't have it and + * has a comment: "There's no need for the 2d driver to be clearing + * buffers for the 3d client. It knows how to do that on its own." + */ if (info->directRenderingEnabled) return; @@ -1063,6 +1075,10 @@ pDRIInfo->InitBuffers = R128DRIInitBuffers; pDRIInfo->MoveBuffers = R128DRIMoveBuffers; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; + pDRIInfo->TransitionTo2d = R128DRITransitionTo2d; + pDRIInfo->TransitionTo3d = R128DRITransitionTo3d; + pDRIInfo->TransitionSingleToMulti3D = R128DRITransitionSingleToMulti3d; + pDRIInfo->TransitionMultiToSingle3D = R128DRITransitionMultiToSingle3d; pDRIInfo->createDummyCtx = TRUE; pDRIInfo->createDummyCtxPriv = FALSE; @@ -1130,6 +1146,7 @@ R128DRICloseScreen(pScreen); return FALSE; } + info->drmMinor = version->version_minor; drmFreeVersion(version); } @@ -1253,6 +1270,13 @@ pR128DRI->agpTexOffset = info->agpTexStart; pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); + /* Have shadowfb run only while there is 3d active. */ + if (info->allowPageFlip && info->drmMinor >= 4 ) { + ShadowFBInit( pScreen, R128DRIRefreshArea ); + } else { + info->allowPageFlip = 0; + } + return TRUE; } @@ -1334,4 +1358,130 @@ xfree(info->pVisualConfigsPriv); info->pVisualConfigsPriv = NULL; } +} + +/* Use callbacks from dri.c to support pageflipping mode for a single + * 3d context without need for any specific full-screen extension. + */ + +/* Use the shadowfb 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 shadowfb 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... + */ + + +static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + R128InfoPtr info = R128PTR(pScrn); + int i; + R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + + /* Don't want to do this when no 3d is active and pages are + * right-way-round + */ + if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) + return; + + (*info->accel->SetupForScreenToScreenCopy)(pScrn, + 1, 1, GXcopy, + (CARD32)(-1), -1); + + for (i = 0 ; i < num ; i++, pbox++) { + int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1); + int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1); + + if (xa <= xb && ya <= yb) { + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, + xa + info->backX, + ya + info->backY, + xb - xa + 1, + yb - ya + 1); + } + } +} + +static void R128EnablePageFlip(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + if (info->allowPageFlip) { + /* 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 R128DisablePageFlip(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. + */ + R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + pSAREAPriv->pfAllowPageFlip = 0; +} + +static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen) +{ + R128DisablePageFlip(pScreen); +} + +static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen) +{ + /* Let the remaining 3d app start page flipping again */ + R128EnablePageFlip(pScreen); +} + +static void R128DRITransitionTo3d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + R128EnablePageFlip(pScreen); + + info->have3DWindows = 1; + + if (info->cursor_start) + xf86ForceHWCursor(pScreen, TRUE); +} + +static void R128DRITransitionTo2d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + /* Shut down shadowing if we've made it back to the front page */ + if (pSAREAPriv->pfCurrentPage == 0) { + R128DisablePageFlip(pScreen); + } else { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[dri] R128DRITransitionTo2d: " + "kernel failed to unflip buffers.\n"); + } + + info->have3DWindows = 0; + + if (info->cursor_start) + xf86ForceHWCursor(pScreen, FALSE); } Index: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c,v retrieving revision 1.31 diff -u -r1.31 r128_driver.c --- xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c 25 Mar 2003 11:19:46 -0000 1.31 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c 6 Apr 2003 22:07:39 -0000 @@ -135,6 +135,7 @@ OPTION_AGP_SIZE, OPTION_RING_SIZE, OPTION_BUFFER_SIZE, + OPTION_PAGE_FLIP, #endif #if USE_CRT_ONLY /* FIXME: Disable CRTOnly until it is tested */ @@ -164,6 +165,7 @@ { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE }, #endif { OPTION_DISPLAY, "Display", OPTV_STRING, {0}, FALSE }, { OPTION_PANEL_WIDTH, "PanelWidth", OPTV_INTEGER, {0}, FALSE }, @@ -318,6 +320,11 @@ "GlxSetVisualConfigs", NULL }; + +static const char *driShadowFBSymbols[] = { + "ShadowFBInit", + NULL +}; #endif static const char *vbeSymbols[] = { @@ -351,6 +358,7 @@ #ifdef XF86DRI drmSymbols, driSymbols, + driShadowFBSymbols, #endif fbdevHWSymbols, int10Symbols, @@ -1848,6 +1856,21 @@ /* This option checked by the R128 DRM kernel module */ } + if (!xf86LoadSubModule(pScrn, "shadowfb")) { + info->allowPageFlip = 0; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't load shadowfb module:\n"); + } else { + xf86LoaderReqSymLists(driShadowFBSymbols, NULL); + + info->allowPageFlip = xf86ReturnOptValBool(info->Options, + OPTION_PAGE_FLIP, + FALSE); + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n", + info->allowPageFlip ? "en" : "dis"); + return TRUE; } #endif @@ -2232,6 +2255,8 @@ int bufferSize = pScrn->virtualY * width_bytes; int l, total; int scanlines; + int width, height; + switch (info->CCEMode) { case R128_DEFAULT_CCE_PIO_MODE: @@ -2311,8 +2336,6 @@ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); return FALSE; } else { - int width, height; - xf86DrvMsg(scrnIndex, X_INFO, "Memory manager initialized to (%d,%d) (%d,%d)\n", MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); @@ -2326,12 +2349,6 @@ } else { xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); } - if (xf86QueryLargestOffscreenArea(pScreen, &width, - &height, 0, 0, 0)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Largest offscreen area available: %d x %d\n", - width, height); - } } /* Allocate the shared back buffer */ @@ -2384,6 +2401,13 @@ info->depthOffset = -1; info->depthPitch = -1; info->spanOffset = -1; + } + + if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, + 0, 0, 0)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); } xf86DrvMsg(scrnIndex, X_INFO, Index: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h,v retrieving revision 1.11 diff -u -r1.11 r128_sarea.h --- xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h 22 Oct 2002 23:38:39 -0000 1.11 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h 6 Apr 2003 22:07:39 -0000 @@ -196,6 +196,8 @@ int texAge[R128_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 */ } R128SAREAPriv, *R128SAREAPrivPtr; #endif Index: xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128.h,v retrieving revision 1.4 diff -u -r1.4 r128.h --- xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128.h 23 Nov 2002 11:58:33 -0000 1.4 +++ xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128.h 6 Apr 2003 22:07:50 -0000 @@ -50,7 +50,7 @@ #define DRIVER_DATE "20021029" #define DRIVER_MAJOR 2 -#define DRIVER_MINOR 3 +#define DRIVER_MINOR 4 #define DRIVER_PATCHLEVEL 0 @@ -64,6 +64,7 @@ [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_FLIP)] = { r128_cce_flip, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, \ @@ -71,7 +72,7 @@ [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)] = { r128_getparam, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)] = { r128_getparam, 1, 0 }, /* Driver customization: */ Index: xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c,v retrieving revision 1.5 diff -u -r1.5 r128_cce.c --- xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c 28 Mar 2003 14:27:35 -0000 1.5 +++ xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_cce.c 6 Apr 2003 22:07:52 -0000 @@ -766,59 +766,8 @@ return r128_do_engine_reset( dev ); } - -/* ================================================================ - * Fullscreen mode - */ - -static int r128_do_init_pageflip( drm_device_t *dev ) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "\n" ); - - dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET ); - dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL ); - - R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset ); - R128_WRITE( R128_CRTC_OFFSET_CNTL, - dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL ); - - dev_priv->page_flipping = 1; - dev_priv->current_page = 0; - - return 0; -} - -int r128_do_cleanup_pageflip( drm_device_t *dev ) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "\n" ); - - R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); - R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); - - dev_priv->page_flipping = 0; - dev_priv->current_page = 0; - - return 0; -} - int r128_fullscreen( DRM_IOCTL_ARGS ) { - DRM_DEVICE; - drm_r128_fullscreen_t fs; - - LOCK_TEST_WITH_RETURN( dev, filp ); - - DRM_COPY_FROM_USER_IOCTL( fs, (drm_r128_fullscreen_t *)data, sizeof(fs) ); - - switch ( fs.func ) { - case R128_INIT_FULLSCREEN: - return r128_do_init_pageflip( dev ); - case R128_CLEANUP_FULLSCREEN: - return r128_do_cleanup_pageflip( dev ); - } - return DRM_ERR(EINVAL); } Index: xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drm.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drm.h,v retrieving revision 1.3 diff -u -r1.3 r128_drm.h --- xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drm.h 30 Oct 2002 06:10:34 -0000 1.3 +++ xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drm.h 6 Apr 2003 22:07:53 -0000 @@ -164,6 +164,8 @@ drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; int tex_age[R128_NR_TEX_HEAPS]; int ctx_owner; + int pfState; /* number of 3d windows (0,1,2ormore) */ + int pfCurrentPage; /* which buffer is being displayed? */ } drm_r128_sarea_t; @@ -191,6 +193,7 @@ #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) #define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) #define DRM_IOCTL_R128_GETPARAM DRM_IOW( 0x52, drm_r128_getparam_t) +#define DRM_IOCTL_R128_FLIP DRM_IO( 0x53) typedef struct drm_r128_init { enum { Index: xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drv.h =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drv.h,v retrieving revision 1.6 diff -u -r1.6 r128_drv.h --- xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drv.h 28 Mar 2003 14:27:35 -0000 1.6 +++ xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drv.h 6 Apr 2003 22:07:53 -0000 @@ -147,6 +147,7 @@ /* r128_state.c */ extern int r128_cce_clear( DRM_IOCTL_ARGS ); extern int r128_cce_swap( DRM_IOCTL_ARGS ); +extern int r128_cce_flip( DRM_IOCTL_ARGS ); extern int r128_cce_vertex( DRM_IOCTL_ARGS ); extern int r128_cce_indices( DRM_IOCTL_ARGS ); extern int r128_cce_blit( DRM_IOCTL_ARGS ); Index: xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_state.c =================================================================== RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_state.c,v retrieving revision 1.7 diff -u -r1.7 r128_state.c --- xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_state.c 29 Mar 2003 03:30:21 -0000 1.7 +++ xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_state.c 6 Apr 2003 22:08:02 -0000 @@ -499,9 +499,17 @@ R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS ); - - OUT_RING( dev_priv->back_pitch_offset_c ); - OUT_RING( dev_priv->front_pitch_offset_c ); + + /* Make this work even if front & back are flipped: + */ + if (dev_priv->current_page == 0) { + OUT_RING( dev_priv->back_pitch_offset_c ); + OUT_RING( dev_priv->front_pitch_offset_c ); + } + else { + OUT_RING( dev_priv->front_pitch_offset_c ); + OUT_RING( dev_priv->back_pitch_offset_c ); + } OUT_RING( (x << 16) | y ); OUT_RING( (x << 16) | y ); @@ -528,7 +536,10 @@ { drm_r128_private_t *dev_priv = dev->dev_private; RING_LOCALS; - DRM_DEBUG( "page=%d\n", dev_priv->current_page ); + DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", + __FUNCTION__, + dev_priv->current_page, + dev_priv->sarea_priv->pfCurrentPage); #if R128_PERFORMANCE_BOXES /* Do some trivial performance monitoring... @@ -543,10 +554,8 @@ if ( dev_priv->current_page == 0 ) { OUT_RING( dev_priv->back_offset ); - dev_priv->current_page = 1; } else { OUT_RING( dev_priv->front_offset ); - dev_priv->current_page = 0; } ADVANCE_RING(); @@ -556,6 +565,8 @@ * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = + 1 - dev_priv->current_page; BEGIN_RING( 2 ); @@ -1264,6 +1275,62 @@ return 0; } +static int r128_do_init_pageflip( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "\n" ); + + dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET ); + dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL ); + + R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset ); + R128_WRITE( R128_CRTC_OFFSET_CNTL, + dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL ); + + dev_priv->page_flipping = 1; + dev_priv->current_page = 0; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; + + return 0; +} + +int r128_do_cleanup_pageflip( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "\n" ); + + R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); + R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); + + if (dev_priv->current_page != 0) + r128_cce_dispatch_flip( dev ); + + dev_priv->page_flipping = 0; + return 0; +} + +/* Swapping and flipping are different operations, need different ioctls. + * They can & should be intermixed to support multiple 3d windows. + */ + +int r128_cce_flip( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + LOCK_TEST_WITH_RETURN( dev, filp ); + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + + if (!dev_priv->page_flipping) + r128_do_init_pageflip( dev ); + + r128_cce_dispatch_flip( dev ); + + return 0; +} + int r128_cce_swap( DRM_IOCTL_ARGS ) { DRM_DEVICE; @@ -1278,13 +1345,9 @@ if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; - if ( !dev_priv->page_flipping ) { - r128_cce_dispatch_swap( dev ); - dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | - R128_UPLOAD_MASKS); - } else { - r128_cce_dispatch_flip( dev ); - } + r128_cce_dispatch_swap( dev ); + dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | + R128_UPLOAD_MASKS); return 0; }