Track per-drawable damage to minimize UTS and DFS transfers.
Based on work by Eric Anholt.
This commit is contained in:
parent
6060b612de
commit
f9f33b72e3
49
exa/exa.c
49
exa/exa.c
|
@ -122,13 +122,22 @@ exaGetDrawablePixmap(DrawablePtr pDrawable)
|
||||||
* optimizations in pixmap migration when no changes have occurred.
|
* optimizations in pixmap migration when no changes have occurred.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
exaDrawableDirty (DrawablePtr pDrawable)
|
exaDrawableDirty (DrawablePtr pDrawable, int x1, int y1, int x2, int y2)
|
||||||
{
|
{
|
||||||
ExaPixmapPrivPtr pExaPixmap;
|
ExaPixmapPrivPtr pExaPixmap;
|
||||||
|
RegionPtr pDamageReg;
|
||||||
|
BoxRec box = { max(x1,0), max(y1,0), min(x2,pDrawable->width), min(y2,pDrawable->height) };
|
||||||
|
RegionRec region;
|
||||||
|
|
||||||
pExaPixmap = ExaGetPixmapPriv(exaGetDrawablePixmap (pDrawable));
|
pExaPixmap = ExaGetPixmapPriv(exaGetDrawablePixmap (pDrawable));
|
||||||
if (pExaPixmap != NULL)
|
if (!pExaPixmap || box.x1 >= box.x2 || box.y1 >= box.y2)
|
||||||
pExaPixmap->dirty = TRUE;
|
return;
|
||||||
|
|
||||||
|
pDamageReg = DamageRegion(pExaPixmap->pDamage);
|
||||||
|
|
||||||
|
REGION_INIT(pScreen, ®ion, &box, 1);
|
||||||
|
REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion);
|
||||||
|
REGION_UNINIT(pScreen, ®ion);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
|
@ -149,6 +158,7 @@ exaDestroyPixmap (PixmapPtr pPixmap)
|
||||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||||
}
|
}
|
||||||
|
REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validReg);
|
||||||
}
|
}
|
||||||
return fbDestroyPixmap (pPixmap);
|
return fbDestroyPixmap (pPixmap);
|
||||||
}
|
}
|
||||||
|
@ -216,7 +226,20 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pExaPixmap->dirty = FALSE;
|
/* Set up damage tracking */
|
||||||
|
pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE,
|
||||||
|
pScreen, pPixmap);
|
||||||
|
|
||||||
|
if (pExaPixmap->pDamage == NULL) {
|
||||||
|
fbDestroyPixmap (pPixmap);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
|
||||||
|
DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
|
||||||
|
|
||||||
|
/* None of the pixmap bits are valid initially */
|
||||||
|
REGION_NULL(pScreen, &pExaPixmap->validReg);
|
||||||
|
|
||||||
return pPixmap;
|
return pPixmap;
|
||||||
}
|
}
|
||||||
|
@ -334,8 +357,7 @@ exaPrepareAccess(DrawablePtr pDrawable, int index)
|
||||||
/**
|
/**
|
||||||
* exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
|
* exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
|
||||||
*
|
*
|
||||||
* It deals with marking drawables as dirty, and calling the driver's
|
* It deals with calling the driver's FinishAccess() only if necessary.
|
||||||
* FinishAccess() only if necessary.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
exaFinishAccess(DrawablePtr pDrawable, int index)
|
exaFinishAccess(DrawablePtr pDrawable, int index)
|
||||||
|
@ -345,9 +367,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
|
||||||
PixmapPtr pPixmap;
|
PixmapPtr pPixmap;
|
||||||
ExaPixmapPrivPtr pExaPixmap;
|
ExaPixmapPrivPtr pExaPixmap;
|
||||||
|
|
||||||
if (index == EXA_PREPARE_DEST)
|
|
||||||
exaDrawableDirty (pDrawable);
|
|
||||||
|
|
||||||
pPixmap = exaGetDrawablePixmap (pDrawable);
|
pPixmap = exaGetDrawablePixmap (pDrawable);
|
||||||
|
|
||||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||||
|
@ -373,7 +392,7 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
|
||||||
* accelerated or may sync the card and fall back to fb.
|
* accelerated or may sync the card and fall back to fb.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
exaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
|
exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
|
||||||
{
|
{
|
||||||
/* fbValidateGC will do direct access to pixmaps if the tiling has changed.
|
/* fbValidateGC will do direct access to pixmaps if the tiling has changed.
|
||||||
* Preempt fbValidateGC by doing its work and masking the change out, so
|
* Preempt fbValidateGC by doing its work and masking the change out, so
|
||||||
|
@ -404,6 +423,7 @@ exaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
|
||||||
exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
|
exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
|
||||||
pNewTile = fb24_32ReformatTile (pOldTile,
|
pNewTile = fb24_32ReformatTile (pOldTile,
|
||||||
pDrawable->bitsPerPixel);
|
pDrawable->bitsPerPixel);
|
||||||
|
exaDrawableDirty(&pNewTile->drawable, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height);
|
||||||
exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
|
exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
|
||||||
}
|
}
|
||||||
if (pNewTile)
|
if (pNewTile)
|
||||||
|
@ -419,9 +439,14 @@ exaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
|
||||||
if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
|
if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
|
||||||
pDrawable->bitsPerPixel))
|
pDrawable->bitsPerPixel))
|
||||||
{
|
{
|
||||||
exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
|
/* XXX This fixes corruption with tiled pixmaps, but may just be a
|
||||||
|
* workaround for broken drivers
|
||||||
|
*/
|
||||||
|
exaMoveOutPixmap(pGC->tile.pixmap);
|
||||||
fbPadPixmap (pGC->tile.pixmap);
|
fbPadPixmap (pGC->tile.pixmap);
|
||||||
exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
|
exaDrawableDirty(&pGC->tile.pixmap->drawable, 0, 0,
|
||||||
|
pGC->tile.pixmap->drawable.width,
|
||||||
|
pGC->tile.pixmap->drawable.height);
|
||||||
}
|
}
|
||||||
/* Mask out the GCTile change notification, now that we've done FB's
|
/* Mask out the GCTile change notification, now that we've done FB's
|
||||||
* job for it.
|
* job for it.
|
||||||
|
|
109
exa/exa_accel.c
109
exa/exa_accel.c
|
@ -20,6 +20,11 @@
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Eric Anholt <eric@anholt.net>
|
||||||
|
* Michel Dänzer <michel@tungstengraphics.com>
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_DIX_CONFIG_H
|
#ifdef HAVE_DIX_CONFIG_H
|
||||||
|
@ -104,6 +109,9 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
|
||||||
(*pExaScr->info->Solid) (pPixmap,
|
(*pExaScr->info->Solid) (pPixmap,
|
||||||
fullX1 + off_x, fullY1 + off_y,
|
fullX1 + off_x, fullY1 + off_y,
|
||||||
fullX2 + off_x, fullY1 + 1 + off_y);
|
fullX2 + off_x, fullY1 + 1 + off_y);
|
||||||
|
exaDrawableDirty (pDrawable,
|
||||||
|
fullX1 + off_x, fullY1 + off_y,
|
||||||
|
fullX2 + off_x, fullY1 + 1 + off_y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -118,17 +126,20 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
|
||||||
partX2 = pbox->x2;
|
partX2 = pbox->x2;
|
||||||
if (partX2 > fullX2)
|
if (partX2 > fullX2)
|
||||||
partX2 = fullX2;
|
partX2 = fullX2;
|
||||||
if (partX2 > partX1)
|
if (partX2 > partX1) {
|
||||||
(*pExaScr->info->Solid) (pPixmap,
|
(*pExaScr->info->Solid) (pPixmap,
|
||||||
partX1 + off_x, fullY1 + off_y,
|
partX1 + off_x, fullY1 + off_y,
|
||||||
partX2 + off_x, fullY1 + 1 + off_y);
|
partX2 + off_x, fullY1 + 1 + off_y);
|
||||||
|
exaDrawableDirty (pDrawable,
|
||||||
|
partX1 + off_x, fullY1 + off_y,
|
||||||
|
partX2 + off_x, fullY1 + 1 + off_y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pbox++;
|
pbox++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*pExaScr->info->DoneSolid) (pPixmap);
|
(*pExaScr->info->DoneSolid) (pPixmap);
|
||||||
exaDrawableDirty (pDrawable);
|
|
||||||
exaMarkSync(pScreen);
|
exaMarkSync(pScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,8 +233,8 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
|
||||||
|
|
||||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||||
}
|
}
|
||||||
|
exaDrawableDirty(pDrawable, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff);
|
||||||
}
|
}
|
||||||
exaDrawableDirty(pDrawable);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -351,11 +362,13 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
|
||||||
dst_off_y + pbox->y1 + i,
|
dst_off_y + pbox->y1 + i,
|
||||||
pbox->x2 - pbox->x1, 1);
|
pbox->x2 - pbox->x1, 1);
|
||||||
}
|
}
|
||||||
|
exaDrawableDirty(pDstDrawable,
|
||||||
|
dst_off_x + pbox->x1, dst_off_y + pbox->y1,
|
||||||
|
dst_off_x + pbox->x2, dst_off_y + pbox->y2);
|
||||||
}
|
}
|
||||||
if (dirsetup != 0)
|
if (dirsetup != 0)
|
||||||
pExaScr->info->DoneCopy(pDstPixmap);
|
pExaScr->info->DoneCopy(pDstPixmap);
|
||||||
exaMarkSync(pDstDrawable->pScreen);
|
exaMarkSync(pDstDrawable->pScreen);
|
||||||
exaDrawableDirty(pDstDrawable);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,11 +436,13 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
|
||||||
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
|
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
|
||||||
pbox->x2 - pbox->x1,
|
pbox->x2 - pbox->x1,
|
||||||
pbox->y2 - pbox->y1);
|
pbox->y2 - pbox->y1);
|
||||||
|
exaDrawableDirty (pDstDrawable,
|
||||||
|
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
|
||||||
|
pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
|
||||||
pbox++;
|
pbox++;
|
||||||
}
|
}
|
||||||
(*pExaScr->info->DoneCopy) (pDstPixmap);
|
(*pExaScr->info->DoneCopy) (pDstPixmap);
|
||||||
exaMarkSync(pDstDrawable->pScreen);
|
exaMarkSync(pDstDrawable->pScreen);
|
||||||
exaDrawableDirty (pDstDrawable);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,6 +457,13 @@ fallback:
|
||||||
bitplane, closure);
|
bitplane, closure);
|
||||||
exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
|
exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
|
||||||
exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
|
exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
|
||||||
|
while (nbox--)
|
||||||
|
{
|
||||||
|
exaDrawableDirty (pDstDrawable,
|
||||||
|
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
|
||||||
|
pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
|
||||||
|
pbox++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionPtr
|
RegionPtr
|
||||||
|
@ -681,6 +703,9 @@ exaPolyFillRect(DrawablePtr pDrawable,
|
||||||
(*pExaScr->info->Solid) (pPixmap,
|
(*pExaScr->info->Solid) (pPixmap,
|
||||||
fullX1 + xoff, fullY1 + yoff,
|
fullX1 + xoff, fullY1 + yoff,
|
||||||
fullX2 + xoff, fullY2 + yoff);
|
fullX2 + xoff, fullY2 + yoff);
|
||||||
|
exaDrawableDirty (pDrawable,
|
||||||
|
fullX1 + xoff, fullY1 + yoff,
|
||||||
|
fullX2 + xoff, fullY2 + yoff);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -706,15 +731,18 @@ exaPolyFillRect(DrawablePtr pDrawable,
|
||||||
|
|
||||||
pbox++;
|
pbox++;
|
||||||
|
|
||||||
if (partX1 < partX2 && partY1 < partY2)
|
if (partX1 < partX2 && partY1 < partY2) {
|
||||||
(*pExaScr->info->Solid) (pPixmap,
|
(*pExaScr->info->Solid) (pPixmap,
|
||||||
partX1 + xoff, partY1 + yoff,
|
partX1 + xoff, partY1 + yoff,
|
||||||
partX2 + xoff, partY2 + yoff);
|
partX2 + xoff, partY2 + yoff);
|
||||||
|
exaDrawableDirty (pDrawable,
|
||||||
|
partX1 + xoff, partY1 + yoff,
|
||||||
|
partX2 + xoff, partY2 + yoff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*pExaScr->info->DoneSolid) (pPixmap);
|
(*pExaScr->info->DoneSolid) (pPixmap);
|
||||||
exaDrawableDirty (pDrawable);
|
|
||||||
exaMarkSync(pDrawable->pScreen);
|
exaMarkSync(pDrawable->pScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,11 +763,15 @@ exaSolidBoxClipped (DrawablePtr pDrawable,
|
||||||
int xoff, yoff;
|
int xoff, yoff;
|
||||||
int partX1, partX2, partY1, partY2;
|
int partX1, partX2, partY1, partY2;
|
||||||
ExaMigrationRec pixmaps[1];
|
ExaMigrationRec pixmaps[1];
|
||||||
|
Bool fallback = FALSE;
|
||||||
|
|
||||||
pixmaps[0].as_dst = TRUE;
|
pixmaps[0].as_dst = TRUE;
|
||||||
pixmaps[0].as_src = FALSE;
|
pixmaps[0].as_src = FALSE;
|
||||||
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
|
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
|
||||||
|
|
||||||
|
/* We need to initialize x/yoff for tracking damage in the fallback case */
|
||||||
|
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
|
||||||
|
|
||||||
if (pExaScr->swappedOut ||
|
if (pExaScr->swappedOut ||
|
||||||
pDrawable->width > pExaScr->info->maxX ||
|
pDrawable->width > pExaScr->info->maxX ||
|
||||||
pDrawable->height > pExaScr->info->maxY)
|
pDrawable->height > pExaScr->info->maxY)
|
||||||
|
@ -750,19 +782,21 @@ exaSolidBoxClipped (DrawablePtr pDrawable,
|
||||||
exaDoMigration (pixmaps, 1, TRUE);
|
exaDoMigration (pixmaps, 1, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
|
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
|
||||||
|
|
||||||
|
if (!pPixmap ||
|
||||||
!(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg))
|
!(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg))
|
||||||
{
|
{
|
||||||
fallback:
|
fallback:
|
||||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable,
|
EXA_FALLBACK(("to %p (%c)\n", pDrawable,
|
||||||
exaDrawableLocation(pDrawable)));
|
exaDrawableLocation(pDrawable)));
|
||||||
|
fallback = TRUE;
|
||||||
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
|
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
|
||||||
fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
|
fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
|
||||||
fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
|
fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
|
||||||
fbAnd (GXcopy, fg, pm),
|
fbAnd (GXcopy, fg, pm),
|
||||||
fbXor (GXcopy, fg, pm));
|
fbXor (GXcopy, fg, pm));
|
||||||
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
|
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
|
for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
|
||||||
nbox--;
|
nbox--;
|
||||||
|
@ -790,12 +824,19 @@ fallback:
|
||||||
if (partY2 <= partY1)
|
if (partY2 <= partY1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
(*pExaScr->info->Solid) (pPixmap,
|
if (!fallback)
|
||||||
partX1 + xoff, partY1 + yoff,
|
(*pExaScr->info->Solid) (pPixmap,
|
||||||
partX2 + xoff, partY2 + yoff);
|
partX1 + xoff, partY1 + yoff,
|
||||||
|
partX2 + xoff, partY2 + yoff);
|
||||||
|
exaDrawableDirty (pDrawable,
|
||||||
|
partX1 + xoff, partY1 + yoff,
|
||||||
|
partX2 + xoff, partY2 + yoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fallback)
|
||||||
|
return;
|
||||||
|
|
||||||
(*pExaScr->info->DoneSolid) (pPixmap);
|
(*pExaScr->info->DoneSolid) (pPixmap);
|
||||||
exaDrawableDirty (pDrawable);
|
|
||||||
exaMarkSync(pDrawable->pScreen);
|
exaMarkSync(pDrawable->pScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,6 +969,8 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
|
||||||
gStride,
|
gStride,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
exaDrawableDirty(pDrawable, gx + dstXoff, gy + dstYoff,
|
||||||
|
gx + dstXoff + gWidth, gy + dstYoff + gHeight);
|
||||||
}
|
}
|
||||||
x += pci->metrics.characterWidth;
|
x += pci->metrics.characterWidth;
|
||||||
}
|
}
|
||||||
|
@ -994,6 +1037,8 @@ exaFillRegionSolid (DrawablePtr pDrawable,
|
||||||
PixmapPtr pPixmap;
|
PixmapPtr pPixmap;
|
||||||
int xoff, yoff;
|
int xoff, yoff;
|
||||||
ExaMigrationRec pixmaps[1];
|
ExaMigrationRec pixmaps[1];
|
||||||
|
int nbox = REGION_NUM_RECTS (pRegion);
|
||||||
|
BoxPtr pBox = REGION_RECTS (pRegion);
|
||||||
|
|
||||||
pixmaps[0].as_dst = TRUE;
|
pixmaps[0].as_dst = TRUE;
|
||||||
pixmaps[0].as_src = FALSE;
|
pixmaps[0].as_src = FALSE;
|
||||||
|
@ -1011,19 +1056,18 @@ exaFillRegionSolid (DrawablePtr pDrawable,
|
||||||
if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
|
if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
|
||||||
(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel))
|
(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel))
|
||||||
{
|
{
|
||||||
int nbox = REGION_NUM_RECTS (pRegion);
|
|
||||||
BoxPtr pBox = REGION_RECTS (pRegion);
|
|
||||||
|
|
||||||
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);
|
||||||
|
exaDrawableDirty (pDrawable,
|
||||||
|
pBox->x1 + xoff, pBox->y1 + yoff,
|
||||||
|
pBox->x2 + xoff, pBox->y2 + yoff);
|
||||||
pBox++;
|
pBox++;
|
||||||
}
|
}
|
||||||
(*pExaScr->info->DoneSolid) (pPixmap);
|
(*pExaScr->info->DoneSolid) (pPixmap);
|
||||||
exaMarkSync(pDrawable->pScreen);
|
exaMarkSync(pDrawable->pScreen);
|
||||||
exaDrawableDirty (pDrawable);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1034,6 +1078,13 @@ fallback:
|
||||||
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 + xoff, pBox->y1 + yoff,
|
||||||
|
pBox->x2 + xoff, pBox->y2 + yoff);
|
||||||
|
pBox++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,9 +1098,11 @@ exaFillRegionTiled (DrawablePtr pDrawable,
|
||||||
{
|
{
|
||||||
ExaScreenPriv(pDrawable->pScreen);
|
ExaScreenPriv(pDrawable->pScreen);
|
||||||
PixmapPtr pPixmap;
|
PixmapPtr pPixmap;
|
||||||
int xoff, yoff;
|
int xoff, yoff, tileXoff, tileYoff;
|
||||||
int tileWidth, tileHeight;
|
int tileWidth, tileHeight;
|
||||||
ExaMigrationRec pixmaps[2];
|
ExaMigrationRec pixmaps[2];
|
||||||
|
int nbox = REGION_NUM_RECTS (pRegion);
|
||||||
|
BoxPtr pBox = REGION_RECTS (pRegion);
|
||||||
|
|
||||||
tileWidth = pTile->drawable.width;
|
tileWidth = pTile->drawable.width;
|
||||||
tileHeight = pTile->drawable.height;
|
tileHeight = pTile->drawable.height;
|
||||||
|
@ -1069,6 +1122,9 @@ exaFillRegionTiled (DrawablePtr pDrawable,
|
||||||
pixmaps[1].as_src = TRUE;
|
pixmaps[1].as_src = TRUE;
|
||||||
pixmaps[1].pPix = pTile;
|
pixmaps[1].pPix = pTile;
|
||||||
|
|
||||||
|
/* We need to initialize x/yoff for tracking damage in the fallback case */
|
||||||
|
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
|
||||||
|
|
||||||
if (pDrawable->width > pExaScr->info->maxX ||
|
if (pDrawable->width > pExaScr->info->maxX ||
|
||||||
pDrawable->height > pExaScr->info->maxY ||
|
pDrawable->height > pExaScr->info->maxY ||
|
||||||
tileWidth > pExaScr->info->maxX ||
|
tileWidth > pExaScr->info->maxX ||
|
||||||
|
@ -1081,18 +1137,16 @@ exaFillRegionTiled (DrawablePtr pDrawable,
|
||||||
}
|
}
|
||||||
|
|
||||||
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
|
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
|
||||||
|
|
||||||
if (!pPixmap)
|
if (!pPixmap)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
if (!exaPixmapIsOffscreen(pTile))
|
if (!exaPixmapIsOffscreen(pTile))
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy,
|
if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile, &tileXoff, &tileYoff), pPixmap, 0, 0, GXcopy,
|
||||||
FB_ALLONES))
|
FB_ALLONES))
|
||||||
{
|
{
|
||||||
int nbox = REGION_NUM_RECTS (pRegion);
|
|
||||||
BoxPtr pBox = REGION_RECTS (pRegion);
|
|
||||||
|
|
||||||
while (nbox--)
|
while (nbox--)
|
||||||
{
|
{
|
||||||
int height = pBox->y2 - pBox->y1;
|
int height = pBox->y2 - pBox->y1;
|
||||||
|
@ -1118,7 +1172,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
|
||||||
width -= w;
|
width -= w;
|
||||||
|
|
||||||
(*pExaScr->info->Copy) (pPixmap,
|
(*pExaScr->info->Copy) (pPixmap,
|
||||||
tileX, tileY,
|
tileX + tileXoff, tileY + tileYoff,
|
||||||
dstX + xoff, dstY + yoff,
|
dstX + xoff, dstY + yoff,
|
||||||
w, h);
|
w, h);
|
||||||
dstX += w;
|
dstX += w;
|
||||||
|
@ -1127,11 +1181,12 @@ exaFillRegionTiled (DrawablePtr pDrawable,
|
||||||
dstY += h;
|
dstY += h;
|
||||||
tileY = 0;
|
tileY = 0;
|
||||||
}
|
}
|
||||||
|
exaDrawableDirty (pDrawable, 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);
|
||||||
exaDrawableDirty (pDrawable);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1144,6 +1199,12 @@ fallback:
|
||||||
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--)
|
||||||
|
{
|
||||||
|
exaDrawableDirty (pDrawable, pBox->x1 + xoff, pBox->y1 + yoff,
|
||||||
|
pBox->x2 + xoff, pBox->y2 + yoff);
|
||||||
|
pBox++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Eric Anholt <eric@anholt.net>
|
* Eric Anholt <eric@anholt.net>
|
||||||
|
* Michel Dänzer <michel@tungstengraphics.com>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -57,6 +58,27 @@ exaPixmapIsPinned (PixmapPtr pPix)
|
||||||
return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
|
return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
|
||||||
|
* and exaCopyDirtyToFb both needed to do this loop.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
|
||||||
|
CARD8 *dst, int dst_pitch)
|
||||||
|
{
|
||||||
|
int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
|
||||||
|
int bytes = (pbox->x2 - pbox->x1) * cpp;
|
||||||
|
|
||||||
|
src += pbox->y1 * src_pitch + pbox->x1 * cpp;
|
||||||
|
dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
|
||||||
|
|
||||||
|
for (i = pbox->y2 - pbox->y1; i; i--) {
|
||||||
|
memcpy (dst, src, bytes);
|
||||||
|
src += src_pitch;
|
||||||
|
dst += dst_pitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns TRUE if the pixmap is dirty (has been modified in its current
|
* Returns TRUE if the pixmap is dirty (has been modified in its current
|
||||||
* location compared to the other), or lacks a private for tracking
|
* location compared to the other), or lacks a private for tracking
|
||||||
|
@ -67,7 +89,8 @@ exaPixmapIsDirty (PixmapPtr pPix)
|
||||||
{
|
{
|
||||||
ExaPixmapPriv (pPix);
|
ExaPixmapPriv (pPix);
|
||||||
|
|
||||||
return pExaPixmap == NULL || pExaPixmap->dirty == TRUE;
|
return pExaPixmap == NULL ||
|
||||||
|
REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,54 +121,62 @@ exaCopyDirtyToSys (PixmapPtr pPixmap)
|
||||||
{
|
{
|
||||||
ExaScreenPriv (pPixmap->drawable.pScreen);
|
ExaScreenPriv (pPixmap->drawable.pScreen);
|
||||||
ExaPixmapPriv (pPixmap);
|
ExaPixmapPriv (pPixmap);
|
||||||
|
RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage);
|
||||||
CARD8 *save_ptr;
|
CARD8 *save_ptr;
|
||||||
int save_pitch;
|
int save_pitch;
|
||||||
|
BoxPtr pBox = REGION_RECTS(pRegion);
|
||||||
if (!pExaPixmap->dirty)
|
int nbox = REGION_NUM_RECTS(pRegion);
|
||||||
return;
|
Bool do_sync = FALSE;
|
||||||
|
|
||||||
save_ptr = pPixmap->devPrivate.ptr;
|
save_ptr = pPixmap->devPrivate.ptr;
|
||||||
save_pitch = pPixmap->devKind;
|
save_pitch = pPixmap->devKind;
|
||||||
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
||||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||||
|
|
||||||
if (pExaScr->info->DownloadFromScreen == NULL ||
|
while (nbox--) {
|
||||||
!pExaScr->info->DownloadFromScreen (pPixmap,
|
pBox->x1 = max(pBox->x1, 0);
|
||||||
0,
|
pBox->y1 = max(pBox->y1, 0);
|
||||||
0,
|
pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
|
||||||
pPixmap->drawable.width,
|
pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
|
||||||
pPixmap->drawable.height,
|
|
||||||
pExaPixmap->sys_ptr,
|
|
||||||
pExaPixmap->sys_pitch))
|
|
||||||
{
|
|
||||||
char *src, *dst;
|
|
||||||
int src_pitch, dst_pitch, i, bytes;
|
|
||||||
|
|
||||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
|
||||||
|
continue;
|
||||||
|
|
||||||
dst = pExaPixmap->sys_ptr;
|
if (pExaScr->info->DownloadFromScreen == NULL ||
|
||||||
dst_pitch = pExaPixmap->sys_pitch;
|
!pExaScr->info->DownloadFromScreen (pPixmap,
|
||||||
src = pExaPixmap->fb_ptr;
|
pBox->x1, pBox->y1,
|
||||||
src_pitch = pExaPixmap->fb_pitch;
|
pBox->x2 - pBox->x1,
|
||||||
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
|
pBox->y2 - pBox->y1,
|
||||||
|
pExaPixmap->sys_ptr
|
||||||
for (i = 0; i < pPixmap->drawable.height; i++) {
|
+ pBox->y1 * pExaPixmap->sys_pitch
|
||||||
memcpy (dst, src, bytes);
|
+ pBox->x1 * pPixmap->drawable.bitsPerPixel / 8,
|
||||||
dst += dst_pitch;
|
pExaPixmap->sys_pitch))
|
||||||
src += src_pitch;
|
{
|
||||||
|
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
||||||
|
exaMemcpyBox (pPixmap, pBox,
|
||||||
|
pExaPixmap->fb_ptr, pExaPixmap->fb_pitch,
|
||||||
|
pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
|
||||||
|
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
||||||
}
|
}
|
||||||
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
else
|
||||||
|
do_sync = TRUE;
|
||||||
|
|
||||||
|
pBox++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the bits have actually landed, since we don't necessarily sync
|
/* Make sure the bits have actually landed, since we don't necessarily sync
|
||||||
* when accessing pixmaps in system memory.
|
* when accessing pixmaps in system memory.
|
||||||
*/
|
*/
|
||||||
exaWaitSync (pPixmap->drawable.pScreen);
|
if (do_sync)
|
||||||
|
exaWaitSync (pPixmap->drawable.pScreen);
|
||||||
|
|
||||||
pPixmap->devPrivate.ptr = save_ptr;
|
pPixmap->devPrivate.ptr = save_ptr;
|
||||||
pPixmap->devKind = save_pitch;
|
pPixmap->devKind = save_pitch;
|
||||||
|
|
||||||
pExaPixmap->dirty = FALSE;
|
/* The previously damaged bits are now no longer damaged but valid */
|
||||||
|
REGION_UNION(pPixmap->drawable.pScreen,
|
||||||
|
&pExaPixmap->validReg, &pExaPixmap->validReg, pRegion);
|
||||||
|
DamageEmpty (pExaPixmap->pDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,49 +189,59 @@ exaCopyDirtyToFb (PixmapPtr pPixmap)
|
||||||
{
|
{
|
||||||
ExaScreenPriv (pPixmap->drawable.pScreen);
|
ExaScreenPriv (pPixmap->drawable.pScreen);
|
||||||
ExaPixmapPriv (pPixmap);
|
ExaPixmapPriv (pPixmap);
|
||||||
|
RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage);
|
||||||
CARD8 *save_ptr;
|
CARD8 *save_ptr;
|
||||||
int save_pitch;
|
int save_pitch;
|
||||||
|
BoxPtr pBox = REGION_RECTS(pRegion);
|
||||||
if (!pExaPixmap->dirty)
|
int nbox = REGION_NUM_RECTS(pRegion);
|
||||||
return;
|
Bool do_sync = FALSE;
|
||||||
|
|
||||||
save_ptr = pPixmap->devPrivate.ptr;
|
save_ptr = pPixmap->devPrivate.ptr;
|
||||||
save_pitch = pPixmap->devKind;
|
save_pitch = pPixmap->devKind;
|
||||||
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
||||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||||
|
|
||||||
if (pExaScr->info->UploadToScreen == NULL ||
|
while (nbox--) {
|
||||||
!pExaScr->info->UploadToScreen (pPixmap,
|
pBox->x1 = max(pBox->x1, 0);
|
||||||
0,
|
pBox->y1 = max(pBox->y1, 0);
|
||||||
0,
|
pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
|
||||||
pPixmap->drawable.width,
|
pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
|
||||||
pPixmap->drawable.height,
|
|
||||||
pExaPixmap->sys_ptr,
|
|
||||||
pExaPixmap->sys_pitch))
|
|
||||||
{
|
|
||||||
char *src, *dst;
|
|
||||||
int src_pitch, dst_pitch, i, bytes;
|
|
||||||
|
|
||||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
|
if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
|
||||||
|
continue;
|
||||||
|
|
||||||
dst = pExaPixmap->fb_ptr;
|
if (pExaScr->info->UploadToScreen == NULL ||
|
||||||
dst_pitch = pExaPixmap->fb_pitch;
|
!pExaScr->info->UploadToScreen (pPixmap,
|
||||||
src = pExaPixmap->sys_ptr;
|
pBox->x1, pBox->y1,
|
||||||
src_pitch = pExaPixmap->sys_pitch;
|
pBox->x2 - pBox->x1,
|
||||||
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
|
pBox->y2 - pBox->y1,
|
||||||
|
pExaPixmap->sys_ptr
|
||||||
for (i = 0; i < pPixmap->drawable.height; i++) {
|
+ pBox->y1 * pExaPixmap->sys_pitch
|
||||||
memcpy (dst, src, bytes);
|
+ pBox->x1 * pPixmap->drawable.bitsPerPixel / 8,
|
||||||
dst += dst_pitch;
|
pExaPixmap->sys_pitch))
|
||||||
src += src_pitch;
|
{
|
||||||
|
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
|
||||||
|
exaMemcpyBox (pPixmap, pBox,
|
||||||
|
pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
|
||||||
|
pExaPixmap->fb_ptr, pExaPixmap->fb_pitch);
|
||||||
|
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
|
||||||
}
|
}
|
||||||
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
|
else
|
||||||
|
do_sync = TRUE;
|
||||||
|
|
||||||
|
pBox++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (do_sync)
|
||||||
|
exaMarkSync (pPixmap->drawable.pScreen);
|
||||||
|
|
||||||
pPixmap->devPrivate.ptr = save_ptr;
|
pPixmap->devPrivate.ptr = save_ptr;
|
||||||
pPixmap->devKind = save_pitch;
|
pPixmap->devKind = save_pitch;
|
||||||
|
|
||||||
pExaPixmap->dirty = FALSE;
|
/* The previously damaged bits are now no longer damaged but valid */
|
||||||
|
REGION_UNION(pPixmap->drawable.pScreen,
|
||||||
|
&pExaPixmap->validReg, &pExaPixmap->validReg, pRegion);
|
||||||
|
DamageEmpty (pExaPixmap->pDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -213,6 +254,7 @@ exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
|
||||||
{
|
{
|
||||||
PixmapPtr pPixmap = area->privData;
|
PixmapPtr pPixmap = area->privData;
|
||||||
ExaPixmapPriv(pPixmap);
|
ExaPixmapPriv(pPixmap);
|
||||||
|
RegionPtr pDamageReg = DamageRegion(pExaPixmap->pDamage);
|
||||||
|
|
||||||
DBG_MIGRATE (("Save %p (%p) (%dx%d) (%c)\n", pPixmap,
|
DBG_MIGRATE (("Save %p (%p) (%dx%d) (%c)\n", pPixmap,
|
||||||
(void*)(ExaGetPixmapPriv(pPixmap)->area ?
|
(void*)(ExaGetPixmapPriv(pPixmap)->area ?
|
||||||
|
@ -231,10 +273,9 @@ exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
|
||||||
pExaPixmap->fb_ptr = NULL;
|
pExaPixmap->fb_ptr = NULL;
|
||||||
pExaPixmap->area = NULL;
|
pExaPixmap->area = NULL;
|
||||||
|
|
||||||
/* Mark it dirty now, to say that there is important data in the
|
/* Mark all valid bits as damaged, so they'll get copied to FB next time */
|
||||||
* system-memory copy.
|
REGION_UNION(pPixmap->drawable.pScreen, pDamageReg, pDamageReg,
|
||||||
*/
|
&pExaPixmap->validReg);
|
||||||
pExaPixmap->dirty = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -413,30 +454,57 @@ exaMigrateTowardSys (PixmapPtr pPixmap)
|
||||||
* If the pixmap has both a framebuffer and system memory copy, this function
|
* If the pixmap has both a framebuffer and system memory copy, this function
|
||||||
* asserts that both of them are the same.
|
* asserts that both of them are the same.
|
||||||
*/
|
*/
|
||||||
static void
|
static Bool
|
||||||
exaAssertNotDirty (PixmapPtr pPixmap)
|
exaAssertNotDirty (PixmapPtr pPixmap)
|
||||||
{
|
{
|
||||||
ExaPixmapPriv (pPixmap);
|
ExaPixmapPriv (pPixmap);
|
||||||
CARD8 *dst, *src;
|
CARD8 *dst, *src;
|
||||||
int dst_pitch, src_pitch, data_row_bytes, y;
|
RegionPtr pValidReg = &pExaPixmap->validReg;
|
||||||
|
int dst_pitch, src_pitch, cpp, y, nbox = REGION_NUM_RECTS(pValidReg);
|
||||||
|
BoxPtr pBox = REGION_RECTS(pValidReg);
|
||||||
|
Bool ret = TRUE;
|
||||||
|
|
||||||
if (pExaPixmap == NULL || pExaPixmap->fb_ptr == NULL)
|
if (pExaPixmap == NULL || pExaPixmap->fb_ptr == NULL)
|
||||||
return;
|
return ret;
|
||||||
|
|
||||||
dst = pExaPixmap->sys_ptr;
|
dst = pExaPixmap->sys_ptr;
|
||||||
dst_pitch = pExaPixmap->sys_pitch;
|
dst_pitch = pExaPixmap->sys_pitch;
|
||||||
src = pExaPixmap->fb_ptr;
|
src = pExaPixmap->fb_ptr;
|
||||||
src_pitch = pExaPixmap->fb_pitch;
|
src_pitch = pExaPixmap->fb_pitch;
|
||||||
data_row_bytes = pPixmap->drawable.width *
|
cpp = pPixmap->drawable.bitsPerPixel / 8;
|
||||||
pPixmap->drawable.bitsPerPixel / 8;
|
|
||||||
|
|
||||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
||||||
for (y = 0; y < pPixmap->drawable.height; y++) {
|
while (nbox--) {
|
||||||
if (memcmp(dst, src, data_row_bytes) != 0) {
|
int rowbytes;
|
||||||
abort();
|
|
||||||
}
|
pBox->x1 = max(pBox->x1, 0);
|
||||||
|
pBox->y1 = max(pBox->y1, 0);
|
||||||
|
pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
|
||||||
|
pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
|
||||||
|
|
||||||
|
if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rowbytes = (pBox->x2 - pBox->x1) * cpp;
|
||||||
|
src += pBox->y1 * src_pitch + pBox->x1 * cpp;
|
||||||
|
dst += pBox->y1 * dst_pitch + pBox->x1 * cpp;
|
||||||
|
|
||||||
|
for (y = pBox->y2 - pBox->y1; y; y--) {
|
||||||
|
if (memcmp(dst + pBox->y1 * dst_pitch + pBox->x1 * cpp,
|
||||||
|
src + pBox->y1 * src_pitch + pBox->x1 * cpp,
|
||||||
|
(pBox->x2 - pBox->x1) * cpp) != 0) {
|
||||||
|
ret = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
src += src_pitch;
|
||||||
|
dst += dst_pitch;
|
||||||
|
}
|
||||||
|
src -= pBox->y1 * src_pitch + pBox->x1 * cpp;
|
||||||
|
dst -= pBox->y1 * dst_pitch + pBox->x1 * cpp;
|
||||||
}
|
}
|
||||||
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -460,8 +528,9 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
|
||||||
*/
|
*/
|
||||||
if (pExaScr->checkDirtyCorrectness) {
|
if (pExaScr->checkDirtyCorrectness) {
|
||||||
for (i = 0; i < npixmaps; i++) {
|
for (i = 0; i < npixmaps; i++) {
|
||||||
if (!exaPixmapIsDirty (pixmaps[i].pPix))
|
if (!exaPixmapIsDirty (pixmaps[i].pPix) &&
|
||||||
exaAssertNotDirty (pixmaps[i].pPix);
|
!exaAssertNotDirty (pixmaps[i].pPix))
|
||||||
|
ErrorF("%s: Pixmap %d dirty but not marked as such!\n", __func__, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If anything is pinned in system memory, we won't be able to
|
/* If anything is pinned in system memory, we won't be able to
|
||||||
|
|
|
@ -390,6 +390,7 @@ ExaOffscreenMarkUsed (PixmapPtr pPixmap)
|
||||||
if (area->state == ExaOffscreenRemovable)
|
if (area->state == ExaOffscreenRemovable)
|
||||||
area->score = (area->score * 7) / 8;
|
area->score = (area->score * 7) / 8;
|
||||||
}
|
}
|
||||||
|
iter = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#ifdef RENDER
|
#ifdef RENDER
|
||||||
#include "fbpict.h"
|
#include "fbpict.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "damage.h"
|
||||||
|
|
||||||
#define DEBUG_TRACE_FALL 0
|
#define DEBUG_TRACE_FALL 0
|
||||||
#define DEBUG_MIGRATE 0
|
#define DEBUG_MIGRATE 0
|
||||||
|
@ -168,16 +169,16 @@ typedef struct {
|
||||||
unsigned int fb_size; /**< size of pixmap in framebuffer memory */
|
unsigned int fb_size; /**< size of pixmap in framebuffer memory */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If area is NULL, then dirty == TRUE means that the pixmap has been
|
* The damage record contains the areas of the pixmap's current location
|
||||||
* modified, so the contents are defined. Used to avoid uploads of
|
* (framebuffer or system) that have been damaged compared to the other
|
||||||
* undefined data.
|
* location.
|
||||||
*
|
|
||||||
* If area is non-NULL, then dirty == TRUE means that the pixmap data at
|
|
||||||
* pPixmap->devPrivate.ptr (either fb_ptr or sys_ptr) has been changed
|
|
||||||
* compared to the copy in the other location. This is used to avoid
|
|
||||||
* uploads/downloads of unmodified data.
|
|
||||||
*/
|
*/
|
||||||
Bool dirty;
|
DamagePtr pDamage;
|
||||||
|
/**
|
||||||
|
* The valid region marks the valid bits of a drawable (at least, as it's
|
||||||
|
* derived from damage, which may be overreported).
|
||||||
|
*/
|
||||||
|
RegionRec validReg;
|
||||||
} ExaPixmapPrivRec, *ExaPixmapPrivPtr;
|
} ExaPixmapPrivRec, *ExaPixmapPrivPtr;
|
||||||
|
|
||||||
typedef struct _ExaMigrationRec {
|
typedef struct _ExaMigrationRec {
|
||||||
|
@ -323,7 +324,7 @@ ExaCheckComposite (CARD8 op,
|
||||||
CARD16 height);
|
CARD16 height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* exaoffscreen.c */
|
/* exa_offscreen.c */
|
||||||
void
|
void
|
||||||
ExaOffscreenMarkUsed (PixmapPtr pPixmap);
|
ExaOffscreenMarkUsed (PixmapPtr pPixmap);
|
||||||
|
|
||||||
|
@ -347,7 +348,7 @@ void
|
||||||
exaFinishAccess(DrawablePtr pDrawable, int index);
|
exaFinishAccess(DrawablePtr pDrawable, int index);
|
||||||
|
|
||||||
void
|
void
|
||||||
exaDrawableDirty(DrawablePtr pDrawable);
|
exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2);
|
||||||
|
|
||||||
Bool
|
Bool
|
||||||
exaDrawableIsOffscreen (DrawablePtr pDrawable);
|
exaDrawableIsOffscreen (DrawablePtr pDrawable);
|
||||||
|
|
|
@ -298,12 +298,13 @@ exaTryDriverSolidFill(PicturePtr pSrc,
|
||||||
(*pExaScr->info->Solid) (pDstPix,
|
(*pExaScr->info->Solid) (pDstPix,
|
||||||
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
|
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
|
||||||
pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
|
pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
|
||||||
|
exaDrawableDirty (pDst->pDrawable,
|
||||||
|
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
|
||||||
|
pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
|
||||||
pbox++;
|
pbox++;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*pExaScr->info->DoneSolid) (pDstPix);
|
(*pExaScr->info->DoneSolid) (pDstPix);
|
||||||
exaMarkSync(pDst->pDrawable->pScreen);
|
exaMarkSync(pDst->pDrawable->pScreen);
|
||||||
exaDrawableDirty (pDst->pDrawable);
|
|
||||||
|
|
||||||
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
|
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -437,12 +438,13 @@ exaTryDriverComposite(CARD8 op,
|
||||||
pbox->y1 + dst_off_y,
|
pbox->y1 + dst_off_y,
|
||||||
pbox->x2 - pbox->x1,
|
pbox->x2 - pbox->x1,
|
||||||
pbox->y2 - pbox->y1);
|
pbox->y2 - pbox->y1);
|
||||||
|
exaDrawableDirty (pDst->pDrawable,
|
||||||
|
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
|
||||||
|
pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
|
||||||
pbox++;
|
pbox++;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*pExaScr->info->DoneComposite) (pDstPix);
|
(*pExaScr->info->DoneComposite) (pDstPix);
|
||||||
exaMarkSync(pDst->pDrawable->pScreen);
|
exaMarkSync(pDst->pDrawable->pScreen);
|
||||||
exaDrawableDirty (pDst->pDrawable);
|
|
||||||
|
|
||||||
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
|
REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -648,6 +650,8 @@ exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap,
|
||||||
|
|
||||||
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
||||||
fbRasterizeTrapezoid(pPicture, trap, x_off, y_off);
|
fbRasterizeTrapezoid(pPicture, trap, x_off, y_off);
|
||||||
|
exaDrawableDirty(pPicture->pDrawable, 0, 0,
|
||||||
|
pPicture->pDrawable->width, pPicture->pDrawable->height);
|
||||||
exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,6 +673,8 @@ exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri,
|
||||||
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
||||||
fbAddTriangles(pPicture, x_off, y_off, ntri, tris);
|
fbAddTriangles(pPicture, x_off, y_off, ntri, tris);
|
||||||
exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
||||||
|
exaDrawableDirty(pPicture->pDrawable, 0, 0,
|
||||||
|
pPicture->pDrawable->width, pPicture->pDrawable->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -958,7 +964,8 @@ exaGlyphs (CARD8 op,
|
||||||
exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC,
|
exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC,
|
||||||
0, 0, glyph->info.width, glyph->info.height, 0, 0);
|
0, 0, glyph->info.width, glyph->info.height, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
exaDrawableDirty (&pPixmap->drawable);
|
exaDrawableDirty (&pPixmap->drawable, 0, 0,
|
||||||
|
glyph->info.width, glyph->info.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maskFormat)
|
if (maskFormat)
|
||||||
|
|
|
@ -23,6 +23,26 @@
|
||||||
|
|
||||||
#include "exa_priv.h"
|
#include "exa_priv.h"
|
||||||
|
|
||||||
|
#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
|
||||||
|
BoxPtr extents = &pGC->pCompositeClip->extents;\
|
||||||
|
if(box.x1 < extents->x1) box.x1 = extents->x1; \
|
||||||
|
if(box.x2 > extents->x2) box.x2 = extents->x2; \
|
||||||
|
if(box.y1 < extents->y1) box.y1 = extents->y1; \
|
||||||
|
if(box.y2 > extents->y2) box.y2 = extents->y2; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TRANSLATE_BOX(box, pDrawable) { \
|
||||||
|
box.x1 += pDrawable->x; \
|
||||||
|
box.x2 += pDrawable->x; \
|
||||||
|
box.y1 += pDrawable->y; \
|
||||||
|
box.y2 += pDrawable->y; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
|
||||||
|
TRANSLATE_BOX(box, pDrawable); \
|
||||||
|
TRIM_BOX(box, pGC); \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions wrap the low-level fb rendering functions and
|
* These functions wrap the low-level fb rendering functions and
|
||||||
* synchronize framebuffer/accelerated drawing by stalling until
|
* synchronize framebuffer/accelerated drawing by stalling until
|
||||||
|
@ -200,11 +220,35 @@ ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
|
||||||
int nrect, xRectangle *prect)
|
int nrect, xRectangle *prect)
|
||||||
{
|
{
|
||||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||||
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
|
|
||||||
exaPrepareAccessGC (pGC);
|
if (nrect) {
|
||||||
fbPolyFillRect (pDrawable, pGC, nrect, prect);
|
BoxRec box = { .x1 = max(prect->x,0),
|
||||||
exaFinishAccessGC (pGC);
|
.x2 = min(prect->x + prect->width,pDrawable->width),
|
||||||
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
|
.y1 = max(prect->y,0),
|
||||||
|
.y2 = min(prect->y + prect->height,pDrawable->height) };
|
||||||
|
|
||||||
|
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
|
||||||
|
exaPrepareAccessGC (pGC);
|
||||||
|
fbPolyFillRect (pDrawable, pGC, nrect, prect);
|
||||||
|
exaFinishAccessGC (pGC);
|
||||||
|
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
|
||||||
|
|
||||||
|
/* Only track bounding box of damage, as this path can degenerate to
|
||||||
|
* zillions of damage boxes
|
||||||
|
*/
|
||||||
|
while (--nrect)
|
||||||
|
{
|
||||||
|
prect++;
|
||||||
|
box.x1 = min(box.x1, prect->x);
|
||||||
|
box.x2 = max(box.x2, prect->x + prect->width);
|
||||||
|
box.y1 = min(box.y1, prect->y);
|
||||||
|
box.y2 = max(box.y2, prect->y + prect->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
|
||||||
|
|
||||||
|
exaDrawableDirty (pDrawable, box.x1, box.x2, box.y1, box.y2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue