From 6060b612de6b41f872d034c6130770c1d189d0a3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 12 Jun 2006 20:12:31 +0200 Subject: [PATCH 1/5] Provide option to report damage after operation is complete. --- miext/damage/damage.c | 150 +++++++++++++++++++++++++++++---------- miext/damage/damage.h | 3 + miext/damage/damagestr.h | 3 + 3 files changed, 119 insertions(+), 37 deletions(-) diff --git a/miext/damage/damage.c b/miext/damage/damage.c index ef7bca455..5b9402898 100755 --- a/miext/damage/damage.c +++ b/miext/damage/damage.c @@ -113,6 +113,52 @@ getDrawableDamageRef (DrawablePtr pDrawable) DamagePtr *pPrev = (DamagePtr *) \ &(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 static void _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; RegionPtr pDamageRegion; RegionRec pixClip; - Bool was_empty; - RegionRec tmpRegion; - BoxRec tmpBox; int draw_x, draw_y; #ifdef COMPOSITE int screen_x = 0, screen_y = 0; @@ -256,41 +299,18 @@ damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, */ if (draw_x || draw_y) REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); - - 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 the damage rec has been flagged to report damage after the op has + * completed, then union it into the delayed damage region, which will + * be used for reporting after calling down, and skip the reporting + */ + if (!pDamage->reportAfter) { + DamageReportDamage (pDamage, pDamageRegion); + } else { + REGION_UNION(pScreen, &pDamage->pendingDamage, + &pDamage->pendingDamage, pDamageRegion); } + /* * translate original region back */ @@ -305,6 +325,21 @@ damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, 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 #define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) static void @@ -550,6 +585,7 @@ damageComposite (CARD8 op, yDst, width, height); + damageReportPostOp (pDst->pDrawable); wrap (pScrPriv, ps, Composite, damageComposite); } @@ -616,6 +652,7 @@ damageGlyphs (CARD8 op, } unwrap (pScrPriv, ps, Glyphs); (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + damageReportPostOp (pDst->pDrawable); wrap (pScrPriv, ps, Glyphs, damageGlyphs); } #endif @@ -668,6 +705,7 @@ damageFillSpans(DrawablePtr pDrawable, (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -715,6 +753,7 @@ damageSetSpans(DrawablePtr pDrawable, damageDamageBox (pDrawable, &box, pGC->subWindowMode); } (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -746,6 +785,7 @@ damagePutImage(DrawablePtr pDrawable, } (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pImage); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -789,6 +829,7 @@ damageCopyArea(DrawablePtr pSrc, ret = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, srcx, srcy, width, height, dstx, dsty); + damageReportPostOp (pDst); DAMAGE_GC_OP_EPILOGUE(pGC, pDst); return ret; } @@ -834,6 +875,7 @@ damageCopyPlane(DrawablePtr pSrc, ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + damageReportPostOp (pDst); DAMAGE_GC_OP_EPILOGUE(pGC, pDst); return ret; } @@ -875,6 +917,7 @@ damagePolyPoint(DrawablePtr pDrawable, damageDamageBox (pDrawable, &box, pGC->subWindowMode); } (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -948,6 +991,7 @@ damagePolylines(DrawablePtr pDrawable, damageDamageBox (pDrawable, &box, pGC->subWindowMode); } (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1026,6 +1070,7 @@ damagePolySegment(DrawablePtr pDrawable, damageDamageBox (pDrawable, &box, pGC->subWindowMode); } (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1087,6 +1132,7 @@ damagePolyRectangle(DrawablePtr pDrawable, } } (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1139,6 +1185,7 @@ damagePolyArc(DrawablePtr pDrawable, damageDamageBox (pDrawable, &box, pGC->subWindowMode); } (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1197,6 +1244,7 @@ damageFillPolygon(DrawablePtr pDrawable, } (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1235,6 +1283,7 @@ damagePolyFillRect(DrawablePtr pDrawable, damageDamageBox (pDrawable, &box, pGC->subWindowMode); } (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1276,6 +1325,7 @@ damagePolyFillArc(DrawablePtr pDrawable, damageDamageBox (pDrawable, &box, pGC->subWindowMode); } (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1386,6 +1436,7 @@ damagePolyText8(DrawablePtr pDrawable, Linear8Bit, TT_POLY8); else x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); return x; } @@ -1406,6 +1457,7 @@ damagePolyText16(DrawablePtr pDrawable, TT_POLY16); else x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); return x; } @@ -1425,6 +1477,7 @@ damageImageText8(DrawablePtr pDrawable, Linear8Bit, TT_IMAGE8); else (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1444,6 +1497,7 @@ damageImageText16(DrawablePtr pDrawable, TT_IMAGE16); else (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1462,6 +1516,7 @@ damageImageGlyphBlt(DrawablePtr pDrawable, nglyph, ppci, TRUE, pGC->subWindowMode); (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1479,6 +1534,7 @@ damagePolyGlyphBlt(DrawablePtr pDrawable, nglyph, ppci, FALSE, pGC->subWindowMode); (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1512,6 +1568,7 @@ damagePushPixels(GCPtr pGC, damageDamageBox (pDrawable, &box, pGC->subWindowMode); } (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); + damageReportPostOp (pDrawable); DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); } @@ -1591,10 +1648,12 @@ damagePaintWindow(WindowPtr pWindow, if(what == PW_BACKGROUND) { unwrap (pScrPriv, pScreen, PaintWindowBackground); (*pScreen->PaintWindowBackground) (pWindow, prgn, what); + damageReportPostOp (&pWindow->drawable); wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); } else { unwrap (pScrPriv, pScreen, PaintWindowBorder); (*pScreen->PaintWindowBorder) (pWindow, prgn, what); + damageReportPostOp (&pWindow->drawable); wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); } } @@ -1623,6 +1682,7 @@ damageCopyWindow(WindowPtr pWindow, } unwrap (pScrPriv, pScreen, CopyWindow); (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + damageReportPostOp (&pWindow->drawable); wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); } @@ -1654,6 +1714,7 @@ damageRestoreAreas (PixmapPtr pPixmap, unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn, xorg, yorg, pWindow); + damageReportPostOp (&pWindow->drawable); wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, damageRestoreAreas); } @@ -1822,12 +1883,14 @@ DamageCreate (DamageReportFunc damageReport, pDamage->pNext = 0; pDamage->pNextWin = 0; REGION_NULL(pScreen, &pDamage->damage); + REGION_NULL(pScreen, &pDamage->pendingDamage); pDamage->damageLevel = damageLevel; pDamage->isInternal = isInternal; pDamage->closure = closure; pDamage->isWindow = FALSE; pDamage->pDrawable = 0; + pDamage->reportAfter = FALSE; pDamage->damageReport = damageReport; pDamage->damageDestroy = damageDestroy; @@ -1911,6 +1974,7 @@ DamageDestroy (DamagePtr pDamage) if (pDamage->damageDestroy) (*pDamage->damageDestroy) (pDamage, pDamage->closure); REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage); + REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->pendingDamage); xfree (pDamage); } @@ -1964,4 +2028,16 @@ DamageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion) { 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; } diff --git a/miext/damage/damage.h b/miext/damage/damage.h index c760f6bef..36a06545f 100755 --- a/miext/damage/damage.h +++ b/miext/damage/damage.h @@ -81,4 +81,7 @@ void DamageDamageRegion (DrawablePtr pDrawable, const RegionPtr pRegion); +void +DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter); + #endif /* _DAMAGE_H_ */ diff --git a/miext/damage/damagestr.h b/miext/damage/damagestr.h index 0fe9e0ad7..93e213fd1 100755 --- a/miext/damage/damagestr.h +++ b/miext/damage/damagestr.h @@ -48,6 +48,9 @@ typedef struct _damage { DamageReportFunc damageReport; DamageDestroyFunc damageDestroy; + + Bool reportAfter; + RegionRec pendingDamage; } DamageRec; typedef struct _damageScrPriv { From f9f33b72e34eaeccea2a20f4a3dd68c2dbefc90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Mon, 12 Jun 2006 20:19:11 +0200 Subject: [PATCH 2/5] Track per-drawable damage to minimize UTS and DFS transfers. Based on work by Eric Anholt. --- exa/exa.c | 49 +++++++--- exa/exa_accel.c | 111 +++++++++++++++++------ exa/exa_migration.c | 211 +++++++++++++++++++++++++++++--------------- exa/exa_offscreen.c | 1 + exa/exa_priv.h | 23 ++--- exa/exa_render.c | 17 ++-- exa/exa_unaccel.c | 54 ++++++++++-- 7 files changed, 337 insertions(+), 129 deletions(-) diff --git a/exa/exa.c b/exa/exa.c index 75d5c0d69..b0c4d314e 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -122,13 +122,22 @@ exaGetDrawablePixmap(DrawablePtr pDrawable) * optimizations in pixmap migration when no changes have occurred. */ void -exaDrawableDirty (DrawablePtr pDrawable) +exaDrawableDirty (DrawablePtr pDrawable, int x1, int y1, int x2, int y2) { 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)); - if (pExaPixmap != NULL) - pExaPixmap->dirty = TRUE; + if (!pExaPixmap || box.x1 >= box.x2 || box.y1 >= box.y2) + return; + + pDamageReg = DamageRegion(pExaPixmap->pDamage); + + REGION_INIT(pScreen, ®ion, &box, 1); + REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); + REGION_UNINIT(pScreen, ®ion); } static Bool @@ -149,6 +158,7 @@ exaDestroyPixmap (PixmapPtr pPixmap) pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; pPixmap->devKind = pExaPixmap->sys_pitch; } + REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validReg); } return fbDestroyPixmap (pPixmap); } @@ -216,7 +226,20 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth) 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; } @@ -334,8 +357,7 @@ exaPrepareAccess(DrawablePtr pDrawable, int index) /** * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. * - * It deals with marking drawables as dirty, and calling the driver's - * FinishAccess() only if necessary. + * It deals with calling the driver's FinishAccess() only if necessary. */ void exaFinishAccess(DrawablePtr pDrawable, int index) @@ -345,9 +367,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index) PixmapPtr pPixmap; ExaPixmapPrivPtr pExaPixmap; - if (index == EXA_PREPARE_DEST) - exaDrawableDirty (pDrawable); - pPixmap = exaGetDrawablePixmap (pDrawable); pExaPixmap = ExaGetPixmapPriv(pPixmap); @@ -373,7 +392,7 @@ exaFinishAccess(DrawablePtr pDrawable, int index) * accelerated or may sync the card and fall back to fb. */ 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. * 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); pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel); + exaDrawableDirty(&pNewTile->drawable, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); } if (pNewTile) @@ -419,9 +439,14 @@ exaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width * 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); - 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 * job for it. diff --git a/exa/exa_accel.c b/exa/exa_accel.c index bc77a4071..102973ac6 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -20,6 +20,11 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Eric Anholt + * Michel Dänzer + * */ #ifdef HAVE_DIX_CONFIG_H @@ -104,6 +109,9 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, (*pExaScr->info->Solid) (pPixmap, fullX1 + off_x, fullY1 + 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 { @@ -118,17 +126,20 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, partX2 = pbox->x2; if (partX2 > fullX2) partX2 = fullX2; - if (partX2 > partX1) + if (partX2 > partX1) { (*pExaScr->info->Solid) (pPixmap, partX1 + off_x, fullY1 + 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++; } } } (*pExaScr->info->DoneSolid) (pPixmap); - exaDrawableDirty (pDrawable); exaMarkSync(pScreen); } @@ -222,8 +233,8 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, exaFinishAccess(pDrawable, EXA_PREPARE_DEST); } + exaDrawableDirty(pDrawable, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } - exaDrawableDirty(pDrawable); return; @@ -351,11 +362,13 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, dst_off_y + pbox->y1 + i, 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) pExaScr->info->DoneCopy(pDstPixmap); exaMarkSync(pDstDrawable->pScreen); - exaDrawableDirty(pDstDrawable); return TRUE; } @@ -423,11 +436,13 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, 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++; } (*pExaScr->info->DoneCopy) (pDstPixmap); exaMarkSync(pDstDrawable->pScreen); - exaDrawableDirty (pDstDrawable); return; } @@ -442,6 +457,13 @@ fallback: bitplane, closure); exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); 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 @@ -681,6 +703,9 @@ exaPolyFillRect(DrawablePtr pDrawable, (*pExaScr->info->Solid) (pPixmap, fullX1 + xoff, fullY1 + yoff, fullX2 + xoff, fullY2 + yoff); + exaDrawableDirty (pDrawable, + fullX1 + xoff, fullY1 + yoff, + fullX2 + xoff, fullY2 + yoff); } else { @@ -706,15 +731,18 @@ exaPolyFillRect(DrawablePtr pDrawable, pbox++; - if (partX1 < partX2 && partY1 < partY2) + if (partX1 < partX2 && partY1 < partY2) { (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); + exaDrawableDirty (pDrawable, + partX1 + xoff, partY1 + yoff, + partX2 + xoff, partY2 + yoff); + } } } } (*pExaScr->info->DoneSolid) (pPixmap); - exaDrawableDirty (pDrawable); exaMarkSync(pDrawable->pScreen); } @@ -735,11 +763,15 @@ exaSolidBoxClipped (DrawablePtr pDrawable, int xoff, yoff; int partX1, partX2, partY1, partY2; ExaMigrationRec pixmaps[1]; + Bool fallback = FALSE; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; 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 || pDrawable->width > pExaScr->info->maxX || pDrawable->height > pExaScr->info->maxY) @@ -750,19 +782,21 @@ exaSolidBoxClipped (DrawablePtr pDrawable, exaDoMigration (pixmaps, 1, TRUE); } - if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + + if (!pPixmap || !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg)) { fallback: EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); + fallback = TRUE; exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); nbox--; @@ -790,12 +824,19 @@ fallback: if (partY2 <= partY1) continue; - (*pExaScr->info->Solid) (pPixmap, - partX1 + xoff, partY1 + yoff, - partX2 + xoff, partY2 + yoff); + if (!fallback) + (*pExaScr->info->Solid) (pPixmap, + 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); - exaDrawableDirty (pDrawable); exaMarkSync(pDrawable->pScreen); } @@ -928,6 +969,8 @@ exaImageGlyphBlt (DrawablePtr pDrawable, gStride, 0); } + exaDrawableDirty(pDrawable, gx + dstXoff, gy + dstYoff, + gx + dstXoff + gWidth, gy + dstYoff + gHeight); } x += pci->metrics.characterWidth; } @@ -994,6 +1037,8 @@ exaFillRegionSolid (DrawablePtr pDrawable, PixmapPtr pPixmap; int xoff, yoff; ExaMigrationRec pixmaps[1]; + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; @@ -1011,19 +1056,18 @@ exaFillRegionSolid (DrawablePtr pDrawable, if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && (*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel)) { - int nbox = REGION_NUM_RECTS (pRegion); - BoxPtr pBox = REGION_RECTS (pRegion); - while (nbox--) { (*pExaScr->info->Solid) (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, pBox->x2 + xoff, pBox->y2 + yoff); + exaDrawableDirty (pDrawable, + pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); pBox++; } (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); } else { @@ -1034,6 +1078,13 @@ fallback: fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); 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); PixmapPtr pPixmap; - int xoff, yoff; + int xoff, yoff, tileXoff, tileYoff; int tileWidth, tileHeight; ExaMigrationRec pixmaps[2]; + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); tileWidth = pTile->drawable.width; tileHeight = pTile->drawable.height; @@ -1069,6 +1122,9 @@ exaFillRegionTiled (DrawablePtr pDrawable, pixmaps[1].as_src = TRUE; 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 || pDrawable->height > pExaScr->info->maxY || tileWidth > pExaScr->info->maxX || @@ -1081,18 +1137,16 @@ exaFillRegionTiled (DrawablePtr pDrawable, } pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (!pPixmap) goto fallback; if (!exaPixmapIsOffscreen(pTile)) 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)) { - int nbox = REGION_NUM_RECTS (pRegion); - BoxPtr pBox = REGION_RECTS (pRegion); - while (nbox--) { int height = pBox->y2 - pBox->y1; @@ -1118,7 +1172,7 @@ exaFillRegionTiled (DrawablePtr pDrawable, width -= w; (*pExaScr->info->Copy) (pPixmap, - tileX, tileY, + tileX + tileXoff, tileY + tileYoff, dstX + xoff, dstY + yoff, w, h); dstX += w; @@ -1127,11 +1181,12 @@ exaFillRegionTiled (DrawablePtr pDrawable, dstY += h; tileY = 0; } + exaDrawableDirty (pDrawable, pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); pBox++; } (*pExaScr->info->DoneCopy) (pPixmap); exaMarkSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); return; } @@ -1144,6 +1199,12 @@ fallback: fbFillRegionTiled (pDrawable, pRegion, pTile); exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + while (nbox--) + { + exaDrawableDirty (pDrawable, pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); + pBox++; + } } void diff --git a/exa/exa_migration.c b/exa/exa_migration.c index 57d651f80..d24a1bf98 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -22,6 +22,7 @@ * * Authors: * Eric Anholt + * Michel Dänzer * */ @@ -57,6 +58,27 @@ exaPixmapIsPinned (PixmapPtr pPix) 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 * location compared to the other), or lacks a private for tracking @@ -67,7 +89,8 @@ exaPixmapIsDirty (PixmapPtr 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); ExaPixmapPriv (pPixmap); + RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage); CARD8 *save_ptr; int save_pitch; - - if (!pExaPixmap->dirty) - return; + BoxPtr pBox = REGION_RECTS(pRegion); + int nbox = REGION_NUM_RECTS(pRegion); + Bool do_sync = FALSE; save_ptr = pPixmap->devPrivate.ptr; save_pitch = pPixmap->devKind; pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; pPixmap->devKind = pExaPixmap->fb_pitch; - if (pExaScr->info->DownloadFromScreen == NULL || - !pExaScr->info->DownloadFromScreen (pPixmap, - 0, - 0, - pPixmap->drawable.width, - pPixmap->drawable.height, - pExaPixmap->sys_ptr, - pExaPixmap->sys_pitch)) - { - char *src, *dst; - int src_pitch, dst_pitch, i, bytes; + while (nbox--) { + 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); - exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); + if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) + continue; - dst = pExaPixmap->sys_ptr; - dst_pitch = pExaPixmap->sys_pitch; - src = pExaPixmap->fb_ptr; - src_pitch = pExaPixmap->fb_pitch; - bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch; - - for (i = 0; i < pPixmap->drawable.height; i++) { - memcpy (dst, src, bytes); - dst += dst_pitch; - src += src_pitch; + if (pExaScr->info->DownloadFromScreen == NULL || + !pExaScr->info->DownloadFromScreen (pPixmap, + pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1, + pExaPixmap->sys_ptr + + pBox->y1 * pExaPixmap->sys_pitch + + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8, + pExaPixmap->sys_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 * when accessing pixmaps in system memory. */ - exaWaitSync (pPixmap->drawable.pScreen); + if (do_sync) + exaWaitSync (pPixmap->drawable.pScreen); pPixmap->devPrivate.ptr = save_ptr; 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); ExaPixmapPriv (pPixmap); + RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage); CARD8 *save_ptr; int save_pitch; - - if (!pExaPixmap->dirty) - return; + BoxPtr pBox = REGION_RECTS(pRegion); + int nbox = REGION_NUM_RECTS(pRegion); + Bool do_sync = FALSE; save_ptr = pPixmap->devPrivate.ptr; save_pitch = pPixmap->devKind; pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; pPixmap->devKind = pExaPixmap->fb_pitch; - if (pExaScr->info->UploadToScreen == NULL || - !pExaScr->info->UploadToScreen (pPixmap, - 0, - 0, - pPixmap->drawable.width, - pPixmap->drawable.height, - pExaPixmap->sys_ptr, - pExaPixmap->sys_pitch)) - { - char *src, *dst; - int src_pitch, dst_pitch, i, bytes; + while (nbox--) { + 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); - exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST); + if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) + continue; - dst = pExaPixmap->fb_ptr; - dst_pitch = pExaPixmap->fb_pitch; - src = pExaPixmap->sys_ptr; - src_pitch = pExaPixmap->sys_pitch; - bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch; - - for (i = 0; i < pPixmap->drawable.height; i++) { - memcpy (dst, src, bytes); - dst += dst_pitch; - src += src_pitch; + if (pExaScr->info->UploadToScreen == NULL || + !pExaScr->info->UploadToScreen (pPixmap, + pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1, + pExaPixmap->sys_ptr + + pBox->y1 * pExaPixmap->sys_pitch + + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8, + pExaPixmap->sys_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->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; ExaPixmapPriv(pPixmap); + RegionPtr pDamageReg = DamageRegion(pExaPixmap->pDamage); DBG_MIGRATE (("Save %p (%p) (%dx%d) (%c)\n", pPixmap, (void*)(ExaGetPixmapPriv(pPixmap)->area ? @@ -231,10 +273,9 @@ exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area) pExaPixmap->fb_ptr = NULL; pExaPixmap->area = NULL; - /* Mark it dirty now, to say that there is important data in the - * system-memory copy. - */ - pExaPixmap->dirty = TRUE; + /* Mark all valid bits as damaged, so they'll get copied to FB next time */ + REGION_UNION(pPixmap->drawable.pScreen, pDamageReg, pDamageReg, + &pExaPixmap->validReg); } /** @@ -413,30 +454,57 @@ exaMigrateTowardSys (PixmapPtr pPixmap) * If the pixmap has both a framebuffer and system memory copy, this function * asserts that both of them are the same. */ -static void +static Bool exaAssertNotDirty (PixmapPtr pPixmap) { ExaPixmapPriv (pPixmap); 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) - return; + return ret; dst = pExaPixmap->sys_ptr; dst_pitch = pExaPixmap->sys_pitch; src = pExaPixmap->fb_ptr; src_pitch = pExaPixmap->fb_pitch; - data_row_bytes = pPixmap->drawable.width * - pPixmap->drawable.bitsPerPixel / 8; + cpp = pPixmap->drawable.bitsPerPixel / 8; exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); - for (y = 0; y < pPixmap->drawable.height; y++) { - if (memcmp(dst, src, data_row_bytes) != 0) { - abort(); - } + while (nbox--) { + int rowbytes; + + 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); + + return ret; } /** @@ -460,8 +528,9 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) */ if (pExaScr->checkDirtyCorrectness) { for (i = 0; i < npixmaps; i++) { - if (!exaPixmapIsDirty (pixmaps[i].pPix)) - exaAssertNotDirty (pixmaps[i].pPix); + if (!exaPixmapIsDirty (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 diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c index b55802e1e..d5864dc57 100644 --- a/exa/exa_offscreen.c +++ b/exa/exa_offscreen.c @@ -390,6 +390,7 @@ ExaOffscreenMarkUsed (PixmapPtr pPixmap) if (area->state == ExaOffscreenRemovable) area->score = (area->score * 7) / 8; } + iter = 0; } } diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 90af55335..c725b4da0 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -51,6 +51,7 @@ #ifdef RENDER #include "fbpict.h" #endif +#include "damage.h" #define DEBUG_TRACE_FALL 0 #define DEBUG_MIGRATE 0 @@ -168,16 +169,16 @@ typedef struct { unsigned int fb_size; /**< size of pixmap in framebuffer memory */ /** - * If area is NULL, then dirty == TRUE means that the pixmap has been - * modified, so the contents are defined. Used to avoid uploads of - * undefined data. - * - * 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. + * The damage record contains the areas of the pixmap's current location + * (framebuffer or system) that have been damaged compared to the other + * location. */ - 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; typedef struct _ExaMigrationRec { @@ -323,7 +324,7 @@ ExaCheckComposite (CARD8 op, CARD16 height); #endif -/* exaoffscreen.c */ +/* exa_offscreen.c */ void ExaOffscreenMarkUsed (PixmapPtr pPixmap); @@ -347,7 +348,7 @@ void exaFinishAccess(DrawablePtr pDrawable, int index); void -exaDrawableDirty(DrawablePtr pDrawable); +exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2); Bool exaDrawableIsOffscreen (DrawablePtr pDrawable); diff --git a/exa/exa_render.c b/exa/exa_render.c index 26b29ab04..790a359a3 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -298,12 +298,13 @@ exaTryDriverSolidFill(PicturePtr pSrc, (*pExaScr->info->Solid) (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + 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++; } - (*pExaScr->info->DoneSolid) (pDstPix); exaMarkSync(pDst->pDrawable->pScreen); - exaDrawableDirty (pDst->pDrawable); REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return 1; @@ -437,12 +438,13 @@ exaTryDriverComposite(CARD8 op, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, 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++; } - (*pExaScr->info->DoneComposite) (pDstPix); exaMarkSync(pDst->pDrawable->pScreen); - exaDrawableDirty (pDst->pDrawable); REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return 1; @@ -648,6 +650,8 @@ exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); fbRasterizeTrapezoid(pPicture, trap, x_off, y_off); + exaDrawableDirty(pPicture->pDrawable, 0, 0, + pPicture->pDrawable->width, pPicture->pDrawable->height); 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); fbAddTriangles(pPicture, x_off, y_off, ntri, tris); 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, 0, 0, glyph->info.width, glyph->info.height, 0, 0); } else { - exaDrawableDirty (&pPixmap->drawable); + exaDrawableDirty (&pPixmap->drawable, 0, 0, + glyph->info.width, glyph->info.height); } if (maskFormat) diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index f9df6adc4..a30911507 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -23,6 +23,26 @@ #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 * synchronize framebuffer/accelerated drawing by stalling until @@ -200,11 +220,35 @@ ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC (pGC); - fbPolyFillRect (pDrawable, pGC, nrect, prect); - exaFinishAccessGC (pGC); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + + if (nrect) { + BoxRec box = { .x1 = max(prect->x,0), + .x2 = min(prect->x + prect->width,pDrawable->width), + .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 From 7e4717683d6c08d1e490a60b7493a94bbc57bf8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Sun, 15 Oct 2006 18:12:28 +0200 Subject: [PATCH 3/5] exaDrawableDirty: Fix initialization of BoxRec. This will hopefully fix the partial window corruption experienced by some people. --- exa/exa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exa/exa.c b/exa/exa.c index b0c4d314e..3e6ac76dc 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -126,7 +126,8 @@ exaDrawableDirty (DrawablePtr pDrawable, int x1, int y1, int x2, int y2) { ExaPixmapPrivPtr pExaPixmap; RegionPtr pDamageReg; - BoxRec box = { max(x1,0), max(y1,0), min(x2,pDrawable->width), min(y2,pDrawable->height) }; + BoxRec box = { .x1 = max(x1,0), .x2 = min(x2,pDrawable->width), + .y1 = max(y1,0), .y2 = min(y2,pDrawable->height) }; RegionRec region; pExaPixmap = ExaGetPixmapPriv(exaGetDrawablePixmap (pDrawable)); From 467c00cf450826e0bf06fe94470ec193af625d68 Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Tue, 19 Dec 2006 18:45:25 +0100 Subject: [PATCH 4/5] exaGlyphs: mark dirty for software path also. This affects drivers with no UploadToScreen or UploadToScreen failures. --- exa/exa_render.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exa/exa_render.c b/exa/exa_render.c index a73582000..be7c2403b 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -1034,11 +1034,11 @@ exaGlyphs (CARD8 op, exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC, 0, 0, glyph->info.width, glyph->info.height, 0, 0); - } else { - exaDrawableDirty (&pPixmap->drawable, 0, 0, - glyph->info.width, glyph->info.height); } + exaDrawableDirty (&pPixmap->drawable, 0, 0, + glyph->info.width, glyph->info.height); + if (maskFormat) { exaComposite (PictOpAdd, pPicture, NULL, pMask, 0, 0, 0, 0, From 9563b2eea2f61246b6a9e14e00c701f693efa4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 19 Dec 2006 18:57:22 +0100 Subject: [PATCH 5/5] EXA: Lots of damage tracking fixes. Mostly due to exaDrawableDirty() now calculating the backing pixmap coordinates internally, for cases where they aren't trivially known. There's a new exaPixmapDirty() function for the other cases. --- exa/exa.c | 106 ++++++++++++++++++++++++++++++---------------- exa/exa_accel.c | 89 +++++++++++++++++++------------------- exa/exa_priv.h | 3 ++ exa/exa_render.c | 36 ++++++++-------- exa/exa_unaccel.c | 40 ++++------------- 5 files changed, 143 insertions(+), 131 deletions(-) diff --git a/exa/exa.c b/exa/exa.c index 195457cd5..e61bc69a8 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -121,6 +121,57 @@ exaGetDrawablePixmap(DrawablePtr 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, ®ion, &box, 1); + REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); + REGION_UNINIT(pScreen, ®ion); +} + /** * exaDrawableDirty() marks a pixmap backing a drawable as dirty, allowing for * optimizations in pixmap migration when no changes have occurred. @@ -128,21 +179,20 @@ exaGetDrawablePixmap(DrawablePtr pDrawable) void exaDrawableDirty (DrawablePtr pDrawable, int x1, int y1, int x2, int y2) { - ExaPixmapPrivPtr pExaPixmap; - RegionPtr pDamageReg; - BoxRec box = { .x1 = max(x1,0), .x2 = min(x2,pDrawable->width), - .y1 = max(y1,0), .y2 = min(y2,pDrawable->height) }; - RegionRec region; + PixmapPtr pPix = exaGetDrawablePixmap(pDrawable); + int xoff, yoff; - pExaPixmap = ExaGetPixmapPriv(exaGetDrawablePixmap (pDrawable)); - if (!pExaPixmap || box.x1 >= box.x2 || box.y1 >= box.y2) + x1 = max(x1, pDrawable->x); + y1 = max(y1, pDrawable->y); + x2 = min(x2, pDrawable->x + pDrawable->width); + y2 = min(y2, pDrawable->y + pDrawable->height); + + if (x1 >= x2 || y1 >= y2) return; - - pDamageReg = DamageRegion(pExaPixmap->pDamage); - REGION_INIT(pScreen, ®ion, &box, 1); - REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); - REGION_UNINIT(pScreen, ®ion); + exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff); + + exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } static Bool @@ -289,32 +339,14 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) /** * 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. - * These coordinates are nonzero only for redirected windows. */ PixmapPtr exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) { - PixmapPtr pPixmap; - int x, y; + PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); + + 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)) return pPixmap; else @@ -428,7 +460,7 @@ exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC); pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel); - exaDrawableDirty(&pNewTile->drawable, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); + exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); } if (pNewTile) @@ -449,9 +481,9 @@ exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) */ exaMoveOutPixmap(pGC->tile.pixmap); fbPadPixmap (pGC->tile.pixmap); - exaDrawableDirty(&pGC->tile.pixmap->drawable, 0, 0, - pGC->tile.pixmap->drawable.width, - pGC->tile.pixmap->drawable.height); + 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 * job for it. diff --git a/exa/exa_accel.c b/exa/exa_accel.c index d2fe2e034..6fa481ad0 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -109,9 +109,8 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, (*pExaScr->info->Solid) (pPixmap, fullX1 + off_x, fullY1 + off_y, fullX2 + off_x, fullY1 + 1 + off_y); - exaDrawableDirty (pDrawable, - fullX1 + off_x, fullY1 + 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 { @@ -130,9 +129,8 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, (*pExaScr->info->Solid) (pPixmap, partX1 + off_x, fullY1 + off_y, partX2 + off_x, fullY1 + 1 + off_y); - exaDrawableDirty (pDrawable, - partX1 + off_x, fullY1 + 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++; @@ -233,7 +231,7 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, exaFinishAccess(pDrawable, EXA_PREPARE_DEST); } - exaDrawableDirty(pDrawable, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); + exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } return; @@ -362,9 +360,8 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, dst_off_y + pbox->y1 + i, 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); + 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) pExaScr->info->DoneCopy(pDstPixmap); @@ -437,9 +434,9 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, 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); + exaPixmapDirty (pDstPixmap, + pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } (*pExaScr->info->DoneCopy) (pDstPixmap); @@ -460,9 +457,7 @@ fallback: 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); + exaDrawableDirty (pDstDrawable, pbox->x1, pbox->y1, pbox->x2, pbox->y2); pbox++; } } @@ -704,9 +699,8 @@ exaPolyFillRect(DrawablePtr pDrawable, (*pExaScr->info->Solid) (pPixmap, fullX1 + xoff, fullY1 + yoff, fullX2 + xoff, fullY2 + yoff); - exaDrawableDirty (pDrawable, - fullX1 + xoff, fullY1 + yoff, - fullX2 + xoff, fullY2 + yoff); + exaPixmapDirty (pPixmap, fullX1 + xoff, fullY1 + yoff, + fullX2 + xoff, fullY2 + yoff); } else { @@ -736,9 +730,8 @@ exaPolyFillRect(DrawablePtr pDrawable, (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); - exaDrawableDirty (pDrawable, - partX1 + xoff, partY1 + yoff, - partX2 + xoff, partY2 + yoff); + exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, + partX2 + xoff, partY2 + yoff); } } } @@ -770,9 +763,6 @@ exaSolidBoxClipped (DrawablePtr pDrawable, pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); - /* We need to initialize x/yoff for tracking damage in the fallback case */ - pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); - if (pExaScr->swappedOut || pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.height > pExaScr->info->maxY) @@ -825,13 +815,14 @@ fallback: if (partY2 <= partY1) continue; - if (!fallback) + if (!fallback) { (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); - exaDrawableDirty (pDrawable, - 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) @@ -950,12 +941,17 @@ exaImageGlyphBlt (DrawablePtr pDrawable, pPriv->fg, gx + dstXoff, gHeight); + exaDrawableDirty (pDrawable, gx, gy, gx + gWidth, gy + gHeight); } else { + RegionPtr pClip = fbGetCompositeClip(pGC); + int nbox; + BoxPtr pbox; + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); fbPutXYImage (pDrawable, - fbGetCompositeClip(pGC), + pClip, pPriv->fg, pPriv->bg, pPriv->pm, @@ -969,9 +965,19 @@ exaImageGlyphBlt (DrawablePtr pDrawable, (FbStip *) pglyph, gStride, 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); + } } - exaDrawableDirty(pDrawable, gx + dstXoff, gy + dstYoff, - gx + dstXoff + gWidth, gy + dstYoff + gHeight); } x += pci->metrics.characterWidth; } @@ -1062,9 +1068,8 @@ exaFillRegionSolid (DrawablePtr pDrawable, (*pExaScr->info->Solid) (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, pBox->x2 + xoff, pBox->y2 + yoff); - exaDrawableDirty (pDrawable, - pBox->x1 + xoff, pBox->y1 + yoff, - pBox->x2 + xoff, pBox->y2 + yoff); + exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); pBox++; } (*pExaScr->info->DoneSolid) (pPixmap); @@ -1081,9 +1086,7 @@ fallback: exaFinishAccess (pDrawable, EXA_PREPARE_DEST); while (nbox--) { - exaDrawableDirty (pDrawable, - pBox->x1 + xoff, pBox->y1 + yoff, - pBox->x2 + xoff, pBox->y2 + yoff); + exaDrawableDirty (pDrawable, pBox->x1, pBox->y1, pBox->x2, pBox->y2); pBox++; } } @@ -1123,9 +1126,6 @@ exaFillRegionTiled (DrawablePtr pDrawable, pixmaps[1].as_src = TRUE; pixmaps[1].pPix = pTile; - /* We need to initialize x/yoff for tracking damage in the fallback case */ - pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); - if (pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.height > pExaScr->info->maxY || tileWidth > pExaScr->info->maxX || @@ -1182,8 +1182,8 @@ exaFillRegionTiled (DrawablePtr pDrawable, dstY += h; tileY = 0; } - exaDrawableDirty (pDrawable, pBox->x1 + xoff, pBox->y1 + yoff, - pBox->x2 + xoff, pBox->y2 + yoff); + exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); pBox++; } (*pExaScr->info->DoneCopy) (pPixmap); @@ -1202,8 +1202,7 @@ fallback: exaFinishAccess (pDrawable, EXA_PREPARE_DEST); while (nbox--) { - exaDrawableDirty (pDrawable, pBox->x1 + xoff, pBox->y1 + yoff, - pBox->x2 + xoff, pBox->y2 + yoff); + exaDrawableDirty (pDrawable, pBox->x1, pBox->y1, pBox->x2, pBox->y2); pBox++; } } diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 80cf60903..926e02a1f 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -339,6 +339,9 @@ exaPrepareAccess(DrawablePtr pDrawable, int index); void exaFinishAccess(DrawablePtr pDrawable, int index); +void +exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2); + void exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2); diff --git a/exa/exa_render.c b/exa/exa_render.c index be7c2403b..75108a75c 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -302,9 +302,8 @@ exaTryDriverSolidFill(PicturePtr pSrc, (*pExaScr->info->Solid) (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + 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); + exaPixmapDirty (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } (*pExaScr->info->DoneSolid) (pDstPix); @@ -447,9 +446,8 @@ exaTryDriverComposite(CARD8 op, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, 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); + exaPixmapDirty (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } (*pExaScr->info->DoneComposite) (pDstPix); @@ -712,18 +710,19 @@ void exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, int x_off, int y_off) { + DrawablePtr pDraw = pPicture->pDrawable; ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = exaGetDrawablePixmap (pPicture->pDrawable); + pixmaps[0].pPix = exaGetDrawablePixmap (pDraw); exaDoMigration(pixmaps, 1, FALSE); - exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); + exaPrepareAccess(pDraw, EXA_PREPARE_DEST); fbRasterizeTrapezoid(pPicture, trap, x_off, y_off); - exaDrawableDirty(pPicture->pDrawable, 0, 0, - pPicture->pDrawable->width, pPicture->pDrawable->height); - 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); } /** @@ -734,18 +733,19 @@ void exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, xTriangle *tris) { + DrawablePtr pDraw = pPicture->pDrawable; ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = exaGetDrawablePixmap (pPicture->pDrawable); + pixmaps[0].pPix = exaGetDrawablePixmap (pDraw); exaDoMigration(pixmaps, 1, FALSE); - exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); + exaPrepareAccess(pDraw, EXA_PREPARE_DEST); fbAddTriangles(pPicture, x_off, y_off, ntri, tris); - exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); - exaDrawableDirty(pPicture->pDrawable, 0, 0, - pPicture->pDrawable->width, pPicture->pDrawable->height); + exaDrawableDirty(pDraw, pDraw->x, pDraw->y, + pDraw->x + pDraw->width, pDraw->y + pDraw->height); + exaFinishAccess(pDraw, EXA_PREPARE_DEST); } /** @@ -1036,8 +1036,8 @@ exaGlyphs (CARD8 op, 0, 0, glyph->info.width, glyph->info.height, 0, 0); } - exaDrawableDirty (&pPixmap->drawable, 0, 0, - glyph->info.width, glyph->info.height); + exaPixmapDirty (pPixmap, 0, 0, + glyph->info.width, glyph->info.height); if (maskFormat) { diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index a30911507..7713a08c9 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -23,26 +23,6 @@ #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 * synchronize framebuffer/accelerated drawing by stalling until @@ -222,10 +202,9 @@ ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); if (nrect) { - BoxRec box = { .x1 = max(prect->x,0), - .x2 = min(prect->x + prect->width,pDrawable->width), - .y1 = max(prect->y,0), - .y2 = min(prect->y + prect->height,pDrawable->height) }; + int x1 = max(prect->x, 0), y1 = max(prect->y, 0); + int x2 = min(prect->x + prect->width, pDrawable->width); + int y2 = min(prect->y + prect->height, pDrawable->height); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccessGC (pGC); @@ -239,15 +218,14 @@ ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, 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); + x1 = min(x1, prect->x); + x2 = max(x2, prect->x + prect->width); + y1 = min(y1, prect->y); + y2 = max(y2, prect->y + prect->height); } - TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); - - exaDrawableDirty (pDrawable, box.x1, box.x2, box.y1, box.y2); + exaDrawableDirty (pDrawable, pDrawable->x + x1, pDrawable->y + y1, + pDrawable->x + x2, pDrawable->y + y2); } }