Merge branch 'exa-damagetrack'

This commit is contained in:
Eric Anholt 2006-12-27 16:11:31 -08:00
commit 683ca3f7af
10 changed files with 500 additions and 199 deletions

128
exa/exa.c
View File

@ -121,18 +121,78 @@ exaGetDrawablePixmap(DrawablePtr pDrawable)
return (PixmapPtr) pDrawable; return (PixmapPtr) pDrawable;
} }
/**
* Sets the offsets to add to coordinates to make them address the same bits in
* the backing drawable. These coordinates are nonzero only for redirected
* windows.
*/
static void
exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
int *xp, int *yp)
{
#ifdef COMPOSITE
if (pDrawable->type == DRAWABLE_WINDOW) {
*xp = -pPixmap->screen_x;
*yp = -pPixmap->screen_y;
return;
}
#endif
*xp = 0;
*yp = 0;
}
/**
* exaPixmapDirty() marks a pixmap as dirty, allowing for
* optimizations in pixmap migration when no changes have occurred.
*/
void
exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
{
ExaPixmapPriv(pPix);
BoxRec box;
RegionPtr pDamageReg;
RegionRec region;
if (!pExaPixmap)
return;
box.x1 = max(x1, 0);
box.y1 = max(y1, 0);
box.x2 = min(x2, pPix->drawable.width);
box.y2 = min(y2, pPix->drawable.height);
if (box.x1 >= box.x2 || box.y1 >= box.y2)
return;
pDamageReg = DamageRegion(pExaPixmap->pDamage);
REGION_INIT(pScreen, &region, &box, 1);
REGION_UNION(pScreen, pDamageReg, pDamageReg, &region);
REGION_UNINIT(pScreen, &region);
}
/** /**
* exaDrawableDirty() marks a pixmap backing a drawable as dirty, allowing for * exaDrawableDirty() marks a pixmap backing a drawable as dirty, allowing for
* 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; PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);
int xoff, yoff;
pExaPixmap = ExaGetPixmapPriv(exaGetDrawablePixmap (pDrawable)); x1 = max(x1, pDrawable->x);
if (pExaPixmap != NULL) y1 = max(y1, pDrawable->y);
pExaPixmap->dirty = TRUE; x2 = min(x2, pDrawable->x + pDrawable->width);
y2 = min(y2, pDrawable->y + pDrawable->height);
if (x1 >= x2 || y1 >= y2)
return;
exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff);
} }
static Bool static Bool
@ -153,6 +213,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);
} }
@ -220,7 +281,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;
} }
@ -265,32 +339,14 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable)
/** /**
* Returns the pixmap which backs a drawable, and the offsets to add to * Returns the pixmap which backs a drawable, and the offsets to add to
* coordinates to make them address the same bits in the backing drawable. * coordinates to make them address the same bits in the backing drawable.
* These coordinates are nonzero only for redirected windows.
*/ */
PixmapPtr PixmapPtr
exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
{ {
PixmapPtr pPixmap; PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
int x, y;
exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp);
if (pDrawable->type == DRAWABLE_WINDOW) {
pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable);
#ifdef COMPOSITE
x = -pPixmap->screen_x;
y = -pPixmap->screen_y;
#else
x = 0;
y = 0;
#endif
}
else
{
pPixmap = (PixmapPtr) pDrawable;
x = 0;
y = 0;
}
*xp = x;
*yp = y;
if (exaPixmapIsOffscreen (pPixmap)) if (exaPixmapIsOffscreen (pPixmap))
return pPixmap; return pPixmap;
else else
@ -338,8 +394,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)
@ -349,9 +404,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);
@ -377,7 +429,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
@ -408,6 +460,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);
exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height);
exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
} }
if (pNewTile) if (pNewTile)
@ -423,9 +476,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); exaPixmapDirty(pGC->tile.pixmap, 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.

View File

@ -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,8 @@ 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);
exaPixmapDirty (pPixmap, fullX1 + off_x, fullY1 + off_y,
fullX2 + off_x, fullY1 + 1 + off_y);
} }
else else
{ {
@ -118,17 +125,19 @@ 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);
exaPixmapDirty (pPixmap, 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 +231,8 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
exaFinishAccess(pDrawable, EXA_PREPARE_DEST); exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
} }
exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff);
} }
exaDrawableDirty(pDrawable);
return; return;
@ -351,11 +360,12 @@ 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);
} }
exaPixmapDirty(pDstPixmap, 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;
} }
@ -424,11 +434,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);
exaPixmapDirty (pDstPixmap,
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;
} }
@ -443,6 +455,11 @@ 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, pbox->y1, pbox->x2, pbox->y2);
pbox++;
}
} }
RegionPtr RegionPtr
@ -682,6 +699,8 @@ 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);
exaPixmapDirty (pPixmap, fullX1 + xoff, fullY1 + yoff,
fullX2 + xoff, fullY2 + yoff);
} }
else else
{ {
@ -707,15 +726,17 @@ 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);
exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff,
partX2 + xoff, partY2 + yoff);
}
} }
} }
} }
(*pExaScr->info->DoneSolid) (pPixmap); (*pExaScr->info->DoneSolid) (pPixmap);
exaDrawableDirty (pDrawable);
exaMarkSync(pDrawable->pScreen); exaMarkSync(pDrawable->pScreen);
} }
@ -736,11 +757,12 @@ 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 = pPixmap = exaGetDrawablePixmap (pDrawable); pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
if (pExaScr->swappedOut || if (pExaScr->swappedOut ||
pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY) pPixmap->drawable.height > pExaScr->info->maxY)
@ -751,19 +773,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--;
@ -791,12 +815,20 @@ 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);
exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff,
partX2 + xoff, partY2 + yoff);
} else
exaDrawableDirty (pDrawable, partX1, partY1, partX2, partY2);
} }
if (fallback)
return;
(*pExaScr->info->DoneSolid) (pPixmap); (*pExaScr->info->DoneSolid) (pPixmap);
exaDrawableDirty (pDrawable);
exaMarkSync(pDrawable->pScreen); exaMarkSync(pDrawable->pScreen);
} }
@ -909,12 +941,17 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
pPriv->fg, pPriv->fg,
gx + dstXoff, gx + dstXoff,
gHeight); gHeight);
exaDrawableDirty (pDrawable, gx, gy, gx + gWidth, gy + gHeight);
} }
else else
{ {
RegionPtr pClip = fbGetCompositeClip(pGC);
int nbox;
BoxPtr pbox;
gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
fbPutXYImage (pDrawable, fbPutXYImage (pDrawable,
fbGetCompositeClip(pGC), pClip,
pPriv->fg, pPriv->fg,
pPriv->bg, pPriv->bg,
pPriv->pm, pPriv->pm,
@ -928,6 +965,18 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
(FbStip *) pglyph, (FbStip *) pglyph,
gStride, gStride,
0); 0);
for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
nbox--; pbox++) {
int x1 = max(gx, pbox->x1), x2 = min(gx + gWidth, pbox->x2);
int y1 = max(gy, pbox->y1), y2 = min(gy + gHeight, pbox->y2);
if (x1 >= x2 || y1 >= y2)
continue;
exaDrawableDirty (pDrawable, gx, gy, gx + gWidth,
gy + gHeight);
}
} }
} }
x += pci->metrics.characterWidth; x += pci->metrics.characterWidth;
@ -995,6 +1044,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;
@ -1012,19 +1063,17 @@ 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);
exaPixmapDirty (pPixmap, 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
{ {
@ -1035,6 +1084,11 @@ 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, pBox->y1, pBox->x2, pBox->y2);
pBox++;
}
} }
} }
@ -1048,9 +1102,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;
@ -1082,18 +1138,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;
@ -1119,7 +1173,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;
@ -1128,11 +1182,12 @@ 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);
exaDrawableDirty (pDrawable);
return; return;
} }
@ -1145,6 +1200,11 @@ 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, pBox->y1, pBox->x2, pBox->y2);
pBox++;
}
} }
void void

