From 3bd8edb95fcbbb49e97a1a2bdd5c8eae4f83d3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 2 Feb 2007 17:41:18 +0100 Subject: [PATCH] Revive i830 page flipping support. Use the damage layer directly instead of via shadowfb. --- configure.ac | 5 ++ src/i830.h | 7 ++ src/i830_dri.c | 175 ++++++++++++++++++++++------------------------ src/i830_driver.c | 9 +++ src/i830_memory.c | 66 ++++++++++------- 5 files changed, 144 insertions(+), 118 deletions(-) diff --git a/configure.ac b/configure.ac index d45185ae..219fbe6a 100644 --- a/configure.ac +++ b/configure.ac @@ -94,6 +94,8 @@ if test "$DRI" != no; then [have_sarea_h="yes"], [have_sarea_h="no"]) AC_CHECK_FILE([${sdkdir}/dristruct.h], [have_dristruct_h="yes"], [have_dristruct_h="no"]) + AC_CHECK_FILE([${sdkdir}/damage.h], + [have_damage_h="yes"], [have_damage_h="no"]) fi AC_MSG_CHECKING([whether to include DRI support]) @@ -127,6 +129,9 @@ if test "$DRI" = yes; then if test "x$DRI_MM" = xyes; then AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management]) fi + if test "$have_damage_h" = yes; then + AC_DEFINE(DAMAGE,1,[Use Damage extension]) + fi fi AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes) diff --git a/src/i830.h b/src/i830.h index 96972eb5..78381fbf 100644 --- a/src/i830.h +++ b/src/i830.h @@ -68,6 +68,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dri.h" #include "GL/glxint.h" #include "i830_dri.h" +#ifdef DAMAGE +#include "damage.h" +#endif #endif #ifdef I830_USE_EXA @@ -302,6 +305,10 @@ typedef struct _I830Rec { unsigned int front_tiled; unsigned int back_tiled; unsigned int depth_tiled; + +#ifdef DAMAGE + DamagePtr pDamage; +#endif #endif Bool NeedRingBufferLow; diff --git a/src/i830_dri.c b/src/i830_dri.c index 3531bf52..05171d37 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -984,17 +984,6 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) DPRINTF(PFX, "I830DRIFinishScreenInit\n"); - /* Have shadow run only while there is 3d active. - */ -#if 0 - if (pI830->allowPageFlip && pI830->drmMinor >= 1) { - shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0); - } - else -#endif - pI830->allowPageFlip = 0; - - if (!DRIFinishScreenInit(pScreen)) return FALSE; @@ -1025,6 +1014,49 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) } } +#ifdef DAMAGE +/* This should be done *before* XAA syncs, + * Otherwise will have to sync again??? + */ +static void +I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + + /* Don't want to do this when no 3d is active and pages are + * right-way-round : + */ + if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0) + return; + + if (pScrn->bitsPerPixel == 32) { + cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + br13 |= 3 << 24; + } else { + cmd = (XY_SRC_COPY_BLT_CMD); + br13 |= 1 << 24; + } + + for (i = 0 ; i < num ; i++, pbox++) { + BEGIN_LP_RING(8); + OUT_RING(cmd); + OUT_RING(br13); + OUT_RING((pbox->y1 << 16) | pbox->x1); + OUT_RING((pbox->y2 << 16) | pbox->x2); + OUT_RING(pI830->BackBuffer.Start); + OUT_RING((pbox->y1 << 16) | pbox->x1); + OUT_RING(br13 & 0xffff); + OUT_RING(pI830->FrontBuffer.Start); + ADVANCE_LP_RING(); + } + + DamageEmpty(pI830->pDamage); +} +#endif + static void I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, @@ -1045,12 +1077,47 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, return; pI830->LockHeld = 1; I830RefreshRing(pScrn); + +#ifdef DAMAGE + if (!pI830->pDamage && pI830->allowPageFlip) { + PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); + pI830->pDamage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, + pScreen, pPix); + + if (pI830->pDamage == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No screen damage record, page flipping disabled\n"); + pI830->allowPageFlip = 0; + } else { + DamageRegister(&pPix->drawable, pI830->pDamage); + + DamageDamageRegion(&pPix->drawable, + &WindowTable[pScreen->myNum]->winSize); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Damage tracking initialized for page flipping\n"); + } + } +#endif } else if (syncType == DRI_2D_SYNC && oldContextType == DRI_NO_CONTEXT && newContextType == DRI_2D_CONTEXT) { pI830->LockHeld = 0; if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("i830DRISwapContext (out)\n"); + +#ifdef DAMAGE + if (pI830->pDamage) { + RegionPtr pDamageReg = DamageRegion(pI830->pDamage); + + if (pDamageReg) { + int nrects = REGION_NUM_RECTS(pDamageReg); + + if (nrects) + I830DRIRefreshArea(pScrn, nrects, REGION_RECTS(pDamageReg)); + } + } +#endif } else if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("i830DRISwapContext (other)\n"); } @@ -1286,54 +1353,6 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, * might be faster, but seems like a lot more work... */ - -#if 0 -/* This should be done *before* XAA syncs, - * Otherwise will have to sync again??? - */ -static void -I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - RegionPtr damage = &pBuf->damage; - int i, num = REGION_NUM_RECTS(damage); - BoxPtr pbox = REGION_RECTS(damage); - drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); - int cmd, br13; - - /* Don't want to do this when no 3d is active and pages are - * right-way-round : - */ - if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0) - return; - - br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); - - if (pScrn->bitsPerPixel == 32) { - cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - br13 |= 3 << 24; - } else { - cmd = (XY_SRC_COPY_BLT_CMD); - br13 |= 1 << 24; - } - - for (i = 0 ; i < num ; i++, pbox++) { - BEGIN_LP_RING(8); - OUT_RING(cmd); - OUT_RING(br13); - OUT_RING((pbox->y1 << 16) | pbox->x1); - OUT_RING((pbox->y2 << 16) | pbox->x2); - OUT_RING(pI830->BackBuffer.Start); - OUT_RING((pbox->y1 << 16) | pbox->x1); - OUT_RING(br13 & 0xffff); - OUT_RING(pI830->FrontBuffer.Start); - ADVANCE_LP_RING(); - } -} -#endif - static void I830EnablePageFlip(ScreenPtr pScreen) { @@ -1342,32 +1361,7 @@ I830EnablePageFlip(ScreenPtr pScreen) drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); pSAREAPriv->pf_enabled = pI830->allowPageFlip; - pSAREAPriv->pf_active = 0; - - if (pI830->allowPageFlip) { - int br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); - - BEGIN_LP_RING(8); - if (pScrn->bitsPerPixel == 32) { - OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - br13 |= 3 << 24; - } else { - OUT_RING(XY_SRC_COPY_BLT_CMD); - br13 |= 1 << 24; - } - - OUT_RING(br13); - OUT_RING(0); - OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX); - OUT_RING(pI830->BackBuffer.Start); - OUT_RING(0); - OUT_RING(br13 & 0xffff); - OUT_RING(pI830->FrontBuffer.Start); - ADVANCE_LP_RING(); - - pSAREAPriv->pf_active = 1; - } + pSAREAPriv->pf_active = pI830->allowPageFlip; } static void @@ -1419,14 +1413,13 @@ I830DRITransitionTo2d(ScreenPtr pScreen) if (sPriv->pf_current_page == 1) drmCommandNone(pI830->drmSubFD, DRM_I830_FLIP); - /* Shut down shadowing if we've made it back to the front page: - */ - if (sPriv->pf_current_page == 0) { - I830DisablePageFlip(pScreen); - } + if (sPriv->pf_current_page == 1) + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[dri] %s: kernel failed to unflip buffers.\n", __func__); + + I830DisablePageFlip(pScreen); pI830->have3DWindows = 0; - } diff --git a/src/i830_driver.c b/src/i830_driver.c index cb3dd878..d1f83e5a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3168,6 +3168,15 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) pI830->closing = TRUE; #ifdef XF86DRI if (pI830->directRenderingOpen) { +#ifdef DAMAGE + if (pI830->pDamage) { + PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); + + DamageUnregister(&pPix->drawable, pI830->pDamage); + DamageDestroy(pI830->pDamage); + pI830->pDamage = NULL; + } +#endif #ifdef XF86DRI_MM if (pI830->mmModeFlags & I830_KERNEL_MM) { #ifndef XSERVER_LIBDRM_MM diff --git a/src/i830_memory.c b/src/i830_memory.c index 6ceb05b5..29d9d31d 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -515,7 +515,7 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, int verbosity = dryrun ? 4 : 1; const char *s = dryrun ? "[dryrun] " : ""; Bool tileable; - int align, alignflags; + int align; long size, alloced, fb_height; /* Clear everything first. */ @@ -586,16 +586,6 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); - if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } size = lineSize * (fb_height + cacheLines); size = ROUND_TO_PAGE(size); @@ -603,10 +593,26 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, "%sInitial %sframebuffer allocation size: %ld kByte\n", s, secondary ? "secondary " : "", size / 1024); - alloced = I830AllocVidMem(pScrn, FrontBuffer, - StolenPool, size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + + if (tileable) { + align = GetBestTileAlignment(size); + + for (align = GetBestTileAlignment(size); + align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) { + alloced = I830AllocVidMem(pScrn, FrontBuffer, StolenPool, size, align, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | + ALIGN_BOTH_ENDS); + if (alloced >= size) + break; + } + } else { + align = KB(64); + + alloced = I830AllocVidMem(pScrn, FrontBuffer, + StolenPool, size, align, + flags | FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + } + if (alloced < size) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " @@ -718,7 +724,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) int verbosity = dryrun ? 4 : 1; const char *s = dryrun ? "[dryrun] " : ""; Bool tileable; - int align, alignflags, i; + int align, i; DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n", BOOLTOSTRING(flags & ALLOC_INITIAL)); @@ -877,20 +883,26 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->FbMemBox.y2 = maxFb / lineSize; tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); + if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; + align = GetBestTileAlignment(size); + + for (align = GetBestTileAlignment(size); + align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) { + alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), + &(pI830->StolenPool), size, align, + flags | FROM_ANYWHERE | + ALLOCATE_AT_TOP | ALIGN_BOTH_ENDS); + if (alloced >= size) + break; + } } else { - align = KB(64); - alignflags = 0; + alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), + &(pI830->StolenPool), maxFb, align, + flags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); } - alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), - &(pI830->StolenPool), maxFb, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < maxFb) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR,