diff options
author | Michel Dänzer <michel@tungstengraphics.com> | 2007-02-20 19:09:37 +0100 |
---|---|---|
committer | Michel Dänzer <michel@tungstengraphics.com> | 2007-02-20 19:09:37 +0100 |
commit | 0bee64f4bc7581de7ab28ca438581d215e85c610 (patch) | |
tree | 0144ade1edf46ff1b5322f20fa4501919260defa | |
parent | 2212baa8454abb4c7948c3f2e20e337f831d1b86 (diff) |
Add support for triple buffering using a third static buffer.
Need to bump the DRI DDX version minor for the added SAREA fields.
-rw-r--r-- | man/intel.man | 17 | ||||
-rw-r--r-- | src/i830.h | 5 | ||||
-rw-r--r-- | src/i830_accel.c | 3 | ||||
-rw-r--r-- | src/i830_common.h | 6 | ||||
-rw-r--r-- | src/i830_dri.c | 63 | ||||
-rw-r--r-- | src/i830_dri.h | 4 | ||||
-rw-r--r-- | src/i830_driver.c | 14 | ||||
-rw-r--r-- | src/i830_memory.c | 84 | ||||
-rw-r--r-- | src/i830_xaa.c | 2 |
9 files changed, 184 insertions, 14 deletions
diff --git a/man/intel.man b/man/intel.man index 3f4cff89..503b52a7 100644 --- a/man/intel.man +++ b/man/intel.man @@ -162,9 +162,22 @@ Default: 32768. .BI "Option \*qPageFlip\*q \*q" boolean \*q Enable support for page flipping. This should improve 3D performance at the potential cost of worse performance or artifacts with mixed 2D/3D. Also note -that this gives no benefit without corresponding support in the Mesa 3D driver. +that this gives no benefit without corresponding support in the Mesa 3D driver +and may not give the full benefit without triple buffering (see +.B "Option \*qTripleBuffer\*q" +). Default for i810: The option is not used. -Default for i9xx: Disabled. +Default for i830 and above: Disabled. +.TP +.BI "Option \*qTripleBuffer\*q \*q" boolean \*q +Enable support for triple flipping. This should improve 3D performance at the +potential cost of worse performance with mixed 2D/3D. Also note that this gives +no benefit without corresponding support in the Mesa 3D driver and may not give +any benefit without page flipping either (see +.B "Option \*qPageFlip\*q" +). +Default for i810: The option is not used. +Default for i830 and above: Disabled. .TP .BI "Option \*qAccelMethod\*q \*q" string \*q Choose acceleration architecture, either "XAA" or "EXA". XAA is the old @@ -294,6 +294,7 @@ typedef struct _I830Rec { I830MemRange ContextMem; #ifdef XF86DRI I830MemRange BackBuffer; + I830MemRange ThirdBuffer; I830MemRange DepthBuffer; I830MemRange TexMem; int TexGranularity; @@ -304,6 +305,7 @@ typedef struct _I830Rec { unsigned int front_tiled; unsigned int back_tiled; + unsigned int third_tiled; unsigned int depth_tiled; #ifdef DAMAGE @@ -313,6 +315,7 @@ typedef struct _I830Rec { Bool NeedRingBufferLow; Bool allowPageFlip; + Bool TripleBuffer; Bool disableTiling; int backPitch; @@ -511,6 +514,7 @@ typedef struct _I830Rec { #define I830_SELECT_FRONT 0 #define I830_SELECT_BACK 1 #define I830_SELECT_DEPTH 2 +#define I830_SELECT_THIRD 3 /* I830 specific functions */ extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis); @@ -539,6 +543,7 @@ extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on); #ifdef XF86DRI extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags); extern Bool I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags); +extern Bool I830AllocateThirdBuffer(ScrnInfoPtr pScrn, const int flags); extern Bool I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags); extern Bool I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags); extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn); diff --git a/src/i830_accel.c b/src/i830_accel.c index db3168a8..c76c7483 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -228,6 +228,9 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int buffer) case I830_SELECT_BACK: pI830->bufferOffset = pI830->BackBuffer.Start; break; + case I830_SELECT_THIRD: + pI830->bufferOffset = pI830->ThirdBuffer.Start; + break; case I830_SELECT_DEPTH: pI830->bufferOffset = pI830->DepthBuffer.Start; break; diff --git a/src/i830_common.h b/src/i830_common.h index 79455b61..f853ccd8 100644 --- a/src/i830_common.h +++ b/src/i830_common.h @@ -130,6 +130,12 @@ typedef struct { int pipeB_y; int pipeB_w; int pipeB_h; + + /* Triple buffering */ + drm_handle_t third_handle; + int third_offset; + int third_size; + unsigned int third_tiled; } drmI830Sarea; /* Flags for perf_boxes diff --git a/src/i830_dri.c b/src/i830_dri.c index d6551830..65736cdc 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -751,6 +751,20 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08x\n", (int)sarea->back_handle); + if (pI830->TripleBuffer) { + if (drmAddMap(pI830->drmSubFD, + (drm_handle_t)(sarea->third_offset + pI830->LinearAddr), + sarea->third_size, DRM_AGP, 0, + (drmAddress) &sarea->third_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(third_handle) failed. Disabling DRI\n"); + DRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n", + (int)sarea->third_handle); + } + if (drmAddMap(pI830->drmSubFD, (drm_handle_t)sarea->depth_offset + pI830->LinearAddr, sarea->depth_size, DRM_AGP, 0, @@ -794,6 +808,10 @@ I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) drmRmMap(pI830->drmSubFD, sarea->back_handle); sarea->back_handle = 0; } + if (sarea->third_handle) { + drmRmMap(pI830->drmSubFD, sarea->third_handle); + sarea->third_handle = 0; + } if (sarea->depth_handle) { drmRmMap(pI830->drmSubFD, sarea->depth_handle); sarea->depth_handle = 0; @@ -870,6 +888,7 @@ I830DRIDoMappings(ScreenPtr pScreen) /* init to zero to be safe */ sarea->front_handle = 0; sarea->back_handle = 0; + sarea->third_handle = 0; sarea->depth_handle = 0; sarea->tex_handle = 0; @@ -1041,17 +1060,10 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) * Otherwise will have to sync again??? */ static void -I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox) +I830DRIDoRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox, CARD32 dst) { 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 | @@ -1068,12 +1080,31 @@ I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox) OUT_RING(br13); OUT_RING((pbox->y1 << 16) | pbox->x1); OUT_RING((pbox->y2 << 16) | pbox->x2); - OUT_RING(pI830->BackBuffer.Start); + OUT_RING(dst); OUT_RING((pbox->y1 << 16) | pbox->x1); OUT_RING(br13 & 0xffff); OUT_RING(pI830->FrontBuffer.Start); ADVANCE_LP_RING(); } +} + +static void +I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + I830Ptr pI830 = I830PTR(pScrn); + 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; + + I830DRIDoRefreshArea(pScrn, num, pbox, pI830->BackBuffer.Start); + + if (pI830->TripleBuffer) { + I830DRIDoRefreshArea(pScrn, num, pbox, pI830->ThirdBuffer.Start); + } DamageEmpty(pI830->pDamage); } @@ -1160,6 +1191,13 @@ I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) I830SelectBuffer(pScrn, I830_SELECT_BACK); I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + + if (I830PTR(pScrn)->TripleBuffer) { + I830SelectBuffer(pScrn, I830_SELECT_THIRD); + I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + } + pbox++; } @@ -1333,6 +1371,10 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, I830SelectBuffer(pScrn, I830_SELECT_BACK); I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + if (pI830->TripleBuffer) { + I830SelectBuffer(pScrn, I830_SELECT_THIRD); + I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + } if (!IS_I965G(pI830)) { I830SelectBuffer(pScrn, I830_SELECT_DEPTH); I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); @@ -1492,6 +1534,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) sarea->front_tiled = pI830->front_tiled; sarea->back_tiled = pI830->back_tiled; + sarea->third_tiled = pI830->third_tiled; sarea->depth_tiled = pI830->depth_tiled; sarea->rotated_tiled = FALSE; @@ -1509,6 +1552,8 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) sarea->height = pScreen->height; sarea->back_offset = pI830->BackBuffer.Start; sarea->back_size = pI830->BackBuffer.Size; + sarea->third_offset = pI830->ThirdBuffer.Start; + sarea->third_size = pI830->ThirdBuffer.Size; sarea->depth_offset = pI830->DepthBuffer.Start; sarea->depth_size = pI830->DepthBuffer.Size; sarea->tex_offset = pI830->TexMem.Start; diff --git a/src/i830_dri.h b/src/i830_dri.h index a1404978..a2cf78ec 100644 --- a/src/i830_dri.h +++ b/src/i830_dri.h @@ -9,8 +9,8 @@ #define I830_MAX_DRAWABLES 256 #define I830_MAJOR_VERSION 1 -#define I830_MINOR_VERSION 7 -#define I830_PATCHLEVEL 2 +#define I830_MINOR_VERSION 8 +#define I830_PATCHLEVEL 0 #define I830_REG_SIZE 0x80000 diff --git a/src/i830_driver.c b/src/i830_driver.c index d1f83e5a..3c8ec1a1 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -273,7 +273,8 @@ typedef enum { OPTION_CHECKDEVICES, OPTION_LINEARALLOC, OPTION_INTELTEXPOOL, - OPTION_INTELMMSIZE + OPTION_INTELMMSIZE, + OPTION_TRIPLEBUFFER, } I830Opts; static OptionInfoRec I830Options[] = { @@ -292,6 +293,7 @@ static OptionInfoRec I830Options[] = { {OPTION_LINEARALLOC, "LinearAlloc", OPTV_INTEGER, {0}, FALSE}, {OPTION_INTELTEXPOOL,"Legacy3D", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_INTELMMSIZE, "AperTexSize", OPTV_INTEGER, {0}, FALSE}, + {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -1487,6 +1489,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } #endif +#ifdef XF86DRI + pI830->TripleBuffer = FALSE; + from = (!pI830->directRenderingDisabled && + xf86GetOptValBool(pI830->Options, OPTION_TRIPLEBUFFER, + &pI830->TripleBuffer)) ? X_CONFIG : X_DEFAULT; + + xf86DrvMsg(pScrn->scrnIndex, from, "Triple buffering %sabled\n", + pI830->TripleBuffer ? "en" : "dis"); +#endif + /* * If the driver can do gamma correction, it should call xf86SetGamma() here. */ diff --git a/src/i830_memory.c b/src/i830_memory.c index 29d9d31d..2d1cca9c 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1118,6 +1118,69 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags) } Bool +I830AllocateThirdBuffer(ScrnInfoPtr pScrn, const int flags) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned long size, alloced, align = 0; + Bool tileable; + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + int lines; + int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX; + + /* Third Buffer */ + memset(&(pI830->ThirdBuffer), 0, sizeof(pI830->ThirdBuffer)); + pI830->ThirdBuffer.Key = -1; + tileable = !(flags & ALLOC_NO_TILING) && + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); + if (tileable) { + /* Make the height a multiple of the tile height (16) */ + lines = (height + 15) / 16 * 16; + } else { + lines = height; + } + + size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp); + /* + * Try to allocate on the best tile-friendly boundaries. + */ + alloced = 0; + if (tileable) { + align = GetBestTileAlignment(size); + for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) { + alloced = I830AllocVidMem(pScrn, &(pI830->ThirdBuffer), + &(pI830->StolenPool), size, align, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | + ALIGN_BOTH_ENDS); + if (alloced >= size) + break; + } + } + if (alloced < size) { + /* Give up on trying to tile */ + tileable = FALSE; + size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp); + align = GTT_PAGE_SIZE; + alloced = I830AllocVidMem(pScrn, &(pI830->ThirdBuffer), + &(pI830->StolenPool), size, align, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); + } + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate third buffer space.\n"); + } + return FALSE; + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for the third buffer at 0x%lx.\n", s, + alloced / 1024, pI830->ThirdBuffer.Start); + + return TRUE; +} + +Bool I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags) { I830Ptr pI830 = I830PTR(pScrn); @@ -1271,6 +1334,9 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) if (!I830AllocateBackBuffer(pScrn, flags)) return FALSE; + if (pI830->TripleBuffer && !I830AllocateThirdBuffer(pScrn, flags)) + return FALSE; + if (!I830AllocateDepthBuffer(pScrn, flags)) return FALSE; @@ -1439,6 +1505,7 @@ I830FixupOffsets(ScrnInfoPtr pScrn) if (pI830->directRenderingEnabled) { I830FixOffset(pScrn, &(pI830->ContextMem)); I830FixOffset(pScrn, &(pI830->BackBuffer)); + I830FixOffset(pScrn, &(pI830->ThirdBuffer)); I830FixOffset(pScrn, &(pI830->DepthBuffer)); if (pI830->mmModeFlags & I830_KERNEL_TEX) { I830FixOffset(pScrn, &(pI830->TexMem)); @@ -1701,6 +1768,7 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) pI830->front_tiled = FENCE_LINEAR; pI830->back_tiled = FENCE_LINEAR; + pI830->third_tiled = FENCE_LINEAR; pI830->depth_tiled = FENCE_LINEAR; if (pI830->allowPageFlip) { @@ -1739,6 +1807,18 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) } } + if (pI830->ThirdBuffer.Alignment >= KB(512)) { + if (MakeTiles(pScrn, &(pI830->ThirdBuffer), FENCE_XMAJOR)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Activating tiled memory for the third buffer.\n"); + pI830->third_tiled = FENCE_XMAJOR; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MakeTiles failed for the third buffer.\n"); + pI830->allowPageFlip = FALSE; + } + } + if (pI830->DepthBuffer.Alignment >= KB(512)) { if (MakeTiles(pScrn, &(pI830->DepthBuffer), FENCE_YMAJOR)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -1825,6 +1905,8 @@ I830BindAGPMemory(ScrnInfoPtr pScrn) return FALSE; if (!BindMemRange(pScrn, &(pI830->BackBuffer))) return FALSE; + if (pI830->TripleBuffer && !BindMemRange(pScrn, &(pI830->ThirdBuffer))) + return FALSE; if (!BindMemRange(pScrn, &(pI830->DepthBuffer))) return FALSE; if ((pI830->mmModeFlags & I830_KERNEL_TEX) && @@ -1919,6 +2001,8 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn) return FALSE; if (!UnbindMemRange(pScrn, &(pI830->BackBuffer))) return FALSE; + if (pI830->TripleBuffer && !UnbindMemRange(pScrn, &(pI830->ThirdBuffer))) + return FALSE; if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer))) return FALSE; if ((pI830->mmModeFlags & I830_KERNEL_TEX) && diff --git a/src/i830_xaa.c b/src/i830_xaa.c index 5ef5d3c4..9b11973f 100644 --- a/src/i830_xaa.c +++ b/src/i830_xaa.c @@ -281,6 +281,8 @@ CheckTiling(ScrnInfoPtr pScrn) tiled = 1; if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR) tiled = 1; + if (pI830->bufferOffset == pI830->ThirdBuffer.Start && pI830->third_tiled == FENCE_XMAJOR) + tiled = 1; /* not really supported as it's always YMajor tiled */ if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR) tiled = 1; |