Revive i830 page flipping support.

Use the damage layer directly instead of via shadowfb.
This commit is contained in:
Michel Dänzer 2007-02-02 17:41:18 +01:00
parent 1d22bad33b
commit 3bd8edb95f
5 changed files with 144 additions and 118 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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,