From 6060b612de6b41f872d034c6130770c1d189d0a3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 12 Jun 2006 20:12:31 +0200 Subject: [PATCH] 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 {