View File

@ -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,32 +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);
dst += dst_pitch; pBox->y1 = max(pBox->y1, 0);
src += src_pitch; 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;
} }
/** /**
@ -462,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

View File

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

View File

@ -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
@ -160,16 +161,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 {
@ -315,7 +316,7 @@ ExaCheckComposite (CARD8 op,
CARD16 height); CARD16 height);
#endif #endif
/* exaoffscreen.c */ /* exa_offscreen.c */
void void
ExaOffscreenMarkUsed (PixmapPtr pPixmap); ExaOffscreenMarkUsed (PixmapPtr pPixmap);
@ -339,7 +340,10 @@ void
exaFinishAccess(DrawablePtr pDrawable, int index); exaFinishAccess(DrawablePtr pDrawable, int index);
void void
exaDrawableDirty(DrawablePtr pDrawable); exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2);
void
exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2);
Bool Bool
exaDrawableIsOffscreen (DrawablePtr pDrawable); exaDrawableIsOffscreen (DrawablePtr pDrawable);

View File

@ -302,12 +302,12 @@ 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);
exaPixmapDirty (pDstPix, 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, &region); REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return 1; return 1;
@ -446,12 +446,12 @@ 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);
exaPixmapDirty (pDstPix, 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, &region); REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return 1; return 1;
@ -710,16 +710,19 @@ void
exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap,
int x_off, int y_off) int x_off, int y_off)
{ {
DrawablePtr pDraw = pPicture->pDrawable;
ExaMigrationRec pixmaps[1]; ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = TRUE; pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = TRUE; pixmaps[0].as_src = TRUE;
pixmaps[0].pPix = exaGetDrawablePixmap (pPicture->pDrawable); pixmaps[0].pPix = exaGetDrawablePixmap (pDraw);
exaDoMigration(pixmaps, 1, FALSE); exaDoMigration(pixmaps, 1, FALSE);
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
fbRasterizeTrapezoid(pPicture, trap, x_off, y_off); fbRasterizeTrapezoid(pPicture, trap, x_off, y_off);
exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); exaDrawableDirty(pDraw, pDraw->x, pDraw->y,
pDraw->x + pDraw->width, pDraw->y + pDraw->height);
exaFinishAccess(pDraw, EXA_PREPARE_DEST);
} }
/** /**
@ -730,16 +733,19 @@ void
exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri,
xTriangle *tris) xTriangle *tris)
{ {
DrawablePtr pDraw = pPicture->pDrawable;
ExaMigrationRec pixmaps[1]; ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = TRUE; pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = TRUE; pixmaps[0].as_src = TRUE;
pixmaps[0].pPix = exaGetDrawablePixmap (pPicture->pDrawable); pixmaps[0].pPix = exaGetDrawablePixmap (pDraw);
exaDoMigration(pixmaps, 1, FALSE); exaDoMigration(pixmaps, 1, FALSE);
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); exaPrepareAccess(pDraw, 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); exaDrawableDirty(pDraw, pDraw->x, pDraw->y,
pDraw->x + pDraw->width, pDraw->y + pDraw->height);
exaFinishAccess(pDraw, EXA_PREPARE_DEST);
} }
/** /**
@ -1028,10 +1034,11 @@ 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 {
exaDrawableDirty (&pPixmap->drawable);
} }
exaPixmapDirty (pPixmap, 0, 0,
glyph->info.width, glyph->info.height);
if (maskFormat) if (maskFormat)
{ {
exaComposite (PictOpAdd, pPicture, NULL, pMask, 0, 0, 0, 0, exaComposite (PictOpAdd, pPicture, NULL, pMask, 0, 0, 0, 0,

View File

@ -200,11 +200,33 @@ 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); int x1 = max(prect->x, 0), y1 = max(prect->y, 0);
exaFinishAccessGC (pGC); int x2 = min(prect->x + prect->width, pDrawable->width);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST); int 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++;
x1 = min(x1, prect->x);
x2 = max(x2, prect->x + prect->width);
y1 = min(y1, prect->y);
y2 = max(y2, prect->y + prect->height);
}
exaDrawableDirty (pDrawable, pDrawable->x + x1, pDrawable->y + y1,
pDrawable->x + x2, pDrawable->y + y2);
}
} }
void void

View File

@ -113,6 +113,52 @@ getDrawableDamageRef (DrawablePtr pDrawable)
DamagePtr *pPrev = (DamagePtr *) \ DamagePtr *pPrev = (DamagePtr *) \
&(pWindow->devPrivates[damageWinPrivateIndex].ptr) &(pWindow->devPrivates[damageWinPrivateIndex].ptr)
static void
DamageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion)
{
BoxRec tmpBox;
RegionRec tmpRegion;
Bool was_empty;
switch (pDamage->damageLevel) {
case DamageReportRawRegion:
(*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure);
break;
case DamageReportDeltaRegion:
REGION_NULL (pScreen, &tmpRegion);
REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage);
if (REGION_NOTEMPTY (pScreen, &tmpRegion)) {
REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
pDamageRegion);
(*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure);
}
REGION_UNINIT(pScreen, &tmpRegion);
break;
case DamageReportBoundingBox:
tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage);
REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
pDamageRegion);
if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) {
(*pDamage->damageReport) (pDamage, &pDamage->damage,
pDamage->closure);
}
break;
case DamageReportNonEmpty:
was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage);
REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
pDamageRegion);
if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) {
(*pDamage->damageReport) (pDamage, &pDamage->damage,
pDamage->closure);
}
break;
case DamageReportNone:
REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
pDamageRegion);
break;
}
}
#if DAMAGE_DEBUG_ENABLE #if DAMAGE_DEBUG_ENABLE
static void static void
_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) _damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where)
@ -130,9 +176,6 @@ damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
RegionRec clippedRec; RegionRec clippedRec;
RegionPtr pDamageRegion; RegionPtr pDamageRegion;
RegionRec pixClip; RegionRec pixClip;
Bool was_empty;
RegionRec tmpRegion;
BoxRec tmpBox;
int draw_x, draw_y; int draw_x, draw_y;
#ifdef COMPOSITE #ifdef COMPOSITE
int screen_x = 0, screen_y = 0; int screen_x = 0, screen_y = 0;
@ -256,41 +299,18 @@ damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
*/ */
if (draw_x || draw_y) if (draw_x || draw_y)
REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y);
switch (pDamage->damageLevel) { /* If the damage rec has been flagged to report damage after the op has
case DamageReportRawRegion: * completed, then union it into the delayed damage region, which will
(*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); * be used for reporting after calling down, and skip the reporting
break; */
case DamageReportDeltaRegion: if (!pDamage->reportAfter) {
REGION_NULL (pScreen, &tmpRegion); DamageReportDamage (pDamage, pDamageRegion);
REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage); } else {
if (REGION_NOTEMPTY (pScreen, &tmpRegion)) REGION_UNION(pScreen, &pDamage->pendingDamage,
{ &pDamage->pendingDamage, pDamageRegion);
REGION_UNION(pScreen, &pDamage->damage,
&pDamage->damage, pDamageRegion);
(*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure);
}
REGION_UNINIT(pScreen, &tmpRegion);
break;
case DamageReportBoundingBox:
tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage);
REGION_UNION(pScreen, &pDamage->damage,
&pDamage->damage, pDamageRegion);
if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage)))
(*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure);
break;
case DamageReportNonEmpty:
was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage);
REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
pDamageRegion);
if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage))
(*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure);
break;
case DamageReportNone:
REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
pDamageRegion);
break;
} }
/* /*
* translate original region back * translate original region back
*/ */
@ -305,6 +325,21 @@ damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
REGION_UNINIT (pScreen, &clippedRec); REGION_UNINIT (pScreen, &clippedRec);
} }
static void
damageReportPostOp (DrawablePtr pDrawable)
{
drawableDamage(pDrawable);
for (; pDamage != NULL; pDamage = pDamage->pNext)
{
if (pDamage->reportAfter) {
DamageReportDamage (pDamage, &pDamage->pendingDamage);
REGION_EMPTY (pScreen, &pDamage->pendingDamage);
}
}
}
#if DAMAGE_DEBUG_ENABLE #if DAMAGE_DEBUG_ENABLE
#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) #define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
static void static void
@ -550,6 +585,7 @@ damageComposite (CARD8 op,
yDst, yDst,
width, width,
height); height);
damageReportPostOp (pDst->pDrawable);
wrap (pScrPriv, ps, Composite, damageComposite); wrap (pScrPriv, ps, Composite, damageComposite);
} }
@ -616,6 +652,7 @@ damageGlyphs (CARD8 op,
} }
unwrap (pScrPriv, ps, Glyphs); unwrap (pScrPriv, ps, Glyphs);
(*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
damageReportPostOp (pDst->pDrawable);
wrap (pScrPriv, ps, Glyphs, damageGlyphs); wrap (pScrPriv, ps, Glyphs, damageGlyphs);
} }
#endif #endif
@ -668,6 +705,7 @@ damageFillSpans(DrawablePtr pDrawable,
(*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -715,6 +753,7 @@ damageSetSpans(DrawablePtr pDrawable,
damageDamageBox (pDrawable, &box, pGC->subWindowMode); damageDamageBox (pDrawable, &box, pGC->subWindowMode);
} }
(*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -746,6 +785,7 @@ damagePutImage(DrawablePtr pDrawable,
} }
(*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
leftPad, format, pImage); leftPad, format, pImage);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -789,6 +829,7 @@ damageCopyArea(DrawablePtr pSrc,
ret = (*pGC->ops->CopyArea)(pSrc, pDst, ret = (*pGC->ops->CopyArea)(pSrc, pDst,
pGC, srcx, srcy, width, height, dstx, dsty); pGC, srcx, srcy, width, height, dstx, dsty);
damageReportPostOp (pDst);
DAMAGE_GC_OP_EPILOGUE(pGC, pDst); DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
return ret; return ret;
} }
@ -834,6 +875,7 @@ damageCopyPlane(DrawablePtr pSrc,
ret = (*pGC->ops->CopyPlane)(pSrc, pDst, ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
damageReportPostOp (pDst);
DAMAGE_GC_OP_EPILOGUE(pGC, pDst); DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
return ret; return ret;
} }
@ -875,6 +917,7 @@ damagePolyPoint(DrawablePtr pDrawable,
damageDamageBox (pDrawable, &box, pGC->subWindowMode); damageDamageBox (pDrawable, &box, pGC->subWindowMode);
} }
(*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -948,6 +991,7 @@ damagePolylines(DrawablePtr pDrawable,
damageDamageBox (pDrawable, &box, pGC->subWindowMode); damageDamageBox (pDrawable, &box, pGC->subWindowMode);
} }
(*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1026,6 +1070,7 @@ damagePolySegment(DrawablePtr pDrawable,
damageDamageBox (pDrawable, &box, pGC->subWindowMode); damageDamageBox (pDrawable, &box, pGC->subWindowMode);
} }
(*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1087,6 +1132,7 @@ damagePolyRectangle(DrawablePtr pDrawable,
} }
} }
(*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1139,6 +1185,7 @@ damagePolyArc(DrawablePtr pDrawable,
damageDamageBox (pDrawable, &box, pGC->subWindowMode); damageDamageBox (pDrawable, &box, pGC->subWindowMode);
} }
(*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1197,6 +1244,7 @@ damageFillPolygon(DrawablePtr pDrawable,
} }
(*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1235,6 +1283,7 @@ damagePolyFillRect(DrawablePtr pDrawable,
damageDamageBox (pDrawable, &box, pGC->subWindowMode); damageDamageBox (pDrawable, &box, pGC->subWindowMode);
} }
(*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1276,6 +1325,7 @@ damagePolyFillArc(DrawablePtr pDrawable,
damageDamageBox (pDrawable, &box, pGC->subWindowMode); damageDamageBox (pDrawable, &box, pGC->subWindowMode);
} }
(*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1386,6 +1436,7 @@ damagePolyText8(DrawablePtr pDrawable,
Linear8Bit, TT_POLY8); Linear8Bit, TT_POLY8);
else else
x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
return x; return x;
} }
@ -1406,6 +1457,7 @@ damagePolyText16(DrawablePtr pDrawable,
TT_POLY16); TT_POLY16);
else else
x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
return x; return x;
} }
@ -1425,6 +1477,7 @@ damageImageText8(DrawablePtr pDrawable,
Linear8Bit, TT_IMAGE8); Linear8Bit, TT_IMAGE8);
else else
(*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1444,6 +1497,7 @@ damageImageText16(DrawablePtr pDrawable,
TT_IMAGE16); TT_IMAGE16);
else else
(*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1462,6 +1516,7 @@ damageImageGlyphBlt(DrawablePtr pDrawable,
nglyph, ppci, TRUE, pGC->subWindowMode); nglyph, ppci, TRUE, pGC->subWindowMode);
(*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph,
ppci, pglyphBase); ppci, pglyphBase);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1479,6 +1534,7 @@ damagePolyGlyphBlt(DrawablePtr pDrawable,
nglyph, ppci, FALSE, pGC->subWindowMode); nglyph, ppci, FALSE, pGC->subWindowMode);
(*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
ppci, pglyphBase); ppci, pglyphBase);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1512,6 +1568,7 @@ damagePushPixels(GCPtr pGC,
damageDamageBox (pDrawable, &box, pGC->subWindowMode); damageDamageBox (pDrawable, &box, pGC->subWindowMode);
} }
(*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
damageReportPostOp (pDrawable);
DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
} }
@ -1591,10 +1648,12 @@ damagePaintWindow(WindowPtr pWindow,
if(what == PW_BACKGROUND) { if(what == PW_BACKGROUND) {
unwrap (pScrPriv, pScreen, PaintWindowBackground); unwrap (pScrPriv, pScreen, PaintWindowBackground);
(*pScreen->PaintWindowBackground) (pWindow, prgn, what); (*pScreen->PaintWindowBackground) (pWindow, prgn, what);
damageReportPostOp (&pWindow->drawable);
wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow);
} else { } else {
unwrap (pScrPriv, pScreen, PaintWindowBorder); unwrap (pScrPriv, pScreen, PaintWindowBorder);
(*pScreen->PaintWindowBorder) (pWindow, prgn, what); (*pScreen->PaintWindowBorder) (pWindow, prgn, what);
damageReportPostOp (&pWindow->drawable);
wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow);
} }
} }
@ -1623,6 +1682,7 @@ damageCopyWindow(WindowPtr pWindow,
} }
unwrap (pScrPriv, pScreen, CopyWindow); unwrap (pScrPriv, pScreen, CopyWindow);
(*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
damageReportPostOp (&pWindow->drawable);
wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
} }
@ -1654,6 +1714,7 @@ damageRestoreAreas (PixmapPtr pPixmap,
unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
(*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn, (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn,
xorg, yorg, pWindow); xorg, yorg, pWindow);
damageReportPostOp (&pWindow->drawable);
wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
damageRestoreAreas); damageRestoreAreas);
} }
@ -1820,12 +1881,14 @@ DamageCreate (DamageReportFunc damageReport,
pDamage->pNext = 0; pDamage->pNext = 0;
pDamage->pNextWin = 0; pDamage->pNextWin = 0;
REGION_NULL(pScreen, &pDamage->damage); REGION_NULL(pScreen, &pDamage->damage);
REGION_NULL(pScreen, &pDamage->pendingDamage);
pDamage->damageLevel = damageLevel; pDamage->damageLevel = damageLevel;
pDamage->isInternal = isInternal; pDamage->isInternal = isInternal;
pDamage->closure = closure; pDamage->closure = closure;
pDamage->isWindow = FALSE; pDamage->isWindow = FALSE;
pDamage->pDrawable = 0; pDamage->pDrawable = 0;
pDamage->reportAfter = FALSE;
pDamage->damageReport = damageReport; pDamage->damageReport = damageReport;
pDamage->damageDestroy = damageDestroy; pDamage->damageDestroy = damageDestroy;
@ -1909,6 +1972,7 @@ DamageDestroy (DamagePtr pDamage)
if (pDamage->damageDestroy) if (pDamage->damageDestroy)
(*pDamage->damageDestroy) (pDamage, pDamage->closure); (*pDamage->damageDestroy) (pDamage, pDamage->closure);
REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage); REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage);
REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->pendingDamage);
xfree (pDamage); xfree (pDamage);
} }
@ -1962,4 +2026,16 @@ DamageDamageRegion (DrawablePtr pDrawable,
RegionPtr pRegion) RegionPtr pRegion)
{ {
damageDamageRegion (pDrawable, pRegion, FALSE, -1); damageDamageRegion (pDrawable, pRegion, FALSE, -1);
/* Go back and report this damage for DamagePtrs with reportAfter set, since
* this call isn't part of an in-progress drawing op in the call chain and
* the DDX probably just wants to know about it right away.
*/
damageReportPostOp (pDrawable);
}
void
DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter)
{
pDamage->reportAfter = reportAfter;
} }

View File

@ -81,4 +81,7 @@ void
DamageDamageRegion (DrawablePtr pDrawable, DamageDamageRegion (DrawablePtr pDrawable,
const RegionPtr pRegion); const RegionPtr pRegion);
void
DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter);
#endif /* _DAMAGE_H_ */ #endif /* _DAMAGE_H_ */

View File

@ -48,6 +48,9 @@ typedef struct _damage {
DamageReportFunc damageReport; DamageReportFunc damageReport;
DamageDestroyFunc damageDestroy; DamageDestroyFunc damageDestroy;
Bool reportAfter;
RegionRec pendingDamage;
} DamageRec; } DamageRec;
typedef struct _damageScrPriv { typedef struct _damageScrPriv {