summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2007-02-20 19:09:37 +0100
committerMichel Dänzer <michel@tungstengraphics.com>2007-02-20 19:09:37 +0100
commit0bee64f4bc7581de7ab28ca438581d215e85c610 (patch)
tree0144ade1edf46ff1b5322f20fa4501919260defa
parent2212baa8454abb4c7948c3f2e20e337f831d1b86 (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.man17
-rw-r--r--src/i830.h5
-rw-r--r--src/i830_accel.c3
-rw-r--r--src/i830_common.h6
-rw-r--r--src/i830_dri.c63
-rw-r--r--src/i830_dri.h4
-rw-r--r--src/i830_driver.c14
-rw-r--r--src/i830_memory.c84
-rw-r--r--src/i830_xaa.c2
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
diff --git a/src/i830.h b/src/i830.h
index 78381fbf..bbbb4a8e 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -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;