summaryrefslogtreecommitdiff
path: root/miext/damage/damage.c
diff options
context:
space:
mode:
Diffstat (limited to 'miext/damage/damage.c')
-rwxr-xr-xmiext/damage/damage.c1933
1 files changed, 1933 insertions, 0 deletions
diff --git a/miext/damage/damage.c b/miext/damage/damage.c
new file mode 100755
index 000000000..963780f70
--- /dev/null
+++ b/miext/damage/damage.c
@@ -0,0 +1,1933 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2003 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "font.h"
+#include "dixfontstr.h"
+#include "fontstruct.h"
+#include "mi.h"
+#include "regionstr.h"
+#include "globals.h"
+#include "gcstruct.h"
+#include "damage.h"
+#include "damagestr.h"
+#ifdef COMPOSITE
+#include "cw.h"
+#endif
+
+#define wrap(priv, real, mem, func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv, real, mem) {\
+ real->mem = priv->mem; \
+}
+
+#define BOX_SAME(a,b) \
+ ((a)->x1 == (b)->x1 && \
+ (a)->y1 == (b)->y1 && \
+ (a)->x2 == (b)->x2 && \
+ (a)->y2 == (b)->y2)
+
+#define DAMAGE_VALIDATE_ENABLE 0
+#define DAMAGE_DEBUG_ENABLE 0
+#if DAMAGE_DEBUG_ENABLE
+#define DAMAGE_DEBUG(x) ErrorF x
+#else
+#define DAMAGE_DEBUG(x)
+#endif
+
+#define getPixmapDamageRef(pPixmap) \
+ ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr))
+
+#define pixmapDamage(pPixmap) damagePixPriv(pPixmap)
+
+static DamagePtr *
+getDrawableDamageRef (DrawablePtr pDrawable)
+{
+ PixmapPtr pPixmap;
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ ScreenPtr pScreen = pDrawable->pScreen;
+
+ pPixmap = 0;
+ if (pScreen->GetWindowPixmap
+#ifdef ROOTLESS_WORKAROUND
+ && ((WindowPtr)pDrawable)->viewable
+#endif
+ )
+ pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable);
+
+ if (!pPixmap)
+ {
+ damageScrPriv(pScreen);
+
+ return &pScrPriv->pScreenDamage;
+ }
+ }
+ else
+ pPixmap = (PixmapPtr) pDrawable;
+ return getPixmapDamageRef (pPixmap);
+}
+
+#define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable))
+#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable)
+
+#define drawableDamage(pDrawable) \
+ DamagePtr pDamage = getDrawableDamage(pDrawable)
+
+#define windowDamage(pWin) drawableDamage(&(pWin)->drawable)
+
+#define winDamageRef(pWindow) \
+ DamagePtr *pPrev = (DamagePtr *) \
+ &(pWindow->devPrivates[damageWinPrivateIndex].ptr)
+
+#if DAMAGE_DEBUG_ENABLE
+static void
+_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, char *where)
+#define damageDamageRegion(d,r,c) _damageDamageRegion(d,r,c,__FUNCTION__)
+#else
+static void
+damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip)
+#endif
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ damageScrPriv(pScreen);
+ drawableDamage(pDrawable);
+ DamagePtr pNext;
+ RegionPtr pClip;
+ 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;
+#endif
+
+ /* short circuit for empty regions */
+ if (!REGION_NOTEMPTY(pScreen, pRegion))
+ return;
+
+#ifdef COMPOSITE
+ /*
+ * When drawing to a pixmap which is storing window contents,
+ * the region presented is in pixmap relative coordinates which
+ * need to be converted to screen relative coordinates
+ */
+ if (pDrawable->type != DRAWABLE_WINDOW)
+ {
+ screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x;
+ screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y;
+ }
+ if (screen_x || screen_y)
+ REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y);
+#endif
+
+ REGION_NULL (pScreen, &clippedRec);
+ for (; pDamage; pDamage = pNext)
+ {
+ pNext = pDamage->pNext;
+ /*
+ * Check for internal damage and don't send events
+ */
+ if (pScrPriv->internalLevel > 0 && !pDamage->isInternal)
+ {
+ DAMAGE_DEBUG (("non internal damage, skipping at %d\n",
+ pScrPriv->internalLevel));
+ continue;
+ }
+ /*
+ * Check for unrealized windows
+ */
+ if (pDamage->pDrawable->type == DRAWABLE_WINDOW &&
+ !((WindowPtr) (pDamage->pDrawable))->realized)
+ {
+#if 0
+ DAMAGE_DEBUG (("damage while window unrealized\n"));
+#endif
+ continue;
+ }
+
+ draw_x = pDamage->pDrawable->x;
+ draw_y = pDamage->pDrawable->y;
+#ifdef COMPOSITE
+ /*
+ * Need to move everyone to screen coordinates
+ * XXX what about off-screen pixmaps with non-zero x/y?
+ */
+ if (pDamage->pDrawable->type != DRAWABLE_WINDOW)
+ {
+ draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x;
+ draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y;
+ }
+#endif
+
+ /*
+ * Clip against border or pixmap bounds
+ */
+
+ pDamageRegion = pRegion;
+ if (clip || pDamage->pDrawable != pDrawable)
+ {
+ pDamageRegion = &clippedRec;
+ if (pDamage->pDrawable->type == DRAWABLE_WINDOW)
+ pClip = &((WindowPtr)(pDamage->pDrawable))->borderClip;
+ else
+ {
+ BoxRec box;
+ box.x1 = draw_x;
+ box.y1 = draw_y;
+ box.x2 = draw_x + pDamage->pDrawable->width;
+ box.y2 = draw_y + pDamage->pDrawable->height;
+ REGION_INIT(pScreen, &pixClip, &box, 1);
+ pClip = &pixClip;
+ }
+ REGION_INTERSECT (pScreen, pDamageRegion, pRegion, pClip);
+ /*
+ * Short circuit empty results
+ */
+ if (!REGION_NOTEMPTY(pScreen, pDamageRegion))
+ continue;
+ }
+
+ DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
+ where,
+ pDamageRegion->extents.x2 - pDamageRegion->extents.x1,
+ pDamageRegion->extents.y2 - pDamageRegion->extents.y1,
+ pDamageRegion->extents.x1, pDamageRegion->extents.y1,
+ pDrawable->id, pDamage->pDrawable->id));
+
+ /*
+ * Move region to target coordinate space
+ */
+ 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);
+ }
+ 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
+ */
+ if (pDamageRegion == pRegion && (draw_x || draw_y))
+ REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y);
+ }
+#ifdef COMPOSITE
+ if (screen_x || screen_y)
+ REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y);
+#endif
+
+ REGION_UNINIT (pScreen, &clippedRec);
+}
+
+#if DAMAGE_DEBUG_ENABLE
+#define damageDamageBox(d,b) _damageDamageBox(d,b,__FUNCTION__)
+static void
+_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, char *where)
+#else
+static void
+damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox)
+#endif
+{
+ RegionRec region;
+
+ REGION_INIT (pDrawable->pScreen, &region, pBox, 1);
+#if DAMAGE_DEBUG_ENABLE
+ _damageDamageRegion (pDrawable, &region, TRUE, where);
+#else
+ damageDamageRegion (pDrawable, &region, TRUE);
+#endif
+ REGION_UNINIT (pDrawable->pScreen, &region);
+}
+
+static void damageValidateGC(GCPtr, unsigned long, DrawablePtr);
+static void damageChangeGC(GCPtr, unsigned long);
+static void damageCopyGC(GCPtr, unsigned long, GCPtr);
+static void damageDestroyGC(GCPtr);
+static void damageChangeClip(GCPtr, int, pointer, int);
+static void damageDestroyClip(GCPtr);
+static void damageCopyClip(GCPtr, GCPtr);
+
+GCFuncs damageGCFuncs = {
+ damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC,
+ damageChangeClip, damageDestroyClip, damageCopyClip
+};
+
+extern GCOps damageGCOps;
+
+static Bool
+damageCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ damageScrPriv(pScreen);
+ damageGCPriv(pGC);
+ Bool ret;
+
+ pGC->pCompositeClip = 0;
+ unwrap (pScrPriv, pScreen, CreateGC);
+ if((ret = (*pScreen->CreateGC) (pGC))) {
+ pGCPriv->ops = NULL;
+ pGCPriv->funcs = pGC->funcs;
+ pGC->funcs = &damageGCFuncs;
+ }
+ wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
+
+ return ret;
+}
+
+#ifdef NOTUSED
+static void
+damageWrapGC (GCPtr pGC)
+{
+ damageGCPriv(pGC);
+
+ pGCPriv->ops = NULL;
+ pGCPriv->funcs = pGC->funcs;
+ pGC->funcs = &damageGCFuncs;
+}
+
+static void
+damageUnwrapGC (GCPtr pGC)
+{
+ damageGCPriv(pGC);
+
+ pGC->funcs = pGCPriv->funcs;
+ if (pGCPriv->ops)
+ pGC->ops = pGCPriv->ops;
+}
+#endif
+
+#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
+ damageGCPriv(pGC); \
+ GCFuncs *oldFuncs = pGC->funcs; \
+ unwrap(pGCPriv, pGC, funcs); \
+ unwrap(pGCPriv, pGC, ops); \
+
+#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
+ wrap(pGCPriv, pGC, funcs, oldFuncs); \
+ wrap(pGCPriv, pGC, ops, &damageGCOps)
+
+#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
+ damageGCPriv(pGC); \
+ unwrap(pGCPriv, pGC, funcs); \
+ if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
+
+#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
+ wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \
+ if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
+
+static void
+damageValidateGC(GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDrawable)
+{
+ DAMAGE_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
+ pGCPriv->ops = pGC->ops; /* just so it's not NULL */
+ DAMAGE_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+damageDestroyGC(GCPtr pGC)
+{
+ DAMAGE_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->DestroyGC)(pGC);
+ DAMAGE_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+damageChangeGC (GCPtr pGC,
+ unsigned long mask)
+{
+ DAMAGE_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+ DAMAGE_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+damageCopyGC (GCPtr pGCSrc,
+ unsigned long mask,
+ GCPtr pGCDst)
+{
+ DAMAGE_GC_FUNC_PROLOGUE (pGCDst);
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+ DAMAGE_GC_FUNC_EPILOGUE (pGCDst);
+}
+
+static void
+damageChangeClip (GCPtr pGC,
+ int type,
+ pointer pvalue,
+ int nrects)
+{
+ DAMAGE_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+ DAMAGE_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ DAMAGE_GC_FUNC_PROLOGUE (pgcDst);
+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+ DAMAGE_GC_FUNC_EPILOGUE (pgcDst);
+}
+
+static void
+damageDestroyClip(GCPtr pGC)
+{
+ DAMAGE_GC_FUNC_PROLOGUE (pGC);
+ (* pGC->funcs->DestroyClip)(pGC);
+ DAMAGE_GC_FUNC_EPILOGUE (pGC);
+}
+
+#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); \
+ }
+
+#define BOX_NOT_EMPTY(box) \
+ (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
+
+#define checkGCDamage(d,g) (getDrawableDamage(d) && \
+ (!g->pCompositeClip ||\
+ REGION_NOTEMPTY(d->pScreen, \
+ g->pCompositeClip)))
+
+#ifdef RENDER
+
+#define TRIM_PICTURE_BOX(box, pDst) { \
+ BoxPtr extents = &pDst->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 checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \
+ REGION_NOTEMPTY(pScreen, p->pCompositeClip))
+
+static void
+damageComposite (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ damageScrPriv(pScreen);
+
+ if (checkPictureDamage (pDst))
+ {
+ BoxRec box;
+
+ box.x1 = xDst + pDst->pDrawable->x;
+ box.y1 = yDst + pDst->pDrawable->y;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+ TRIM_PICTURE_BOX(box, pDst);
+ if (BOX_NOT_EMPTY(box))
+ damageDamageBox (pDst->pDrawable, &box);
+ }
+ unwrap (pScrPriv, ps, Composite);
+ (*ps->Composite) (op,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height);
+ wrap (pScrPriv, ps, Composite, damageComposite);
+}
+
+static void
+damageGlyphs (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int nlist,
+ GlyphListPtr list,
+ GlyphPtr *glyphs)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ damageScrPriv(pScreen);
+
+ if (checkPictureDamage (pDst))
+ {
+ int nlistTmp = nlist;
+ GlyphListPtr listTmp = list;
+ GlyphPtr *glyphsTmp = glyphs;
+ int x, y;
+ int n;
+ GlyphPtr glyph;
+ BoxRec box;
+ int x1, y1, x2, y2;
+
+ box.x1 = 32767;
+ box.y1 = 32767;
+ box.x2 = -32767;
+ box.y2 = -32767;
+ x = pDst->pDrawable->x;
+ y = pDst->pDrawable->y;
+ while (nlistTmp--)
+ {
+ x += listTmp->xOff;
+ y += listTmp->yOff;
+ n = listTmp->len;
+ while (n--)
+ {
+ glyph = *glyphsTmp++;
+ x1 = x - glyph->info.x;
+ y1 = y - glyph->info.y;
+ x2 = x1 + glyph->info.width;
+ y2 = y1 + glyph->info.height;
+ if (x1 < box.x1)
+ box.x1 = x1;
+ if (y1 < box.y1)
+ box.y1 = y1;
+ if (x2 > box.x2)
+ box.x2 = x2;
+ if (y2 > box.y2)
+ box.y2 = y2;
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ listTmp++;
+ }
+ TRIM_PICTURE_BOX (box, pDst);
+ if (BOX_NOT_EMPTY(box))
+ damageDamageBox (pDst->pDrawable, &box);
+ }
+ unwrap (pScrPriv, ps, Glyphs);
+ (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+ wrap (pScrPriv, ps, Glyphs, damageGlyphs);
+}
+#endif
+
+/**********************************************************/
+
+
+static void
+damageFillSpans(DrawablePtr pDrawable,
+ GC *pGC,
+ int npt,
+ DDXPointPtr ppt,
+ int *pwidth,
+ int fSorted)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (npt && checkGCDamage (pDrawable, pGC))
+ {
+ int nptTmp = npt;
+ DDXPointPtr pptTmp = ppt;
+ int *pwidthTmp = pwidth;
+ BoxRec box;
+
+ box.x1 = pptTmp->x;
+ box.x2 = box.x1 + *pwidthTmp;
+ box.y2 = box.y1 = pptTmp->y;
+
+ while(--nptTmp)
+ {
+ pptTmp++;
+ pwidthTmp++;
+ if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
+ if(box.x2 < (pptTmp->x + *pwidthTmp))
+ box.x2 = pptTmp->x + *pwidthTmp;
+ if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
+ else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
+ }
+
+ box.y2++;
+
+ if(!pGC->miTranslate) {
+ TRANSLATE_BOX(box, pDrawable);
+ }
+ TRIM_BOX(box, pGC);
+
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+
+ (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted);
+
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damageSetSpans(DrawablePtr pDrawable,
+ GCPtr pGC,
+ char *pcharsrc,
+ DDXPointPtr ppt,
+ int *pwidth,
+ int npt,
+ int fSorted)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (npt && checkGCDamage (pDrawable, pGC))
+ {
+ DDXPointPtr pptTmp = ppt;
+ int *pwidthTmp = pwidth;
+ int nptTmp = npt;
+ BoxRec box;
+
+ box.x1 = pptTmp->x;
+ box.x2 = box.x1 + *pwidthTmp;
+ box.y2 = box.y1 = pptTmp->y;
+
+ while(--nptTmp)
+ {
+ pptTmp++;
+ pwidthTmp++;
+ if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
+ if(box.x2 < (pptTmp->x + *pwidthTmp))
+ box.x2 = pptTmp->x + *pwidthTmp;
+ if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
+ else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
+ }
+
+ box.y2++;
+
+ if(!pGC->miTranslate) {
+ TRANSLATE_BOX(box, pDrawable);
+ }
+ TRIM_BOX(box, pGC);
+
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damagePutImage(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int depth,
+ int x,
+ int y,
+ int w,
+ int h,
+ int leftPad,
+ int format,
+ char *pImage)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+ if (checkGCDamage (pDrawable, pGC))
+ {
+ BoxRec box;
+
+ box.x1 = x + pDrawable->x;
+ box.x2 = box.x1 + w;
+ box.y1 = y + pDrawable->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
+ leftPad, format, pImage);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static RegionPtr
+damageCopyArea(DrawablePtr pSrc,
+ DrawablePtr pDst,
+ GC *pGC,
+ int srcx,
+ int srcy,
+ int width,
+ int height,
+ int dstx,
+ int dsty)
+{
+ RegionPtr ret;
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
+
+ /* The driver will only call SourceValidate() when pSrc != pDst,
+ * but the software sprite (misprite.c) always need to know when a
+ * drawable is copied so it can remove the sprite. See #1030. */
+ if ((pSrc == pDst) && pSrc->pScreen->SourceValidate)
+ (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
+
+ if (checkGCDamage (pDst, pGC))
+ {
+ BoxRec box;
+
+ box.x1 = dstx + pDst->x;
+ box.x2 = box.x1 + width;
+ box.y1 = dsty + pDst->y;
+ box.y2 = box.y1 + height;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDst, &box);
+ }
+
+ ret = (*pGC->ops->CopyArea)(pSrc, pDst,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
+ return ret;
+}
+
+static RegionPtr
+damageCopyPlane(DrawablePtr pSrc,
+ DrawablePtr pDst,
+ GCPtr pGC,
+ int srcx,
+ int srcy,
+ int width,
+ int height,
+ int dstx,
+ int dsty,
+ unsigned long bitPlane)
+{
+ RegionPtr ret;
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
+
+ /* The driver will only call SourceValidate() when pSrc != pDst,
+ * but the software sprite (misprite.c) always need to know when a
+ * drawable is copied so it can remove the sprite. See #1030. */
+ if ((pSrc == pDst) && pSrc->pScreen->SourceValidate)
+ (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
+
+ if (checkGCDamage (pDst, pGC))
+ {
+ BoxRec box;
+
+ box.x1 = dstx + pDst->x;
+ box.x2 = box.x1 + width;
+ box.y1 = dsty + pDst->y;
+ box.y2 = box.y1 + height;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDst, &box);
+ }
+
+ ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
+ pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
+ return ret;
+}
+
+static void
+damagePolyPoint(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ xPoint *ppt)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (npt && checkGCDamage (pDrawable, pGC))
+ {
+ BoxRec box;
+ int nptTmp = npt;
+ xPoint *pptTmp = ppt;
+
+ box.x2 = box.x1 = pptTmp->x;
+ box.y2 = box.y1 = pptTmp->y;
+
+ /* this could be slow if the points were spread out */
+
+ while(--nptTmp)
+ {
+ pptTmp++;
+ if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
+ else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
+ if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
+ else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damagePolylines(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ DDXPointPtr ppt)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (npt && checkGCDamage (pDrawable, pGC))
+ {
+ int nptTmp = npt;
+ DDXPointPtr pptTmp = ppt;
+ BoxRec box;
+ int extra = pGC->lineWidth >> 1;
+
+ box.x2 = box.x1 = pptTmp->x;
+ box.y2 = box.y1 = pptTmp->y;
+
+ if(nptTmp > 1)
+ {
+ if(pGC->joinStyle == JoinMiter)
+ extra = 6 * pGC->lineWidth;
+ else if(pGC->capStyle == CapProjecting)
+ extra = pGC->lineWidth;
+ }
+
+ if(mode == CoordModePrevious)
+ {
+ int x = box.x1;
+ int y = box.y1;
+ while(--nptTmp)
+ {
+ pptTmp++;
+ x += pptTmp->x;
+ y += pptTmp->y;
+ if(box.x1 > x) box.x1 = x;
+ else if(box.x2 < x) box.x2 = x;
+ if(box.y1 > y) box.y1 = y;
+ else if(box.y2 < y) box.y2 = y;
+ }
+ }
+ else
+ {
+ while(--nptTmp)
+ {
+ pptTmp++;
+ if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
+ else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
+ if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
+ else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra)
+ {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damagePolySegment(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nSeg,
+ xSegment *pSeg)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (nSeg && checkGCDamage (pDrawable, pGC))
+ {
+ BoxRec box;
+ int extra = pGC->lineWidth;
+ int nsegTmp = nSeg;
+ xSegment *pSegTmp = pSeg;
+
+ if(pGC->capStyle != CapProjecting)
+ extra >>= 1;
+
+ if(pSegTmp->x2 > pSegTmp->x1) {
+ box.x1 = pSegTmp->x1;
+ box.x2 = pSegTmp->x2;
+ } else {
+ box.x2 = pSegTmp->x1;
+ box.x1 = pSegTmp->x2;
+ }
+
+ if(pSegTmp->y2 > pSegTmp->y1) {
+ box.y1 = pSegTmp->y1;
+ box.y2 = pSegTmp->y2;
+ } else {
+ box.y2 = pSegTmp->y1;
+ box.y1 = pSegTmp->y2;
+ }
+
+ while(--nsegTmp)
+ {
+ pSegTmp++;
+ if(pSegTmp->x2 > pSegTmp->x1)
+ {
+ if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1;
+ if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2;
+ }
+ else
+ {
+ if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2;
+ if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1;
+ }
+ if(pSegTmp->y2 > pSegTmp->y1)
+ {
+ if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1;
+ if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2;
+ }
+ else
+ {
+ if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2;
+ if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra)
+ {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damagePolyRectangle(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nRects,
+ xRectangle *pRects)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (nRects && checkGCDamage (pDrawable, pGC))
+ {
+ BoxRec box;
+ int offset1, offset2, offset3;
+ int nRectsTmp = nRects;
+ xRectangle *pRectsTmp = pRects;
+
+ offset2 = pGC->lineWidth;
+ if(!offset2) offset2 = 1;
+ offset1 = offset2 >> 1;
+ offset3 = offset2 - offset1;
+
+ while(nRectsTmp--)
+ {
+ box.x1 = pRectsTmp->x - offset1;
+ box.y1 = pRectsTmp->y - offset1;
+ box.x2 = box.x1 + pRectsTmp->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+
+ box.x1 = pRectsTmp->x - offset1;
+ box.y1 = pRectsTmp->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRectsTmp->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+
+ box.x1 = pRectsTmp->x + pRectsTmp->width - offset1;
+ box.y1 = pRectsTmp->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRectsTmp->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+
+ box.x1 = pRectsTmp->x - offset1;
+ box.y1 = pRectsTmp->y + pRectsTmp->height - offset1;
+ box.x2 = box.x1 + pRectsTmp->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+
+ pRectsTmp++;
+ }
+ }
+ (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damagePolyArc(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nArcs,
+ xArc *pArcs)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (nArcs && checkGCDamage (pDrawable, pGC))
+ {
+ int extra = pGC->lineWidth >> 1;
+ BoxRec box;
+ int nArcsTmp = nArcs;
+ xArc *pArcsTmp = pArcs;
+
+ box.x1 = pArcsTmp->x;
+ box.x2 = box.x1 + pArcsTmp->width;
+ box.y1 = pArcsTmp->y;
+ box.y2 = box.y1 + pArcsTmp->height;
+
+ while(--nArcsTmp)
+ {
+ pArcsTmp++;
+ if(box.x1 > pArcsTmp->x)
+ box.x1 = pArcsTmp->x;
+ if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
+ box.x2 = pArcsTmp->x + pArcsTmp->width;
+ if(box.y1 > pArcsTmp->y)
+ box.y1 = pArcsTmp->y;
+ if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
+ box.y2 = pArcsTmp->y + pArcsTmp->height;
+ }
+
+ if(extra)
+ {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damageFillPolygon(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int shape,
+ int mode,
+ int npt,
+ DDXPointPtr ppt)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (npt > 2 && checkGCDamage (pDrawable, pGC))
+ {
+ DDXPointPtr pptTmp = ppt;
+ int nptTmp = npt;
+ BoxRec box;
+
+ box.x2 = box.x1 = pptTmp->x;
+ box.y2 = box.y1 = pptTmp->y;
+
+ if(mode != CoordModeOrigin)
+ {
+ int x = box.x1;
+ int y = box.y1;
+ while(--nptTmp)
+ {
+ pptTmp++;
+ x += pptTmp->x;
+ y += pptTmp->y;
+ if(box.x1 > x) box.x1 = x;
+ else if(box.x2 < x) box.x2 = x;
+ if(box.y1 > y) box.y1 = y;
+ else if(box.y2 < y) box.y2 = y;
+ }
+ }
+ else
+ {
+ while(--nptTmp)
+ {
+ pptTmp++;
+ if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
+ else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
+ if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
+ else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+
+ (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+
+static void
+damagePolyFillRect(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nRects,
+ xRectangle *pRects)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+ if (nRects && checkGCDamage (pDrawable, pGC))
+ {
+ BoxRec box;
+ xRectangle *pRectsTmp = pRects;
+ int nRectsTmp = nRects;
+
+ box.x1 = pRectsTmp->x;
+ box.x2 = box.x1 + pRectsTmp->width;
+ box.y1 = pRectsTmp->y;
+ box.y2 = box.y1 + pRectsTmp->height;
+
+ while(--nRectsTmp)
+ {
+ pRectsTmp++;
+ if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x;
+ if(box.x2 < (pRectsTmp->x + pRectsTmp->width))
+ box.x2 = pRectsTmp->x + pRectsTmp->width;
+ if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y;
+ if(box.y2 < (pRectsTmp->y + pRectsTmp->height))
+ box.y2 = pRectsTmp->y + pRectsTmp->height;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+
+static void
+damagePolyFillArc(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nArcs,
+ xArc *pArcs)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (nArcs && checkGCDamage (pDrawable, pGC))
+ {
+ BoxRec box;
+ int nArcsTmp = nArcs;
+ xArc *pArcsTmp = pArcs;
+
+ box.x1 = pArcsTmp->x;
+ box.x2 = box.x1 + pArcsTmp->width;
+ box.y1 = pArcsTmp->y;
+ box.y2 = box.y1 + pArcsTmp->height;
+
+ while(--nArcsTmp)
+ {
+ pArcsTmp++;
+ if(box.x1 > pArcsTmp->x)
+ box.x1 = pArcsTmp->x;
+ if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
+ box.x2 = pArcsTmp->x + pArcsTmp->width;
+ if(box.y1 > pArcsTmp->y)
+ box.y1 = pArcsTmp->y;
+ if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
+ box.y2 = pArcsTmp->y + pArcsTmp->height;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+/*
+ * general Poly/Image text function. Extract glyph information,
+ * compute bounding box and remove cursor if it is overlapped.
+ */
+
+static void
+damageDamageChars (DrawablePtr pDrawable,
+ FontPtr font,
+ int x,
+ int y,
+ unsigned int n,
+ CharInfoPtr *charinfo,
+ Bool imageblt)
+{
+ ExtentInfoRec extents;
+ BoxRec box;
+
+ QueryGlyphExtents(font, charinfo, n, &extents);
+ if (imageblt)
+ {
+ if (extents.overallWidth > extents.overallRight)
+ extents.overallRight = extents.overallWidth;
+ if (extents.overallWidth < extents.overallLeft)
+ extents.overallLeft = extents.overallWidth;
+ if (extents.overallLeft > 0)
+ extents.overallLeft = 0;
+ if (extents.fontAscent > extents.overallAscent)
+ extents.overallAscent = extents.fontAscent;
+ if (extents.fontDescent > extents.overallDescent)
+ extents.overallDescent = extents.fontDescent;
+ }
+ box.x1 = x + extents.overallLeft;
+ box.y1 = y - extents.overallAscent;
+ box.x2 = x + extents.overallRight;
+ box.y2 = y + extents.overallDescent;
+ damageDamageBox (pDrawable, &box);
+}
+
+/*
+ * values for textType:
+ */
+#define TT_POLY8 0
+#define TT_IMAGE8 1
+#define TT_POLY16 2
+#define TT_IMAGE16 3
+
+static int
+damageText (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned long count,
+ char *chars,
+ FontEncoding fontEncoding,
+ Bool textType)
+{
+ CharInfoPtr *charinfo;
+ CharInfoPtr *info;
+ unsigned long i;
+ unsigned int n;
+ int w;
+ Bool imageblt;
+
+ imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
+
+ charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
+ if (!charinfo)
+ return x;
+
+ GetGlyphs(pGC->font, count, (unsigned char *)chars,
+ fontEncoding, &i, charinfo);
+ n = (unsigned int)i;
+ w = 0;
+ if (!imageblt)
+ for (info = charinfo; i--; info++)
+ w += (*info)->metrics.characterWidth;
+
+ if (n != 0) {
+ damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n,
+ charinfo, imageblt);
+ if (imageblt)
+ (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
+ FONTGLYPHS(pGC->font));
+ else
+ (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
+ FONTGLYPHS(pGC->font));
+ }
+ DEALLOCATE_LOCAL(charinfo);
+ return x + w;
+}
+
+static int
+damagePolyText8(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (checkGCDamage (pDrawable, pGC))
+ damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
+ Linear8Bit, TT_POLY8);
+ else
+ x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+ return x;
+}
+
+static int
+damagePolyText16(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (checkGCDamage (pDrawable, pGC))
+ damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
+ FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
+ TT_POLY16);
+ else
+ x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+ return x;
+}
+
+static void
+damageImageText8(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (checkGCDamage (pDrawable, pGC))
+ damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
+ Linear8Bit, TT_IMAGE8);
+ else
+ (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damageImageText16(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+
+ if (checkGCDamage (pDrawable, pGC))
+ damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
+ FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
+ TT_IMAGE16);
+ else
+ (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+
+static void
+damageImageGlyphBlt(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+ damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
+ nglyph, ppci, TRUE);
+ (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph,
+ ppci, pglyphBase);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damagePolyGlyphBlt(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+ damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
+ nglyph, ppci, FALSE);
+ (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
+ ppci, pglyphBase);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damagePushPixels(GCPtr pGC,
+ PixmapPtr pBitMap,
+ DrawablePtr pDrawable,
+ int dx,
+ int dy,
+ int xOrg,
+ int yOrg)
+{
+ DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
+ if(checkGCDamage (pDrawable, pGC))
+ {
+ BoxRec box;
+
+ box.x1 = xOrg;
+ box.y1 = yOrg;
+
+ if(!pGC->miTranslate) {
+ box.x1 += pDrawable->x;
+ box.y1 += pDrawable->y;
+ }
+
+ box.x2 = box.x1 + dx;
+ box.y2 = box.y1 + dy;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ damageDamageBox (pDrawable, &box);
+ }
+ (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
+ DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
+}
+
+static void
+damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage)
+{
+ while (*pPrev)
+ {
+ if (*pPrev == pDamage)
+ {
+ *pPrev = pDamage->pNext;
+ return;
+ }
+ pPrev = &(*pPrev)->pNext;
+ }
+#if DAMAGE_VALIDATE_ENABLE
+ ErrorF ("Damage not on list\n");
+ abort ();
+#endif
+}
+
+static void
+damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage)
+{
+#if DAMAGE_VALIDATE_ENABLE
+ DamagePtr pOld;
+
+ for (pOld = *pPrev; pOld; pOld = pOld->pNext)
+ if (pOld == pDamage) {
+ ErrorF ("Damage already on list\n");
+ abort ();
+ }
+#endif
+ pDamage->pNext = *pPrev;
+ *pPrev = pDamage;
+}
+
+static Bool
+damageDestroyPixmap (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ damageScrPriv(pScreen);
+
+ if (pPixmap->refcnt == 1)
+ {
+ DamagePtr *pPrev = getPixmapDamageRef (pPixmap);
+ DamagePtr pDamage;
+
+ while ((pDamage = *pPrev))
+ {
+ damageRemoveDamage (pPrev, pDamage);
+ if (!pDamage->isWindow)
+ DamageDestroy (pDamage);
+ }
+ }
+ unwrap (pScrPriv, pScreen, DestroyPixmap);
+ (*pScreen->DestroyPixmap) (pPixmap);
+ wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
+ return TRUE;
+}
+
+static void
+damagePaintWindow(WindowPtr pWindow,
+ RegionPtr prgn,
+ int what)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ damageScrPriv(pScreen);
+
+ /*
+ * Painting background none doesn't actually *do* anything, so
+ * no damage is recorded
+ */
+ if ((what != PW_BACKGROUND || pWindow->backgroundState != None) &&
+ getWindowDamage (pWindow))
+ damageDamageRegion (&pWindow->drawable, prgn, FALSE);
+ if(what == PW_BACKGROUND) {
+ unwrap (pScrPriv, pScreen, PaintWindowBackground);
+ (*pScreen->PaintWindowBackground) (pWindow, prgn, what);
+ wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow);
+ } else {
+ unwrap (pScrPriv, pScreen, PaintWindowBorder);
+ (*pScreen->PaintWindowBorder) (pWindow, prgn, what);
+ wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow);
+ }
+}
+
+
+static void
+damageCopyWindow(WindowPtr pWindow,
+ DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ damageScrPriv(pScreen);
+
+ if (getWindowDamage (pWindow))
+ {
+ int dx = pWindow->drawable.x - ptOldOrg.x;
+ int dy = pWindow->drawable.y - ptOldOrg.y;
+
+ /*
+ * The region comes in source relative, but the damage occurs
+ * at the destination location. Translate back and forth.
+ */
+ REGION_TRANSLATE (pScreen, prgnSrc, dx, dy);
+ damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE);
+ REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
+ }
+ unwrap (pScrPriv, pScreen, CopyWindow);
+ (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
+ wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
+}
+
+GCOps damageGCOps = {
+ damageFillSpans, damageSetSpans,
+ damagePutImage, damageCopyArea,
+ damageCopyPlane, damagePolyPoint,
+ damagePolylines, damagePolySegment,
+ damagePolyRectangle, damagePolyArc,
+ damageFillPolygon, damagePolyFillRect,
+ damagePolyFillArc, damagePolyText8,
+ damagePolyText16, damageImageText8,
+ damageImageText16, damageImageGlyphBlt,
+ damagePolyGlyphBlt, damagePushPixels,
+#ifdef NEED_LINEHELPER
+ NULL,
+#endif
+ {NULL} /* devPrivate */
+};
+
+static void
+damageRestoreAreas (PixmapPtr pPixmap,
+ RegionPtr prgn,
+ int xorg,
+ int yorg,
+ WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ damageScrPriv(pScreen);
+
+ damageDamageRegion (&pWindow->drawable, prgn, FALSE);
+ unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
+ (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn,
+ xorg, yorg, pWindow);
+ wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
+ damageRestoreAreas);
+}
+
+static void
+damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
+{
+ DamagePtr pDamage;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ damageScrPriv(pScreen);
+
+ if ((pDamage = damageGetWinPriv(pWindow)))
+ {
+ PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow);
+ DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap);
+
+ while (pDamage)
+ {
+ damageRemoveDamage (pPrev, pDamage);
+ pDamage = pDamage->pNextWin;
+ }
+ }
+ unwrap (pScrPriv, pScreen, SetWindowPixmap);
+ (*pScreen->SetWindowPixmap) (pWindow, pPixmap);
+ wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
+ if ((pDamage = damageGetWinPriv(pWindow)))
+ {
+ DamagePtr *pPrev = getPixmapDamageRef(pPixmap);
+
+ while (pDamage)
+ {
+ damageInsertDamage (pPrev, pDamage);
+ pDamage = pDamage->pNextWin;
+ }
+ }
+}
+
+static Bool
+damageDestroyWindow (WindowPtr pWindow)
+{
+ DamagePtr pDamage;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ Bool ret;
+ damageScrPriv(pScreen);
+
+ while ((pDamage = damageGetWinPriv(pWindow)))
+ {
+ DamageUnregister (&pWindow->drawable, pDamage);
+ DamageDestroy (pDamage);
+ }
+ unwrap (pScrPriv, pScreen, DestroyWindow);
+ ret = (*pScreen->DestroyWindow) (pWindow);
+ wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
+ return ret;
+}
+
+static Bool
+damageCloseScreen (int i, ScreenPtr pScreen)
+{
+ damageScrPriv(pScreen);
+
+ unwrap (pScrPriv, pScreen, DestroyPixmap);
+ unwrap (pScrPriv, pScreen, CreateGC);
+ unwrap (pScrPriv, pScreen, PaintWindowBackground);
+ unwrap (pScrPriv, pScreen, PaintWindowBorder);
+ unwrap (pScrPriv, pScreen, CopyWindow);
+ unwrap (pScrPriv, pScreen, CloseScreen);
+ unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
+ xfree (pScrPriv);
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+int damageScrPrivateIndex;
+int damagePixPrivateIndex;
+int damageGCPrivateIndex;
+int damageWinPrivateIndex;
+int damageGeneration;
+
+Bool
+DamageSetup (ScreenPtr pScreen)
+{
+ DamageScrPrivPtr pScrPriv;
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+ if (damageGeneration != serverGeneration)
+ {
+ damageScrPrivateIndex = AllocateScreenPrivateIndex ();
+ if (damageScrPrivateIndex == -1)
+ return FALSE;
+ damageGCPrivateIndex = AllocateGCPrivateIndex ();
+ if (damageGCPrivateIndex == -1)
+ return FALSE;
+ damagePixPrivateIndex = AllocatePixmapPrivateIndex ();
+ if (damagePixPrivateIndex == -1)
+ return FALSE;
+ damageWinPrivateIndex = AllocateWindowPrivateIndex ();
+ if (damageWinPrivateIndex == -1)
+ return FALSE;
+ damageGeneration = serverGeneration;
+ }
+ if (pScreen->devPrivates[damageScrPrivateIndex].ptr)
+ return TRUE;
+
+ if (!AllocateGCPrivate (pScreen, damageGCPrivateIndex, sizeof (DamageGCPrivRec)))
+ return FALSE;
+ if (!AllocatePixmapPrivate (pScreen, damagePixPrivateIndex, 0))
+ return FALSE;
+ if (!AllocateWindowPrivate (pScreen, damageWinPrivateIndex, 0))
+ return FALSE;
+
+ pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec));
+ if (!pScrPriv)
+ return FALSE;
+
+#ifdef COMPOSITE
+ /* This is a kludge to ensure wrapping order with the composite wrapper.
+ * If it's done from compinit.c, then DamageSetup may be called before the
+ * extension init phase, so that cw will be higher in the wrapping chain and
+ * rewrite drawables before damage gets to it, causing confusion.
+ */
+ if (!noCompositeExtension)
+ miInitializeCompositeWrapper (pScreen);
+#endif
+
+ pScrPriv->internalLevel = 0;
+ pScrPriv->pScreenDamage = 0;
+
+ wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
+ wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
+ wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow);
+ wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow);
+ wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
+ wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
+ wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
+ wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen);
+ wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
+ damageRestoreAreas);
+#ifdef RENDER
+ if (ps) {
+ wrap (pScrPriv, ps, Glyphs, damageGlyphs);
+ wrap (pScrPriv, ps, Composite, damageComposite);
+ }
+#endif
+
+ pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv;
+ return TRUE;
+}
+
+DamagePtr
+DamageCreate (DamageReportFunc damageReport,
+ DamageDestroyFunc damageDestroy,
+ DamageReportLevel damageLevel,
+ Bool isInternal,
+ ScreenPtr pScreen,
+ void *closure)
+{
+ DamagePtr pDamage;
+
+ pDamage = xalloc (sizeof (DamageRec));
+ if (!pDamage)
+ return 0;
+ pDamage->pNext = 0;
+ pDamage->pNextWin = 0;
+ REGION_NULL(pScreen, &pDamage->damage);
+
+ pDamage->damageLevel = damageLevel;
+ pDamage->isInternal = isInternal;
+ pDamage->closure = closure;
+ pDamage->isWindow = FALSE;
+ pDamage->pDrawable = 0;
+
+ pDamage->damageReport = damageReport;
+ pDamage->damageDestroy = damageDestroy;
+ return pDamage;
+}
+
+void
+DamageRegister (DrawablePtr pDrawable,
+ DamagePtr pDamage)
+{
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWindow = (WindowPtr) pDrawable;
+ winDamageRef(pWindow);
+
+#if DAMAGE_VALIDATE_ENABLE
+ DamagePtr pOld;
+
+ for (pOld = *pPrev; pOld; pOld = pOld->pNextWin)
+ if (pOld == pDamage) {
+ ErrorF ("Damage already on window list\n");
+ abort ();
+ }
+#endif
+ pDamage->pNextWin = *pPrev;
+ *pPrev = pDamage;
+ pDamage->isWindow = TRUE;
+ }
+ else
+ pDamage->isWindow = FALSE;
+ pDamage->pDrawable = pDrawable;
+ damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage);
+}
+
+void
+DamageDrawInternal (ScreenPtr pScreen, Bool enable)
+{
+ damageScrPriv (pScreen);
+
+ pScrPriv->internalLevel += enable ? 1 : -1;
+}
+
+void
+DamageUnregister (DrawablePtr pDrawable,
+ DamagePtr pDamage)
+{
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWindow = (WindowPtr) pDrawable;
+ winDamageRef (pWindow);
+#if DAMAGE_VALIDATE_ENABLE
+ int found = 0;
+#endif
+
+ while (*pPrev)
+ {
+ if (*pPrev == pDamage)
+ {
+ *pPrev = pDamage->pNextWin;
+#if DAMAGE_VALIDATE_ENABLE
+ found = 1;
+#endif
+ break;
+ }
+ pPrev = &(*pPrev)->pNextWin;
+ }
+#if DAMAGE_VALIDATE_ENABLE
+ if (!found) {
+ ErrorF ("Damage not on window list\n");
+ abort ();
+ }
+#endif
+ }
+ pDamage->pDrawable = 0;
+ damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage);
+}
+
+void
+DamageDestroy (DamagePtr pDamage)
+{
+ if (pDamage->damageDestroy)
+ (*pDamage->damageDestroy) (pDamage, pDamage->closure);
+ REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage);
+ xfree (pDamage);
+}
+
+Bool
+DamageSubtract (DamagePtr pDamage,
+ const RegionPtr pRegion)
+{
+ RegionPtr pClip;
+ RegionRec pixmapClip;
+ DrawablePtr pDrawable = pDamage->pDrawable;
+
+ REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion);
+ if (pDrawable)
+ {
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ pClip = &((WindowPtr) pDrawable)->borderClip;
+ else
+ {
+ BoxRec box;
+
+ box.x1 = pDrawable->x;
+ box.y1 = pDrawable->y;
+ box.x2 = pDrawable->x + pDrawable->width;
+ box.y2 = pDrawable->y + pDrawable->height;
+ REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1);
+ pClip = &pixmapClip;
+ }
+ REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y);
+ REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip);
+ REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y);
+ }
+ return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage);
+}
+
+void
+DamageEmpty (DamagePtr pDamage)
+{
+ REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage);
+}
+
+RegionPtr
+DamageRegion (DamagePtr pDamage)
+{
+ return &pDamage->damage;
+}
+
+void
+DamageDamageRegion (DrawablePtr pDrawable,
+ RegionPtr pRegion)
+{
+ damageDamageRegion (pDrawable, pRegion, FALSE);
+}