EXA: FillRegion{Solid,Tiled} improvements.

* Support planemasks, different ALUs and arbitrary tile origin.
* Leave damage tracking and non-trivial fallbacks to callers.
* Always migrate for fallbacks.

This is in preparation for using these from more other functions.
This commit is contained in:
Michel Dänzer 2007-04-29 23:46:49 +02:00
parent e869573b52
commit 567f18a09b
3 changed files with 72 additions and 40 deletions

View File

@ -126,7 +126,7 @@ exaGetDrawablePixmap(DrawablePtr pDrawable)
* the backing drawable. These coordinates are nonzero only for redirected * the backing drawable. These coordinates are nonzero only for redirected
* windows. * windows.
*/ */
static void void
exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
int *xp, int *yp) int *xp, int *yp)
{ {

View File

@ -1043,10 +1043,12 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
} }
static void static Bool
exaFillRegionSolid (DrawablePtr pDrawable, exaFillRegionSolid (DrawablePtr pDrawable,
RegionPtr pRegion, RegionPtr pRegion,
Pixel pixel) Pixel pixel,
CARD32 planemask,
CARD32 alu)
{ {
ExaScreenPriv(pDrawable->pScreen); ExaScreenPriv(pDrawable->pScreen);
PixmapPtr pPixmap; PixmapPtr pPixmap;
@ -1062,22 +1064,19 @@ exaFillRegionSolid (DrawablePtr pDrawable,
if (pPixmap->drawable.width > pExaScr->info->maxX || if (pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY) pPixmap->drawable.height > pExaScr->info->maxY)
{ {
exaDoMigration (pixmaps, 1, FALSE);
goto fallback; goto fallback;
} else { } else {
exaDoMigration (pixmaps, 1, TRUE); exaDoMigration (pixmaps, 1, TRUE);
} }
if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel)) (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
{ {
while (nbox--) while (nbox--)
{ {
(*pExaScr->info->Solid) (pPixmap, (*pExaScr->info->Solid) (pPixmap,
pBox->x1 + xoff, pBox->y1 + yoff, pBox->x1 + xoff, pBox->y1 + yoff,
pBox->x2 + xoff, pBox->y2 + yoff); pBox->x2 + xoff, pBox->y2 + yoff);
exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff,
pBox->x2 + xoff, pBox->y2 + yoff);
pBox++; pBox++;
} }
(*pExaScr->info->DoneSolid) (pPixmap); (*pExaScr->info->DoneSolid) (pPixmap);
@ -1086,27 +1085,30 @@ exaFillRegionSolid (DrawablePtr pDrawable,
else else
{ {
fallback: fallback:
if (alu != GXcopy || planemask != FB_ALLONES)
return FALSE;
EXA_FALLBACK(("to %p (%c)\n", pDrawable, EXA_FALLBACK(("to %p (%c)\n", pDrawable,
exaDrawableLocation(pDrawable))); exaDrawableLocation(pDrawable)));
exaDoMigration (pixmaps, 1, FALSE);
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
fbFillRegionSolid (pDrawable, pRegion, 0, fbFillRegionSolid (pDrawable, pRegion, 0,
fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
exaFinishAccess (pDrawable, EXA_PREPARE_DEST); exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
while (nbox--)
{
exaDrawableDirty (pDrawable, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
pBox++;
}
} }
return TRUE;
} }
/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. /* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
* Based on fbFillRegionTiled(), fbTile(). * Based on fbFillRegionTiled(), fbTile().
*/ */
static void Bool
exaFillRegionTiled (DrawablePtr pDrawable, exaFillRegionTiled (DrawablePtr pDrawable,
RegionPtr pRegion, RegionPtr pRegion,
PixmapPtr pTile) PixmapPtr pTile,
DDXPointPtr pPatOrg,
CARD32 planemask,
CARD32 alu)
{ {
ExaScreenPriv(pDrawable->pScreen); ExaScreenPriv(pDrawable->pScreen);
PixmapPtr pPixmap; PixmapPtr pPixmap;
@ -1122,10 +1124,10 @@ exaFillRegionTiled (DrawablePtr pDrawable,
/* If we're filling with a solid color, grab it out and go to /* If we're filling with a solid color, grab it out and go to
* FillRegionSolid, saving numerous copies. * FillRegionSolid, saving numerous copies.
*/ */
if (tileWidth == 1 && tileHeight == 1) { if (tileWidth == 1 && tileHeight == 1)
exaFillRegionSolid(pDrawable, pRegion, exaGetPixmapFirstPixel (pTile)); return exaFillRegionSolid(pDrawable, pRegion,
return; exaGetPixmapFirstPixel (pTile), planemask,
} alu);
pixmaps[0].as_dst = TRUE; pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE; pixmaps[0].as_src = FALSE;
@ -1139,7 +1141,6 @@ exaFillRegionTiled (DrawablePtr pDrawable,
tileWidth > pExaScr->info->maxX || tileWidth > pExaScr->info->maxX ||
tileHeight > pExaScr->info->maxY) tileHeight > pExaScr->info->maxY)
{ {
exaDoMigration (pixmaps, 2, FALSE);
goto fallback; goto fallback;
} else { } else {
exaDoMigration (pixmaps, 2, TRUE); exaDoMigration (pixmaps, 2, TRUE);
@ -1153,8 +1154,9 @@ exaFillRegionTiled (DrawablePtr pDrawable,
if (!exaPixmapIsOffscreen(pTile)) if (!exaPixmapIsOffscreen(pTile))
goto fallback; goto fallback;
if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile, &tileXoff, &tileYoff), pPixmap, 0, 0, GXcopy, if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile,
FB_ALLONES)) &tileXoff, &tileYoff),
pPixmap, 0, 0, alu, planemask))
{ {
while (nbox--) while (nbox--)
{ {
@ -1162,7 +1164,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
int dstY = pBox->y1; int dstY = pBox->y1;
int tileY; int tileY;
tileY = (dstY - pDrawable->y) % tileHeight; tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight;
while (height > 0) { while (height > 0) {
int width = pBox->x2 - pBox->x1; int width = pBox->x2 - pBox->x1;
int dstX = pBox->x1; int dstX = pBox->x1;
@ -1173,7 +1175,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
h = height; h = height;
height -= h; height -= h;
tileX = (dstX - pDrawable->x) % tileWidth; tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth;
while (width > 0) { while (width > 0) {
int w = tileWidth - tileX; int w = tileWidth - tileX;
if (w > width) if (w > width)
@ -1190,38 +1192,44 @@ exaFillRegionTiled (DrawablePtr pDrawable,
dstY += h; dstY += h;
tileY = 0; tileY = 0;
} }
exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff,
pBox->x2 + xoff, pBox->y2 + yoff);
pBox++; pBox++;
} }
(*pExaScr->info->DoneCopy) (pPixmap); (*pExaScr->info->DoneCopy) (pPixmap);
exaMarkSync(pDrawable->pScreen); exaMarkSync(pDrawable->pScreen);
return; return TRUE;
} }
fallback: fallback:
if (alu != GXcopy || planemask != FB_ALLONES)
return FALSE;
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable, EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable,
exaDrawableLocation(&pTile->drawable), exaDrawableLocation(&pTile->drawable),
exaDrawableLocation(pDrawable))); exaDrawableLocation(pDrawable)));
exaDoMigration (pixmaps, 2, FALSE);
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
fbFillRegionTiled (pDrawable, pRegion, pTile); fbFillRegionTiled (pDrawable, pRegion, pTile);
exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST); exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
while (nbox--)
{ return TRUE;
exaDrawableDirty (pDrawable, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
pBox++;
}
} }
void void
exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
{ {
ExaScreenPriv (pWin->drawable.pScreen); ExaScreenPriv (pWin->drawable.pScreen);
if (!REGION_NUM_RECTS(pRegion)) PixmapPtr pPixmap = exaGetDrawablePixmap((DrawablePtr)pWin);
int xoff, yoff;
BoxPtr pBox;
int nbox = REGION_NUM_RECTS(pRegion);
if (!nbox)
return; return;
if (!pExaScr->swappedOut) { if (!pExaScr->swappedOut) {
DDXPointRec zeros = { 0, 0 };
switch (what) { switch (what) {
case PW_BACKGROUND: case PW_BACKGROUND:
switch (pWin->backgroundState) { switch (pWin->backgroundState) {
@ -1235,25 +1243,41 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
what); what);
return; return;
case BackgroundPixel: case BackgroundPixel:
exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel,
return; FB_ALLONES, GXcopy);
goto damage;
case BackgroundPixmap: case BackgroundPixmap:
exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap); exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap,
return; &zeros, FB_ALLONES, GXcopy);
goto damage;
} }
break; break;
case PW_BORDER: case PW_BORDER:
if (pWin->borderIsPixel) { if (pWin->borderIsPixel) {
exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel,
return; FB_ALLONES, GXcopy);
goto damage;
} else { } else {
exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap); exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap,
return; &zeros, FB_ALLONES, GXcopy);
goto damage;
} }
break; break;
} }
} }
ExaCheckPaintWindow (pWin, pRegion, what); ExaCheckPaintWindow (pWin, pRegion, what);
damage:
exaGetDrawableDeltas((DrawablePtr)pWin, pPixmap, &xoff, &yoff);
pBox = REGION_RECTS(pRegion);
while (nbox--)
{
exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff,
pBox->x2 + xoff, pBox->y2 + yoff);
pBox++;
}
} }
/** /**

View File

@ -288,6 +288,10 @@ exaGetPixmapFirstPixel (PixmapPtr pPixmap);
void void
exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
Bool
exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu);
void void
exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what);
@ -343,6 +347,10 @@ exaFinishAccess(DrawablePtr pDrawable, int index);
void void
exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2); exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2);
void
exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
int *xp, int *yp);
void void
exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2); exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2);