xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

damage.c (58449B)


      1 /*
      2  * Copyright © 2003 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that
      7  * copyright notice and this permission notice appear in supporting
      8  * documentation, and that the name of Keith Packard not be used in
      9  * advertising or publicity pertaining to distribution of the software without
     10  * specific, written prior permission.  Keith Packard makes no
     11  * representations about the suitability of this software for any purpose.  It
     12  * is provided "as is" without express or implied warranty.
     13  *
     14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     20  * PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 #ifdef HAVE_DIX_CONFIG_H
     24 #include <dix-config.h>
     25 #endif
     26 
     27 #include <stdlib.h>
     28 
     29 #include    <X11/X.h>
     30 #include    "scrnintstr.h"
     31 #include    "windowstr.h"
     32 #include    <X11/fonts/font.h>
     33 #include    "dixfontstr.h"
     34 #include    <X11/fonts/fontstruct.h>
     35 #include    <X11/fonts/libxfont2.h>
     36 #include    "mi.h"
     37 #include    "mipict.h"
     38 #include    "regionstr.h"
     39 #include    "globals.h"
     40 #include    "gcstruct.h"
     41 #include    "damage.h"
     42 #include    "damagestr.h"
     43 
     44 #define wrap(priv, real, mem, func) {\
     45     priv->mem = real->mem; \
     46     real->mem = func; \
     47 }
     48 
     49 #define unwrap(priv, real, mem) {\
     50     real->mem = priv->mem; \
     51 }
     52 
     53 #define BOX_SAME(a,b) \
     54     ((a)->x1 == (b)->x1 && \
     55      (a)->y1 == (b)->y1 && \
     56      (a)->x2 == (b)->x2 && \
     57      (a)->y2 == (b)->y2)
     58 
     59 #define DAMAGE_VALIDATE_ENABLE 0
     60 #define DAMAGE_DEBUG_ENABLE 0
     61 #if DAMAGE_DEBUG_ENABLE
     62 #define DAMAGE_DEBUG(x)	ErrorF x
     63 #else
     64 #define DAMAGE_DEBUG(x)
     65 #endif
     66 
     67 #define getPixmapDamageRef(pPixmap) ((DamagePtr *) \
     68     dixLookupPrivateAddr(&(pPixmap)->devPrivates, damagePixPrivateKey))
     69 
     70 #define pixmapDamage(pPixmap)		damagePixPriv(pPixmap)
     71 
     72 static DevPrivateKeyRec damageScrPrivateKeyRec;
     73 
     74 #define damageScrPrivateKey (&damageScrPrivateKeyRec)
     75 static DevPrivateKeyRec damagePixPrivateKeyRec;
     76 
     77 #define damagePixPrivateKey (&damagePixPrivateKeyRec)
     78 static DevPrivateKeyRec damageGCPrivateKeyRec;
     79 
     80 #define damageGCPrivateKey (&damageGCPrivateKeyRec)
     81 static DevPrivateKeyRec damageWinPrivateKeyRec;
     82 
     83 #define damageWinPrivateKey (&damageWinPrivateKeyRec)
     84 
     85 static DamagePtr *
     86 getDrawableDamageRef(DrawablePtr pDrawable)
     87 {
     88     PixmapPtr pPixmap;
     89 
     90     if (WindowDrawable(pDrawable->type)) {
     91         ScreenPtr pScreen = pDrawable->pScreen;
     92 
     93         pPixmap = 0;
     94         if (pScreen->GetWindowPixmap
     95 #ifdef ROOTLESS_WORKAROUND
     96             && ((WindowPtr) pDrawable)->viewable
     97 #endif
     98             )
     99             pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) pDrawable);
    100 
    101         if (!pPixmap) {
    102             damageScrPriv(pScreen);
    103 
    104             return &pScrPriv->pScreenDamage;
    105         }
    106     }
    107     else
    108         pPixmap = (PixmapPtr) pDrawable;
    109     return getPixmapDamageRef(pPixmap);
    110 }
    111 
    112 #define getDrawableDamage(pDrawable)	(*getDrawableDamageRef (pDrawable))
    113 #define getWindowDamage(pWin)		getDrawableDamage(&(pWin)->drawable)
    114 
    115 #define drawableDamage(pDrawable)	\
    116     DamagePtr	pDamage = getDrawableDamage(pDrawable)
    117 
    118 #define windowDamage(pWin)		drawableDamage(&(pWin)->drawable)
    119 
    120 #define winDamageRef(pWindow) \
    121     DamagePtr	*pPrev = (DamagePtr *) \
    122 	dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey)
    123 
    124 #if DAMAGE_DEBUG_ENABLE
    125 static void
    126 _damageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
    127                     int subWindowMode, const char *where)
    128 #define damageRegionAppend(d,r,c,m) _damageRegionAppend(d,r,c,m,__FUNCTION__)
    129 #else
    130 static void
    131 damageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
    132                    int subWindowMode)
    133 #endif
    134 {
    135     ScreenPtr pScreen = pDrawable->pScreen;
    136 
    137     damageScrPriv(pScreen);
    138     drawableDamage(pDrawable);
    139     DamagePtr pNext;
    140     RegionRec clippedRec;
    141     RegionPtr pDamageRegion;
    142     RegionRec pixClip;
    143     int draw_x, draw_y;
    144 
    145 #ifdef COMPOSITE
    146     int screen_x = 0, screen_y = 0;
    147 #endif
    148 
    149     /* short circuit for empty regions */
    150     if (!RegionNotEmpty(pRegion))
    151         return;
    152 
    153 #ifdef COMPOSITE
    154     /*
    155      * When drawing to a pixmap which is storing window contents,
    156      * the region presented is in pixmap relative coordinates which
    157      * need to be converted to screen relative coordinates
    158      */
    159     if (pDrawable->type != DRAWABLE_WINDOW) {
    160         screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x;
    161         screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y;
    162     }
    163     if (screen_x || screen_y)
    164         RegionTranslate(pRegion, screen_x, screen_y);
    165 #endif
    166 
    167     if (pDrawable->type == DRAWABLE_WINDOW &&
    168         ((WindowPtr) (pDrawable))->backingStore == NotUseful) {
    169         if (subWindowMode == ClipByChildren) {
    170             RegionIntersect(pRegion, pRegion,
    171                             &((WindowPtr) (pDrawable))->clipList);
    172         }
    173         else if (subWindowMode == IncludeInferiors) {
    174             RegionPtr pTempRegion =
    175                 NotClippedByChildren((WindowPtr) (pDrawable));
    176             RegionIntersect(pRegion, pRegion, pTempRegion);
    177             RegionDestroy(pTempRegion);
    178         }
    179         /* If subWindowMode is set to an invalid value, don't perform
    180          * any drawable-based clipping. */
    181     }
    182 
    183     RegionNull(&clippedRec);
    184     for (; pDamage; pDamage = pNext) {
    185         pNext = pDamage->pNext;
    186         /*
    187          * Check for internal damage and don't send events
    188          */
    189         if (pScrPriv->internalLevel > 0 && !pDamage->isInternal) {
    190             DAMAGE_DEBUG(("non internal damage, skipping at %d\n",
    191                           pScrPriv->internalLevel));
    192             continue;
    193         }
    194         /*
    195          * Check for unrealized windows
    196          */
    197         if (pDamage->pDrawable->type == DRAWABLE_WINDOW &&
    198             !((WindowPtr) (pDamage->pDrawable))->realized) {
    199             continue;
    200         }
    201 
    202         draw_x = pDamage->pDrawable->x;
    203         draw_y = pDamage->pDrawable->y;
    204 #ifdef COMPOSITE
    205         /*
    206          * Need to move everyone to screen coordinates
    207          * XXX what about off-screen pixmaps with non-zero x/y?
    208          */
    209         if (!WindowDrawable(pDamage->pDrawable->type)) {
    210             draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x;
    211             draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y;
    212         }
    213 #endif
    214 
    215         /*
    216          * Clip against border or pixmap bounds
    217          */
    218 
    219         pDamageRegion = pRegion;
    220         if (clip || pDamage->pDrawable != pDrawable) {
    221             pDamageRegion = &clippedRec;
    222             if (pDamage->pDrawable->type == DRAWABLE_WINDOW) {
    223                 RegionIntersect(pDamageRegion, pRegion,
    224                                 &((WindowPtr) (pDamage->pDrawable))->
    225                                 borderClip);
    226             }
    227             else {
    228                 BoxRec box;
    229 
    230                 box.x1 = draw_x;
    231                 box.y1 = draw_y;
    232                 box.x2 = draw_x + pDamage->pDrawable->width;
    233                 box.y2 = draw_y + pDamage->pDrawable->height;
    234                 RegionInit(&pixClip, &box, 1);
    235                 RegionIntersect(pDamageRegion, pRegion, &pixClip);
    236                 RegionUninit(&pixClip);
    237             }
    238             /*
    239              * Short circuit empty results
    240              */
    241             if (!RegionNotEmpty(pDamageRegion))
    242                 continue;
    243         }
    244 
    245         DAMAGE_DEBUG(("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
    246                       where,
    247                       pDamageRegion->extents.x2 - pDamageRegion->extents.x1,
    248                       pDamageRegion->extents.y2 - pDamageRegion->extents.y1,
    249                       pDamageRegion->extents.x1, pDamageRegion->extents.y1,
    250                       pDrawable->id, pDamage->pDrawable->id));
    251 
    252         /*
    253          * Move region to target coordinate space
    254          */
    255         if (draw_x || draw_y)
    256             RegionTranslate(pDamageRegion, -draw_x, -draw_y);
    257 
    258         /* Store damage region if needed after submission. */
    259         if (pDamage->reportAfter)
    260             RegionUnion(&pDamage->pendingDamage,
    261                         &pDamage->pendingDamage, pDamageRegion);
    262 
    263         /* Report damage now, if desired. */
    264         if (!pDamage->reportAfter) {
    265             if (pDamage->damageReport)
    266                 DamageReportDamage(pDamage, pDamageRegion);
    267             else
    268                 RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
    269         }
    270 
    271         /*
    272          * translate original region back
    273          */
    274         if (pDamageRegion == pRegion && (draw_x || draw_y))
    275             RegionTranslate(pDamageRegion, draw_x, draw_y);
    276     }
    277 #ifdef COMPOSITE
    278     if (screen_x || screen_y)
    279         RegionTranslate(pRegion, -screen_x, -screen_y);
    280 #endif
    281 
    282     RegionUninit(&clippedRec);
    283 }
    284 
    285 static void
    286 damageRegionProcessPending(DrawablePtr pDrawable)
    287 {
    288     drawableDamage(pDrawable);
    289 
    290     for (; pDamage != NULL; pDamage = pDamage->pNext) {
    291         if (pDamage->reportAfter) {
    292             /* It's possible that there is only interest in postRendering reporting. */
    293             if (pDamage->damageReport)
    294                 DamageReportDamage(pDamage, &pDamage->pendingDamage);
    295             else
    296                 RegionUnion(&pDamage->damage, &pDamage->damage,
    297                             &pDamage->pendingDamage);
    298         }
    299 
    300         if (pDamage->reportAfter)
    301             RegionEmpty(&pDamage->pendingDamage);
    302     }
    303 
    304 }
    305 
    306 #if DAMAGE_DEBUG_ENABLE
    307 #define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
    308 static void
    309 _damageDamageBox(DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode,
    310                  const char *where)
    311 #else
    312 static void
    313 damageDamageBox(DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode)
    314 #endif
    315 {
    316     RegionRec region;
    317 
    318     RegionInit(&region, pBox, 1);
    319 #if DAMAGE_DEBUG_ENABLE
    320     _damageRegionAppend(pDrawable, &region, TRUE, subWindowMode, where);
    321 #else
    322     damageRegionAppend(pDrawable, &region, TRUE, subWindowMode);
    323 #endif
    324     RegionUninit(&region);
    325 }
    326 
    327 static void damageValidateGC(GCPtr, unsigned long, DrawablePtr);
    328 static void damageChangeGC(GCPtr, unsigned long);
    329 static void damageCopyGC(GCPtr, unsigned long, GCPtr);
    330 static void damageDestroyGC(GCPtr);
    331 static void damageChangeClip(GCPtr, int, void *, int);
    332 static void damageDestroyClip(GCPtr);
    333 static void damageCopyClip(GCPtr, GCPtr);
    334 
    335 static GCFuncs damageGCFuncs = {
    336     damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC,
    337     damageChangeClip, damageDestroyClip, damageCopyClip
    338 };
    339 
    340 static GCOps damageGCOps;
    341 
    342 static Bool
    343 damageCreateGC(GCPtr pGC)
    344 {
    345     ScreenPtr pScreen = pGC->pScreen;
    346 
    347     damageScrPriv(pScreen);
    348     damageGCPriv(pGC);
    349     Bool ret;
    350 
    351     unwrap(pScrPriv, pScreen, CreateGC);
    352     if ((ret = (*pScreen->CreateGC) (pGC))) {
    353         pGCPriv->ops = NULL;
    354         pGCPriv->funcs = pGC->funcs;
    355         pGC->funcs = &damageGCFuncs;
    356     }
    357     wrap(pScrPriv, pScreen, CreateGC, damageCreateGC);
    358 
    359     return ret;
    360 }
    361 
    362 #define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
    363     damageGCPriv(pGC);  \
    364     const GCFuncs *oldFuncs = pGC->funcs; \
    365     unwrap(pGCPriv, pGC, funcs);  \
    366     unwrap(pGCPriv, pGC, ops); \
    367 
    368 #define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
    369     wrap(pGCPriv, pGC, funcs, oldFuncs); \
    370     wrap(pGCPriv, pGC, ops, &damageGCOps)
    371 
    372 #define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
    373     damageGCPriv(pGC); \
    374     unwrap(pGCPriv, pGC, funcs); \
    375     if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
    376 
    377 #define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
    378     wrap(pGCPriv, pGC, funcs, &damageGCFuncs);  \
    379     if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
    380 
    381 static void
    382 damageValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
    383 {
    384     DAMAGE_GC_FUNC_PROLOGUE(pGC);
    385     (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
    386     pGCPriv->ops = pGC->ops; /* just so it's not NULL */
    387     DAMAGE_GC_FUNC_EPILOGUE(pGC);
    388 }
    389 
    390 static void
    391 damageDestroyGC(GCPtr pGC)
    392 {
    393     DAMAGE_GC_FUNC_PROLOGUE(pGC);
    394     (*pGC->funcs->DestroyGC) (pGC);
    395     DAMAGE_GC_FUNC_EPILOGUE(pGC);
    396 }
    397 
    398 static void
    399 damageChangeGC(GCPtr pGC, unsigned long mask)
    400 {
    401     DAMAGE_GC_FUNC_PROLOGUE(pGC);
    402     (*pGC->funcs->ChangeGC) (pGC, mask);
    403     DAMAGE_GC_FUNC_EPILOGUE(pGC);
    404 }
    405 
    406 static void
    407 damageCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
    408 {
    409     DAMAGE_GC_FUNC_PROLOGUE(pGCDst);
    410     (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
    411     DAMAGE_GC_FUNC_EPILOGUE(pGCDst);
    412 }
    413 
    414 static void
    415 damageChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
    416 {
    417     DAMAGE_GC_FUNC_PROLOGUE(pGC);
    418     (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
    419     DAMAGE_GC_FUNC_EPILOGUE(pGC);
    420 }
    421 
    422 static void
    423 damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
    424 {
    425     DAMAGE_GC_FUNC_PROLOGUE(pgcDst);
    426     (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc);
    427     DAMAGE_GC_FUNC_EPILOGUE(pgcDst);
    428 }
    429 
    430 static void
    431 damageDestroyClip(GCPtr pGC)
    432 {
    433     DAMAGE_GC_FUNC_PROLOGUE(pGC);
    434     (*pGC->funcs->DestroyClip) (pGC);
    435     DAMAGE_GC_FUNC_EPILOGUE(pGC);
    436 }
    437 
    438 #define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
    439     BoxPtr extents = &pGC->pCompositeClip->extents;\
    440     if(box.x1 < extents->x1) box.x1 = extents->x1; \
    441     if(box.x2 > extents->x2) box.x2 = extents->x2; \
    442     if(box.y1 < extents->y1) box.y1 = extents->y1; \
    443     if(box.y2 > extents->y2) box.y2 = extents->y2; \
    444     }
    445 
    446 #define TRANSLATE_BOX(box, pDrawable) { \
    447     box.x1 += pDrawable->x; \
    448     box.x2 += pDrawable->x; \
    449     box.y1 += pDrawable->y; \
    450     box.y2 += pDrawable->y; \
    451     }
    452 
    453 #define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
    454     TRANSLATE_BOX(box, pDrawable); \
    455     TRIM_BOX(box, pGC); \
    456     }
    457 
    458 #define BOX_NOT_EMPTY(box) \
    459     (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
    460 
    461 #define checkGCDamage(d,g)	(getDrawableDamage(d) && \
    462 				 (!g->pCompositeClip ||\
    463 				  RegionNotEmpty(g->pCompositeClip)))
    464 
    465 #define TRIM_PICTURE_BOX(box, pDst) { \
    466     BoxPtr extents = &pDst->pCompositeClip->extents;\
    467     if(box.x1 < extents->x1) box.x1 = extents->x1; \
    468     if(box.x2 > extents->x2) box.x2 = extents->x2; \
    469     if(box.y1 < extents->y1) box.y1 = extents->y1; \
    470     if(box.y2 > extents->y2) box.y2 = extents->y2; \
    471     }
    472 
    473 #define checkPictureDamage(p)	(getDrawableDamage(p->pDrawable) && \
    474 				 RegionNotEmpty(p->pCompositeClip))
    475 
    476 static void
    477 damageComposite(CARD8 op,
    478                 PicturePtr pSrc,
    479                 PicturePtr pMask,
    480                 PicturePtr pDst,
    481                 INT16 xSrc,
    482                 INT16 ySrc,
    483                 INT16 xMask,
    484                 INT16 yMask,
    485                 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
    486 {
    487     ScreenPtr pScreen = pDst->pDrawable->pScreen;
    488     PictureScreenPtr ps = GetPictureScreen(pScreen);
    489 
    490     damageScrPriv(pScreen);
    491 
    492     if (checkPictureDamage(pDst)) {
    493         BoxRec box;
    494 
    495         box.x1 = xDst + pDst->pDrawable->x;
    496         box.y1 = yDst + pDst->pDrawable->y;
    497         box.x2 = box.x1 + width;
    498         box.y2 = box.y1 + height;
    499         TRIM_PICTURE_BOX(box, pDst);
    500         if (BOX_NOT_EMPTY(box))
    501             damageDamageBox(pDst->pDrawable, &box, pDst->subWindowMode);
    502     }
    503     /*
    504      * Validating a source picture bound to a window may trigger other
    505      * composite operations. Do it before unwrapping to make sure damage
    506      * is reported correctly.
    507      */
    508     if (pSrc->pDrawable && WindowDrawable(pSrc->pDrawable->type))
    509         miCompositeSourceValidate(pSrc);
    510     if (pMask && pMask->pDrawable && WindowDrawable(pMask->pDrawable->type))
    511         miCompositeSourceValidate(pMask);
    512     unwrap(pScrPriv, ps, Composite);
    513     (*ps->Composite) (op,
    514                       pSrc,
    515                       pMask,
    516                       pDst,
    517                       xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
    518     damageRegionProcessPending(pDst->pDrawable);
    519     wrap(pScrPriv, ps, Composite, damageComposite);
    520 }
    521 
    522 static void
    523 damageGlyphs(CARD8 op,
    524              PicturePtr pSrc,
    525              PicturePtr pDst,
    526              PictFormatPtr maskFormat,
    527              INT16 xSrc,
    528              INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
    529 {
    530     ScreenPtr pScreen = pDst->pDrawable->pScreen;
    531     PictureScreenPtr ps = GetPictureScreen(pScreen);
    532 
    533     damageScrPriv(pScreen);
    534 
    535     if (checkPictureDamage(pDst)) {
    536         int nlistTmp = nlist;
    537         GlyphListPtr listTmp = list;
    538         GlyphPtr *glyphsTmp = glyphs;
    539         int x, y;
    540         int n;
    541         GlyphPtr glyph;
    542         BoxRec box;
    543         int x1, y1, x2, y2;
    544 
    545         box.x1 = 32767;
    546         box.y1 = 32767;
    547         box.x2 = -32767;
    548         box.y2 = -32767;
    549         x = pDst->pDrawable->x;
    550         y = pDst->pDrawable->y;
    551         while (nlistTmp--) {
    552             x += listTmp->xOff;
    553             y += listTmp->yOff;
    554             n = listTmp->len;
    555             while (n--) {
    556                 glyph = *glyphsTmp++;
    557                 x1 = x - glyph->info.x;
    558                 y1 = y - glyph->info.y;
    559                 x2 = x1 + glyph->info.width;
    560                 y2 = y1 + glyph->info.height;
    561                 if (x1 < box.x1)
    562                     box.x1 = x1;
    563                 if (y1 < box.y1)
    564                     box.y1 = y1;
    565                 if (x2 > box.x2)
    566                     box.x2 = x2;
    567                 if (y2 > box.y2)
    568                     box.y2 = y2;
    569                 x += glyph->info.xOff;
    570                 y += glyph->info.yOff;
    571             }
    572             listTmp++;
    573         }
    574         TRIM_PICTURE_BOX(box, pDst);
    575         if (BOX_NOT_EMPTY(box))
    576             damageDamageBox(pDst->pDrawable, &box, pDst->subWindowMode);
    577     }
    578     unwrap(pScrPriv, ps, Glyphs);
    579     (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
    580     damageRegionProcessPending(pDst->pDrawable);
    581     wrap(pScrPriv, ps, Glyphs, damageGlyphs);
    582 }
    583 
    584 static void
    585 damageAddTraps(PicturePtr pPicture,
    586                INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
    587 {
    588     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
    589     PictureScreenPtr ps = GetPictureScreen(pScreen);
    590 
    591     damageScrPriv(pScreen);
    592 
    593     if (checkPictureDamage(pPicture)) {
    594         BoxRec box;
    595         int i;
    596         int x, y;
    597         xTrap *t = traps;
    598 
    599         box.x1 = 32767;
    600         box.y1 = 32767;
    601         box.x2 = -32767;
    602         box.y2 = -32767;
    603         x = pPicture->pDrawable->x + x_off;
    604         y = pPicture->pDrawable->y + y_off;
    605         for (i = 0; i < ntrap; i++) {
    606             pixman_fixed_t l = min(t->top.l, t->bot.l);
    607             pixman_fixed_t r = max(t->top.r, t->bot.r);
    608             int x1 = x + pixman_fixed_to_int(l);
    609             int x2 = x + pixman_fixed_to_int(pixman_fixed_ceil(r));
    610             int y1 = y + pixman_fixed_to_int(t->top.y);
    611             int y2 = y + pixman_fixed_to_int(pixman_fixed_ceil(t->bot.y));
    612 
    613             if (x1 < box.x1)
    614                 box.x1 = x1;
    615             if (x2 > box.x2)
    616                 box.x2 = x2;
    617             if (y1 < box.y1)
    618                 box.y1 = y1;
    619             if (y2 > box.y2)
    620                 box.y2 = y2;
    621         }
    622         TRIM_PICTURE_BOX(box, pPicture);
    623         if (BOX_NOT_EMPTY(box))
    624             damageDamageBox(pPicture->pDrawable, &box, pPicture->subWindowMode);
    625     }
    626     unwrap(pScrPriv, ps, AddTraps);
    627     (*ps->AddTraps) (pPicture, x_off, y_off, ntrap, traps);
    628     damageRegionProcessPending(pPicture->pDrawable);
    629     wrap(pScrPriv, ps, AddTraps, damageAddTraps);
    630 }
    631 
    632 /**********************************************************/
    633 
    634 static void
    635 damageFillSpans(DrawablePtr pDrawable,
    636                 GC * pGC, int npt, DDXPointPtr ppt, int *pwidth, int fSorted)
    637 {
    638     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
    639 
    640     if (npt && checkGCDamage(pDrawable, pGC)) {
    641         int nptTmp = npt;
    642         DDXPointPtr pptTmp = ppt;
    643         int *pwidthTmp = pwidth;
    644         BoxRec box;
    645 
    646         box.x1 = pptTmp->x;
    647         box.x2 = box.x1 + *pwidthTmp;
    648         box.y2 = box.y1 = pptTmp->y;
    649 
    650         while (--nptTmp) {
    651             pptTmp++;
    652             pwidthTmp++;
    653             if (box.x1 > pptTmp->x)
    654                 box.x1 = pptTmp->x;
    655             if (box.x2 < (pptTmp->x + *pwidthTmp))
    656                 box.x2 = pptTmp->x + *pwidthTmp;
    657             if (box.y1 > pptTmp->y)
    658                 box.y1 = pptTmp->y;
    659             else if (box.y2 < pptTmp->y)
    660                 box.y2 = pptTmp->y;
    661         }
    662 
    663         box.y2++;
    664 
    665         if (!pGC->miTranslate) {
    666             TRANSLATE_BOX(box, pDrawable);
    667         }
    668         TRIM_BOX(box, pGC);
    669 
    670         if (BOX_NOT_EMPTY(box))
    671             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
    672     }
    673 
    674     (*pGC->ops->FillSpans) (pDrawable, pGC, npt, ppt, pwidth, fSorted);
    675 
    676     damageRegionProcessPending(pDrawable);
    677     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
    678 }
    679 
    680 static void
    681 damageSetSpans(DrawablePtr pDrawable,
    682                GCPtr pGC,
    683                char *pcharsrc,
    684                DDXPointPtr ppt, int *pwidth, int npt, int fSorted)
    685 {
    686     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
    687 
    688     if (npt && checkGCDamage(pDrawable, pGC)) {
    689         DDXPointPtr pptTmp = ppt;
    690         int *pwidthTmp = pwidth;
    691         int nptTmp = npt;
    692         BoxRec box;
    693 
    694         box.x1 = pptTmp->x;
    695         box.x2 = box.x1 + *pwidthTmp;
    696         box.y2 = box.y1 = pptTmp->y;
    697 
    698         while (--nptTmp) {
    699             pptTmp++;
    700             pwidthTmp++;
    701             if (box.x1 > pptTmp->x)
    702                 box.x1 = pptTmp->x;
    703             if (box.x2 < (pptTmp->x + *pwidthTmp))
    704                 box.x2 = pptTmp->x + *pwidthTmp;
    705             if (box.y1 > pptTmp->y)
    706                 box.y1 = pptTmp->y;
    707             else if (box.y2 < pptTmp->y)
    708                 box.y2 = pptTmp->y;
    709         }
    710 
    711         box.y2++;
    712 
    713         if (!pGC->miTranslate) {
    714             TRANSLATE_BOX(box, pDrawable);
    715         }
    716         TRIM_BOX(box, pGC);
    717 
    718         if (BOX_NOT_EMPTY(box))
    719             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
    720     }
    721     (*pGC->ops->SetSpans) (pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
    722     damageRegionProcessPending(pDrawable);
    723     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
    724 }
    725 
    726 static void
    727 damagePutImage(DrawablePtr pDrawable,
    728                GCPtr pGC,
    729                int depth,
    730                int x,
    731                int y, int w, int h, int leftPad, int format, char *pImage)
    732 {
    733     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
    734     if (checkGCDamage(pDrawable, pGC)) {
    735         BoxRec box;
    736 
    737         box.x1 = x + pDrawable->x;
    738         box.x2 = box.x1 + w;
    739         box.y1 = y + pDrawable->y;
    740         box.y2 = box.y1 + h;
    741 
    742         TRIM_BOX(box, pGC);
    743         if (BOX_NOT_EMPTY(box))
    744             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
    745     }
    746     (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h,
    747                            leftPad, format, pImage);
    748     damageRegionProcessPending(pDrawable);
    749     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
    750 }
    751 
    752 static RegionPtr
    753 damageCopyArea(DrawablePtr pSrc,
    754                DrawablePtr pDst,
    755                GC * pGC,
    756                int srcx, int srcy, int width, int height, int dstx, int dsty)
    757 {
    758     RegionPtr ret;
    759 
    760     DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
    761 
    762     if (checkGCDamage(pDst, pGC)) {
    763         BoxRec box;
    764 
    765         box.x1 = dstx + pDst->x;
    766         box.x2 = box.x1 + width;
    767         box.y1 = dsty + pDst->y;
    768         box.y2 = box.y1 + height;
    769 
    770         TRIM_BOX(box, pGC);
    771         if (BOX_NOT_EMPTY(box))
    772             damageDamageBox(pDst, &box, pGC->subWindowMode);
    773     }
    774 
    775     ret = (*pGC->ops->CopyArea) (pSrc, pDst,
    776                                  pGC, srcx, srcy, width, height, dstx, dsty);
    777     damageRegionProcessPending(pDst);
    778     DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
    779     return ret;
    780 }
    781 
    782 static RegionPtr
    783 damageCopyPlane(DrawablePtr pSrc,
    784                 DrawablePtr pDst,
    785                 GCPtr pGC,
    786                 int srcx,
    787                 int srcy,
    788                 int width,
    789                 int height, int dstx, int dsty, unsigned long bitPlane)
    790 {
    791     RegionPtr ret;
    792 
    793     DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
    794 
    795     if (checkGCDamage(pDst, pGC)) {
    796         BoxRec box;
    797 
    798         box.x1 = dstx + pDst->x;
    799         box.x2 = box.x1 + width;
    800         box.y1 = dsty + pDst->y;
    801         box.y2 = box.y1 + height;
    802 
    803         TRIM_BOX(box, pGC);
    804         if (BOX_NOT_EMPTY(box))
    805             damageDamageBox(pDst, &box, pGC->subWindowMode);
    806     }
    807 
    808     ret = (*pGC->ops->CopyPlane) (pSrc, pDst,
    809                                   pGC, srcx, srcy, width, height, dstx, dsty,
    810                                   bitPlane);
    811     damageRegionProcessPending(pDst);
    812     DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
    813     return ret;
    814 }
    815 
    816 static void
    817 damagePolyPoint(DrawablePtr pDrawable,
    818                 GCPtr pGC, int mode, int npt, xPoint * ppt)
    819 {
    820     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
    821 
    822     if (npt && checkGCDamage(pDrawable, pGC)) {
    823         BoxRec box;
    824         int nptTmp = npt;
    825         xPoint *pptTmp = ppt;
    826 
    827         box.x2 = box.x1 = pptTmp->x;
    828         box.y2 = box.y1 = pptTmp->y;
    829 
    830         /* this could be slow if the points were spread out */
    831 
    832         if (mode == CoordModePrevious) {
    833             int x = box.x1;
    834             int y = box.y1;
    835 
    836             while (--nptTmp) {
    837                 pptTmp++;
    838                 x += pptTmp->x;
    839                 y += pptTmp->y;
    840                 if (box.x1 > x)
    841                     box.x1 = x;
    842                 else if (box.x2 < x)
    843                     box.x2 = x;
    844                 if (box.y1 > y)
    845                     box.y1 = y;
    846                 else if (box.y2 < y)
    847                     box.y2 = y;
    848             }
    849         }
    850         else {
    851             while (--nptTmp) {
    852                 pptTmp++;
    853                 if (box.x1 > pptTmp->x)
    854                     box.x1 = pptTmp->x;
    855                 else if (box.x2 < pptTmp->x)
    856                     box.x2 = pptTmp->x;
    857                 if (box.y1 > pptTmp->y)
    858                     box.y1 = pptTmp->y;
    859                 else if (box.y2 < pptTmp->y)
    860                     box.y2 = pptTmp->y;
    861             }
    862         }
    863 
    864         box.x2++;
    865         box.y2++;
    866 
    867         TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
    868         if (BOX_NOT_EMPTY(box))
    869             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
    870     }
    871     (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, ppt);
    872     damageRegionProcessPending(pDrawable);
    873     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
    874 }
    875 
    876 static void
    877 damagePolylines(DrawablePtr pDrawable,
    878                 GCPtr pGC, int mode, int npt, DDXPointPtr ppt)
    879 {
    880     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
    881 
    882     if (npt && checkGCDamage(pDrawable, pGC)) {
    883         int nptTmp = npt;
    884         DDXPointPtr pptTmp = ppt;
    885         BoxRec box;
    886         int extra = pGC->lineWidth >> 1;
    887 
    888         box.x2 = box.x1 = pptTmp->x;
    889         box.y2 = box.y1 = pptTmp->y;
    890 
    891         if (nptTmp > 1) {
    892             if (pGC->joinStyle == JoinMiter)
    893                 extra = 6 * pGC->lineWidth;
    894             else if (pGC->capStyle == CapProjecting)
    895                 extra = pGC->lineWidth;
    896         }
    897 
    898         if (mode == CoordModePrevious) {
    899             int x = box.x1;
    900             int y = box.y1;
    901 
    902             while (--nptTmp) {
    903                 pptTmp++;
    904                 x += pptTmp->x;
    905                 y += pptTmp->y;
    906                 if (box.x1 > x)
    907                     box.x1 = x;
    908                 else if (box.x2 < x)
    909                     box.x2 = x;
    910                 if (box.y1 > y)
    911                     box.y1 = y;
    912                 else if (box.y2 < y)
    913                     box.y2 = y;
    914             }
    915         }
    916         else {
    917             while (--nptTmp) {
    918                 pptTmp++;
    919                 if (box.x1 > pptTmp->x)
    920                     box.x1 = pptTmp->x;
    921                 else if (box.x2 < pptTmp->x)
    922                     box.x2 = pptTmp->x;
    923                 if (box.y1 > pptTmp->y)
    924                     box.y1 = pptTmp->y;
    925                 else if (box.y2 < pptTmp->y)
    926                     box.y2 = pptTmp->y;
    927             }
    928         }
    929 
    930         box.x2++;
    931         box.y2++;
    932 
    933         if (extra) {
    934             box.x1 -= extra;
    935             box.x2 += extra;
    936             box.y1 -= extra;
    937             box.y2 += extra;
    938         }
    939 
    940         TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
    941         if (BOX_NOT_EMPTY(box))
    942             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
    943     }
    944     (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppt);
    945     damageRegionProcessPending(pDrawable);
    946     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
    947 }
    948 
    949 static void
    950 damagePolySegment(DrawablePtr pDrawable, GCPtr pGC, int nSeg, xSegment * pSeg)
    951 {
    952     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
    953 
    954     if (nSeg && checkGCDamage(pDrawable, pGC)) {
    955         BoxRec box;
    956         int extra = pGC->lineWidth;
    957         int nsegTmp = nSeg;
    958         xSegment *pSegTmp = pSeg;
    959 
    960         if (pGC->capStyle != CapProjecting)
    961             extra >>= 1;
    962 
    963         if (pSegTmp->x2 > pSegTmp->x1) {
    964             box.x1 = pSegTmp->x1;
    965             box.x2 = pSegTmp->x2;
    966         }
    967         else {
    968             box.x2 = pSegTmp->x1;
    969             box.x1 = pSegTmp->x2;
    970         }
    971 
    972         if (pSegTmp->y2 > pSegTmp->y1) {
    973             box.y1 = pSegTmp->y1;
    974             box.y2 = pSegTmp->y2;
    975         }
    976         else {
    977             box.y2 = pSegTmp->y1;
    978             box.y1 = pSegTmp->y2;
    979         }
    980 
    981         while (--nsegTmp) {
    982             pSegTmp++;
    983             if (pSegTmp->x2 > pSegTmp->x1) {
    984                 if (pSegTmp->x1 < box.x1)
    985                     box.x1 = pSegTmp->x1;
    986                 if (pSegTmp->x2 > box.x2)
    987                     box.x2 = pSegTmp->x2;
    988             }
    989             else {
    990                 if (pSegTmp->x2 < box.x1)
    991                     box.x1 = pSegTmp->x2;
    992                 if (pSegTmp->x1 > box.x2)
    993                     box.x2 = pSegTmp->x1;
    994             }
    995             if (pSegTmp->y2 > pSegTmp->y1) {
    996                 if (pSegTmp->y1 < box.y1)
    997                     box.y1 = pSegTmp->y1;
    998                 if (pSegTmp->y2 > box.y2)
    999                     box.y2 = pSegTmp->y2;
   1000             }
   1001             else {
   1002                 if (pSegTmp->y2 < box.y1)
   1003                     box.y1 = pSegTmp->y2;
   1004                 if (pSegTmp->y1 > box.y2)
   1005                     box.y2 = pSegTmp->y1;
   1006             }
   1007         }
   1008 
   1009         box.x2++;
   1010         box.y2++;
   1011 
   1012         if (extra) {
   1013             box.x1 -= extra;
   1014             box.x2 += extra;
   1015             box.y1 -= extra;
   1016             box.y2 += extra;
   1017         }
   1018 
   1019         TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1020         if (BOX_NOT_EMPTY(box))
   1021             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1022     }
   1023     (*pGC->ops->PolySegment) (pDrawable, pGC, nSeg, pSeg);
   1024     damageRegionProcessPending(pDrawable);
   1025     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1026 }
   1027 
   1028 static void
   1029 damagePolyRectangle(DrawablePtr pDrawable,
   1030                     GCPtr pGC, int nRects, xRectangle *pRects)
   1031 {
   1032     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1033 
   1034     if (nRects && checkGCDamage(pDrawable, pGC)) {
   1035         BoxRec box;
   1036         int offset1, offset2, offset3;
   1037         int nRectsTmp = nRects;
   1038         xRectangle *pRectsTmp = pRects;
   1039 
   1040         offset2 = pGC->lineWidth;
   1041         if (!offset2)
   1042             offset2 = 1;
   1043         offset1 = offset2 >> 1;
   1044         offset3 = offset2 - offset1;
   1045 
   1046         while (nRectsTmp--) {
   1047             box.x1 = pRectsTmp->x - offset1;
   1048             box.y1 = pRectsTmp->y - offset1;
   1049             box.x2 = box.x1 + pRectsTmp->width + offset2;
   1050             box.y2 = box.y1 + offset2;
   1051             TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1052             if (BOX_NOT_EMPTY(box))
   1053                 damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1054 
   1055             box.x1 = pRectsTmp->x - offset1;
   1056             box.y1 = pRectsTmp->y + offset3;
   1057             box.x2 = box.x1 + offset2;
   1058             box.y2 = box.y1 + pRectsTmp->height - offset2;
   1059             TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1060             if (BOX_NOT_EMPTY(box))
   1061                 damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1062 
   1063             box.x1 = pRectsTmp->x + pRectsTmp->width - offset1;
   1064             box.y1 = pRectsTmp->y + offset3;
   1065             box.x2 = box.x1 + offset2;
   1066             box.y2 = box.y1 + pRectsTmp->height - offset2;
   1067             TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1068             if (BOX_NOT_EMPTY(box))
   1069                 damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1070 
   1071             box.x1 = pRectsTmp->x - offset1;
   1072             box.y1 = pRectsTmp->y + pRectsTmp->height - offset1;
   1073             box.x2 = box.x1 + pRectsTmp->width + offset2;
   1074             box.y2 = box.y1 + offset2;
   1075             TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1076             if (BOX_NOT_EMPTY(box))
   1077                 damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1078 
   1079             pRectsTmp++;
   1080         }
   1081     }
   1082     (*pGC->ops->PolyRectangle) (pDrawable, pGC, nRects, pRects);
   1083     damageRegionProcessPending(pDrawable);
   1084     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1085 }
   1086 
   1087 static void
   1088 damagePolyArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc * pArcs)
   1089 {
   1090     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1091 
   1092     if (nArcs && checkGCDamage(pDrawable, pGC)) {
   1093         int extra = pGC->lineWidth >> 1;
   1094         BoxRec box;
   1095         int nArcsTmp = nArcs;
   1096         xArc *pArcsTmp = pArcs;
   1097 
   1098         box.x1 = pArcsTmp->x;
   1099         box.x2 = box.x1 + pArcsTmp->width;
   1100         box.y1 = pArcsTmp->y;
   1101         box.y2 = box.y1 + pArcsTmp->height;
   1102 
   1103         while (--nArcsTmp) {
   1104             pArcsTmp++;
   1105             if (box.x1 > pArcsTmp->x)
   1106                 box.x1 = pArcsTmp->x;
   1107             if (box.x2 < (pArcsTmp->x + pArcsTmp->width))
   1108                 box.x2 = pArcsTmp->x + pArcsTmp->width;
   1109             if (box.y1 > pArcsTmp->y)
   1110                 box.y1 = pArcsTmp->y;
   1111             if (box.y2 < (pArcsTmp->y + pArcsTmp->height))
   1112                 box.y2 = pArcsTmp->y + pArcsTmp->height;
   1113         }
   1114 
   1115         if (extra) {
   1116             box.x1 -= extra;
   1117             box.x2 += extra;
   1118             box.y1 -= extra;
   1119             box.y2 += extra;
   1120         }
   1121 
   1122         box.x2++;
   1123         box.y2++;
   1124 
   1125         TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1126         if (BOX_NOT_EMPTY(box))
   1127             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1128     }
   1129     (*pGC->ops->PolyArc) (pDrawable, pGC, nArcs, pArcs);
   1130     damageRegionProcessPending(pDrawable);
   1131     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1132 }
   1133 
   1134 static void
   1135 damageFillPolygon(DrawablePtr pDrawable,
   1136                   GCPtr pGC, int shape, int mode, int npt, DDXPointPtr ppt)
   1137 {
   1138     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1139 
   1140     if (npt > 2 && checkGCDamage(pDrawable, pGC)) {
   1141         DDXPointPtr pptTmp = ppt;
   1142         int nptTmp = npt;
   1143         BoxRec box;
   1144 
   1145         box.x2 = box.x1 = pptTmp->x;
   1146         box.y2 = box.y1 = pptTmp->y;
   1147 
   1148         if (mode != CoordModeOrigin) {
   1149             int x = box.x1;
   1150             int y = box.y1;
   1151 
   1152             while (--nptTmp) {
   1153                 pptTmp++;
   1154                 x += pptTmp->x;
   1155                 y += pptTmp->y;
   1156                 if (box.x1 > x)
   1157                     box.x1 = x;
   1158                 else if (box.x2 < x)
   1159                     box.x2 = x;
   1160                 if (box.y1 > y)
   1161                     box.y1 = y;
   1162                 else if (box.y2 < y)
   1163                     box.y2 = y;
   1164             }
   1165         }
   1166         else {
   1167             while (--nptTmp) {
   1168                 pptTmp++;
   1169                 if (box.x1 > pptTmp->x)
   1170                     box.x1 = pptTmp->x;
   1171                 else if (box.x2 < pptTmp->x)
   1172                     box.x2 = pptTmp->x;
   1173                 if (box.y1 > pptTmp->y)
   1174                     box.y1 = pptTmp->y;
   1175                 else if (box.y2 < pptTmp->y)
   1176                     box.y2 = pptTmp->y;
   1177             }
   1178         }
   1179 
   1180         box.x2++;
   1181         box.y2++;
   1182 
   1183         TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1184         if (BOX_NOT_EMPTY(box))
   1185             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1186     }
   1187 
   1188     (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, npt, ppt);
   1189     damageRegionProcessPending(pDrawable);
   1190     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1191 }
   1192 
   1193 static void
   1194 damagePolyFillRect(DrawablePtr pDrawable,
   1195                    GCPtr pGC, int nRects, xRectangle *pRects)
   1196 {
   1197     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1198     if (nRects && checkGCDamage(pDrawable, pGC)) {
   1199         BoxRec box;
   1200         xRectangle *pRectsTmp = pRects;
   1201         int nRectsTmp = nRects;
   1202 
   1203         box.x1 = pRectsTmp->x;
   1204         box.x2 = box.x1 + pRectsTmp->width;
   1205         box.y1 = pRectsTmp->y;
   1206         box.y2 = box.y1 + pRectsTmp->height;
   1207 
   1208         while (--nRectsTmp) {
   1209             pRectsTmp++;
   1210             if (box.x1 > pRectsTmp->x)
   1211                 box.x1 = pRectsTmp->x;
   1212             if (box.x2 < (pRectsTmp->x + pRectsTmp->width))
   1213                 box.x2 = pRectsTmp->x + pRectsTmp->width;
   1214             if (box.y1 > pRectsTmp->y)
   1215                 box.y1 = pRectsTmp->y;
   1216             if (box.y2 < (pRectsTmp->y + pRectsTmp->height))
   1217                 box.y2 = pRectsTmp->y + pRectsTmp->height;
   1218         }
   1219 
   1220         TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1221         if (BOX_NOT_EMPTY(box))
   1222             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1223     }
   1224     (*pGC->ops->PolyFillRect) (pDrawable, pGC, nRects, pRects);
   1225     damageRegionProcessPending(pDrawable);
   1226     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1227 }
   1228 
   1229 static void
   1230 damagePolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc * pArcs)
   1231 {
   1232     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1233 
   1234     if (nArcs && checkGCDamage(pDrawable, pGC)) {
   1235         BoxRec box;
   1236         int nArcsTmp = nArcs;
   1237         xArc *pArcsTmp = pArcs;
   1238 
   1239         box.x1 = pArcsTmp->x;
   1240         box.x2 = box.x1 + pArcsTmp->width;
   1241         box.y1 = pArcsTmp->y;
   1242         box.y2 = box.y1 + pArcsTmp->height;
   1243 
   1244         while (--nArcsTmp) {
   1245             pArcsTmp++;
   1246             if (box.x1 > pArcsTmp->x)
   1247                 box.x1 = pArcsTmp->x;
   1248             if (box.x2 < (pArcsTmp->x + pArcsTmp->width))
   1249                 box.x2 = pArcsTmp->x + pArcsTmp->width;
   1250             if (box.y1 > pArcsTmp->y)
   1251                 box.y1 = pArcsTmp->y;
   1252             if (box.y2 < (pArcsTmp->y + pArcsTmp->height))
   1253                 box.y2 = pArcsTmp->y + pArcsTmp->height;
   1254         }
   1255 
   1256         TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
   1257         if (BOX_NOT_EMPTY(box))
   1258             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1259     }
   1260     (*pGC->ops->PolyFillArc) (pDrawable, pGC, nArcs, pArcs);
   1261     damageRegionProcessPending(pDrawable);
   1262     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1263 }
   1264 
   1265 /*
   1266  * general Poly/Image text function.  Extract glyph information,
   1267  * compute bounding box and remove cursor if it is overlapped.
   1268  */
   1269 
   1270 static void
   1271 damageDamageChars(DrawablePtr pDrawable,
   1272                   FontPtr font,
   1273                   int x,
   1274                   int y,
   1275                   unsigned int n,
   1276                   CharInfoPtr * charinfo, Bool imageblt, int subWindowMode)
   1277 {
   1278     ExtentInfoRec extents;
   1279     BoxRec box;
   1280 
   1281     xfont2_query_glyph_extents(font, charinfo, n, &extents);
   1282     if (imageblt) {
   1283         if (extents.overallWidth > extents.overallRight)
   1284             extents.overallRight = extents.overallWidth;
   1285         if (extents.overallWidth < extents.overallLeft)
   1286             extents.overallLeft = extents.overallWidth;
   1287         if (extents.overallLeft > 0)
   1288             extents.overallLeft = 0;
   1289         if (extents.fontAscent > extents.overallAscent)
   1290             extents.overallAscent = extents.fontAscent;
   1291         if (extents.fontDescent > extents.overallDescent)
   1292             extents.overallDescent = extents.fontDescent;
   1293     }
   1294     box.x1 = x + extents.overallLeft;
   1295     box.y1 = y - extents.overallAscent;
   1296     box.x2 = x + extents.overallRight;
   1297     box.y2 = y + extents.overallDescent;
   1298     damageDamageBox(pDrawable, &box, subWindowMode);
   1299 }
   1300 
   1301 /*
   1302  * values for textType:
   1303  */
   1304 #define TT_POLY8   0
   1305 #define TT_IMAGE8  1
   1306 #define TT_POLY16  2
   1307 #define TT_IMAGE16 3
   1308 
   1309 static void
   1310 damageText(DrawablePtr pDrawable,
   1311            GCPtr pGC,
   1312            int x,
   1313            int y,
   1314            unsigned long count,
   1315            char *chars, FontEncoding fontEncoding, Bool textType)
   1316 {
   1317     CharInfoPtr *charinfo;
   1318     unsigned long i;
   1319     unsigned int n;
   1320     Bool imageblt;
   1321 
   1322     imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
   1323 
   1324     if (!checkGCDamage(pDrawable, pGC))
   1325         return;
   1326 
   1327     charinfo = xallocarray(count, sizeof(CharInfoPtr));
   1328     if (!charinfo)
   1329         return;
   1330 
   1331     GetGlyphs(pGC->font, count, (unsigned char *) chars,
   1332               fontEncoding, &i, charinfo);
   1333     n = (unsigned int) i;
   1334 
   1335     if (n != 0) {
   1336         damageDamageChars(pDrawable, pGC->font, x + pDrawable->x,
   1337                           y + pDrawable->y, n, charinfo, imageblt,
   1338                           pGC->subWindowMode);
   1339     }
   1340     free(charinfo);
   1341 }
   1342 
   1343 static int
   1344 damagePolyText8(DrawablePtr pDrawable,
   1345                 GCPtr pGC, int x, int y, int count, char *chars)
   1346 {
   1347     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1348     damageText(pDrawable, pGC, x, y, (unsigned long) count, chars, Linear8Bit,
   1349                TT_POLY8);
   1350     x = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
   1351     damageRegionProcessPending(pDrawable);
   1352     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1353     return x;
   1354 }
   1355 
   1356 static int
   1357 damagePolyText16(DrawablePtr pDrawable,
   1358                  GCPtr pGC, int x, int y, int count, unsigned short *chars)
   1359 {
   1360     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1361     damageText(pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
   1362                FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
   1363                TT_POLY16);
   1364     x = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
   1365     damageRegionProcessPending(pDrawable);
   1366     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1367     return x;
   1368 }
   1369 
   1370 static void
   1371 damageImageText8(DrawablePtr pDrawable,
   1372                  GCPtr pGC, int x, int y, int count, char *chars)
   1373 {
   1374     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1375     damageText(pDrawable, pGC, x, y, (unsigned long) count, chars, Linear8Bit,
   1376                TT_IMAGE8);
   1377     (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
   1378     damageRegionProcessPending(pDrawable);
   1379     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1380 }
   1381 
   1382 static void
   1383 damageImageText16(DrawablePtr pDrawable,
   1384                   GCPtr pGC, int x, int y, int count, unsigned short *chars)
   1385 {
   1386     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1387     damageText(pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
   1388                FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
   1389                TT_IMAGE16);
   1390     (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
   1391     damageRegionProcessPending(pDrawable);
   1392     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1393 }
   1394 
   1395 static void
   1396 damageImageGlyphBlt(DrawablePtr pDrawable,
   1397                     GCPtr pGC,
   1398                     int x,
   1399                     int y,
   1400                     unsigned int nglyph, CharInfoPtr * ppci, void *pglyphBase)
   1401 {
   1402     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1403     damageDamageChars(pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
   1404                       nglyph, ppci, TRUE, pGC->subWindowMode);
   1405     (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
   1406     damageRegionProcessPending(pDrawable);
   1407     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1408 }
   1409 
   1410 static void
   1411 damagePolyGlyphBlt(DrawablePtr pDrawable,
   1412                    GCPtr pGC,
   1413                    int x,
   1414                    int y,
   1415                    unsigned int nglyph, CharInfoPtr * ppci, void *pglyphBase)
   1416 {
   1417     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1418     damageDamageChars(pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
   1419                       nglyph, ppci, FALSE, pGC->subWindowMode);
   1420     (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
   1421     damageRegionProcessPending(pDrawable);
   1422     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1423 }
   1424 
   1425 static void
   1426 damagePushPixels(GCPtr pGC,
   1427                  PixmapPtr pBitMap,
   1428                  DrawablePtr pDrawable, int dx, int dy, int xOrg, int yOrg)
   1429 {
   1430     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
   1431     if (checkGCDamage(pDrawable, pGC)) {
   1432         BoxRec box;
   1433 
   1434         box.x1 = xOrg;
   1435         box.y1 = yOrg;
   1436 
   1437         if (!pGC->miTranslate) {
   1438             box.x1 += pDrawable->x;
   1439             box.y1 += pDrawable->y;
   1440         }
   1441 
   1442         box.x2 = box.x1 + dx;
   1443         box.y2 = box.y1 + dy;
   1444 
   1445         TRIM_BOX(box, pGC);
   1446         if (BOX_NOT_EMPTY(box))
   1447             damageDamageBox(pDrawable, &box, pGC->subWindowMode);
   1448     }
   1449     (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
   1450     damageRegionProcessPending(pDrawable);
   1451     DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
   1452 }
   1453 
   1454 static void
   1455 damageRemoveDamage(DamagePtr * pPrev, DamagePtr pDamage)
   1456 {
   1457     while (*pPrev) {
   1458         if (*pPrev == pDamage) {
   1459             *pPrev = pDamage->pNext;
   1460             return;
   1461         }
   1462         pPrev = &(*pPrev)->pNext;
   1463     }
   1464 #if DAMAGE_VALIDATE_ENABLE
   1465     ErrorF("Damage not on list\n");
   1466     OsAbort();
   1467 #endif
   1468 }
   1469 
   1470 static void
   1471 damageInsertDamage(DamagePtr * pPrev, DamagePtr pDamage)
   1472 {
   1473 #if DAMAGE_VALIDATE_ENABLE
   1474     DamagePtr pOld;
   1475 
   1476     for (pOld = *pPrev; pOld; pOld = pOld->pNext)
   1477         if (pOld == pDamage) {
   1478             ErrorF("Damage already on list\n");
   1479             OsAbort();
   1480         }
   1481 #endif
   1482     pDamage->pNext = *pPrev;
   1483     *pPrev = pDamage;
   1484 }
   1485 
   1486 static Bool
   1487 damageDestroyPixmap(PixmapPtr pPixmap)
   1488 {
   1489     ScreenPtr pScreen = pPixmap->drawable.pScreen;
   1490 
   1491     damageScrPriv(pScreen);
   1492 
   1493     if (pPixmap->refcnt == 1) {
   1494         DamagePtr *pPrev = getPixmapDamageRef(pPixmap);
   1495         DamagePtr pDamage;
   1496 
   1497         while ((pDamage = *pPrev)) {
   1498             damageRemoveDamage(pPrev, pDamage);
   1499             if (!pDamage->isWindow)
   1500                 DamageDestroy(pDamage);
   1501         }
   1502     }
   1503     unwrap(pScrPriv, pScreen, DestroyPixmap);
   1504     (*pScreen->DestroyPixmap) (pPixmap);
   1505     wrap(pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
   1506     return TRUE;
   1507 }
   1508 
   1509 static void
   1510 damageCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
   1511 {
   1512     ScreenPtr pScreen = pWindow->drawable.pScreen;
   1513 
   1514     damageScrPriv(pScreen);
   1515 
   1516     if (getWindowDamage(pWindow)) {
   1517         int dx = pWindow->drawable.x - ptOldOrg.x;
   1518         int dy = pWindow->drawable.y - ptOldOrg.y;
   1519 
   1520         /*
   1521          * The region comes in source relative, but the damage occurs
   1522          * at the destination location.  Translate back and forth.
   1523          */
   1524         RegionTranslate(prgnSrc, dx, dy);
   1525         damageRegionAppend(&pWindow->drawable, prgnSrc, FALSE, -1);
   1526         RegionTranslate(prgnSrc, -dx, -dy);
   1527     }
   1528     unwrap(pScrPriv, pScreen, CopyWindow);
   1529     (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
   1530     damageRegionProcessPending(&pWindow->drawable);
   1531     wrap(pScrPriv, pScreen, CopyWindow, damageCopyWindow);
   1532 }
   1533 
   1534 static GCOps damageGCOps = {
   1535     damageFillSpans, damageSetSpans,
   1536     damagePutImage, damageCopyArea,
   1537     damageCopyPlane, damagePolyPoint,
   1538     damagePolylines, damagePolySegment,
   1539     damagePolyRectangle, damagePolyArc,
   1540     damageFillPolygon, damagePolyFillRect,
   1541     damagePolyFillArc, damagePolyText8,
   1542     damagePolyText16, damageImageText8,
   1543     damageImageText16, damageImageGlyphBlt,
   1544     damagePolyGlyphBlt, damagePushPixels,
   1545 };
   1546 
   1547 static void
   1548 damageSetWindowPixmap(WindowPtr pWindow, PixmapPtr pPixmap)
   1549 {
   1550     DamagePtr pDamage;
   1551     ScreenPtr pScreen = pWindow->drawable.pScreen;
   1552 
   1553     damageScrPriv(pScreen);
   1554 
   1555     if ((pDamage = damageGetWinPriv(pWindow))) {
   1556         PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow);
   1557         DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap);
   1558 
   1559         while (pDamage) {
   1560             damageRemoveDamage(pPrev, pDamage);
   1561             pDamage = pDamage->pNextWin;
   1562         }
   1563     }
   1564     unwrap(pScrPriv, pScreen, SetWindowPixmap);
   1565     (*pScreen->SetWindowPixmap) (pWindow, pPixmap);
   1566     wrap(pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
   1567     if ((pDamage = damageGetWinPriv(pWindow))) {
   1568         DamagePtr *pPrev = getPixmapDamageRef(pPixmap);
   1569 
   1570         while (pDamage) {
   1571             damageInsertDamage(pPrev, pDamage);
   1572             pDamage = pDamage->pNextWin;
   1573         }
   1574     }
   1575 }
   1576 
   1577 static Bool
   1578 damageDestroyWindow(WindowPtr pWindow)
   1579 {
   1580     DamagePtr pDamage;
   1581     ScreenPtr pScreen = pWindow->drawable.pScreen;
   1582     Bool ret;
   1583 
   1584     damageScrPriv(pScreen);
   1585 
   1586     while ((pDamage = damageGetWinPriv(pWindow))) {
   1587         DamageDestroy(pDamage);
   1588     }
   1589     unwrap(pScrPriv, pScreen, DestroyWindow);
   1590     ret = (*pScreen->DestroyWindow) (pWindow);
   1591     wrap(pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
   1592     return ret;
   1593 }
   1594 
   1595 static Bool
   1596 damageCloseScreen(ScreenPtr pScreen)
   1597 {
   1598     damageScrPriv(pScreen);
   1599 
   1600     unwrap(pScrPriv, pScreen, DestroyPixmap);
   1601     unwrap(pScrPriv, pScreen, CreateGC);
   1602     unwrap(pScrPriv, pScreen, CopyWindow);
   1603     unwrap(pScrPriv, pScreen, CloseScreen);
   1604     free(pScrPriv);
   1605     return (*pScreen->CloseScreen) (pScreen);
   1606 }
   1607 
   1608 /**
   1609  * Default implementations of the damage management functions.
   1610  */
   1611 void
   1612 miDamageCreate(DamagePtr pDamage)
   1613 {
   1614 }
   1615 
   1616 /*
   1617  * We only wrap into the GC when there's a registered listener.  For windows,
   1618  * damage includes damage to children.  So if there's a GC validated against
   1619  * a subwindow and we then register a damage on the parent, we need to bump
   1620  * the serial numbers of the children to re-trigger validation.
   1621  *
   1622  * Since we can't know if a GC has been validated against one of the affected
   1623  * children, just bump them all to be safe.
   1624  */
   1625 static int
   1626 damageRegisterVisit(WindowPtr pWin, void *data)
   1627 {
   1628     pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
   1629     return WT_WALKCHILDREN;
   1630 }
   1631 
   1632 void
   1633 miDamageRegister(DrawablePtr pDrawable, DamagePtr pDamage)
   1634 {
   1635     if (pDrawable->type == DRAWABLE_WINDOW)
   1636         TraverseTree((WindowPtr)pDrawable, damageRegisterVisit, NULL);
   1637     else
   1638         pDrawable->serialNumber = NEXT_SERIAL_NUMBER;
   1639 }
   1640 
   1641 void
   1642 miDamageUnregister(DrawablePtr pDrawable, DamagePtr pDamage)
   1643 {
   1644     if (pDrawable->type == DRAWABLE_WINDOW)
   1645         TraverseTree((WindowPtr)pDrawable, damageRegisterVisit, NULL);
   1646     else
   1647         pDrawable->serialNumber = NEXT_SERIAL_NUMBER;
   1648 }
   1649 
   1650 void
   1651 miDamageDestroy(DamagePtr pDamage)
   1652 {
   1653 }
   1654 
   1655 /**
   1656  * Public functions for consumption outside this file.
   1657  */
   1658 
   1659 Bool
   1660 DamageSetup(ScreenPtr pScreen)
   1661 {
   1662     DamageScrPrivPtr pScrPriv;
   1663     PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
   1664 
   1665     const DamageScreenFuncsRec miFuncs = {
   1666         miDamageCreate, miDamageRegister, miDamageUnregister, miDamageDestroy
   1667     };
   1668 
   1669     if (!dixRegisterPrivateKey(&damageScrPrivateKeyRec, PRIVATE_SCREEN, 0))
   1670         return FALSE;
   1671 
   1672     if (dixLookupPrivate(&pScreen->devPrivates, damageScrPrivateKey))
   1673         return TRUE;
   1674 
   1675     if (!dixRegisterPrivateKey
   1676         (&damageGCPrivateKeyRec, PRIVATE_GC, sizeof(DamageGCPrivRec)))
   1677         return FALSE;
   1678 
   1679     if (!dixRegisterPrivateKey(&damagePixPrivateKeyRec, PRIVATE_PIXMAP, 0))
   1680         return FALSE;
   1681 
   1682     if (!dixRegisterPrivateKey(&damageWinPrivateKeyRec, PRIVATE_WINDOW, 0))
   1683         return FALSE;
   1684 
   1685     pScrPriv = malloc(sizeof(DamageScrPrivRec));
   1686     if (!pScrPriv)
   1687         return FALSE;
   1688 
   1689     pScrPriv->internalLevel = 0;
   1690     pScrPriv->pScreenDamage = 0;
   1691 
   1692     wrap(pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
   1693     wrap(pScrPriv, pScreen, CreateGC, damageCreateGC);
   1694     wrap(pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
   1695     wrap(pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
   1696     wrap(pScrPriv, pScreen, CopyWindow, damageCopyWindow);
   1697     wrap(pScrPriv, pScreen, CloseScreen, damageCloseScreen);
   1698     if (ps) {
   1699         wrap(pScrPriv, ps, Glyphs, damageGlyphs);
   1700         wrap(pScrPriv, ps, Composite, damageComposite);
   1701         wrap(pScrPriv, ps, AddTraps, damageAddTraps);
   1702     }
   1703 
   1704     pScrPriv->funcs = miFuncs;
   1705 
   1706     dixSetPrivate(&pScreen->devPrivates, damageScrPrivateKey, pScrPriv);
   1707     return TRUE;
   1708 }
   1709 
   1710 DamagePtr
   1711 DamageCreate(DamageReportFunc damageReport,
   1712              DamageDestroyFunc damageDestroy,
   1713              DamageReportLevel damageLevel,
   1714              Bool isInternal, ScreenPtr pScreen, void *closure)
   1715 {
   1716     damageScrPriv(pScreen);
   1717     DamagePtr pDamage;
   1718 
   1719     pDamage = calloc(1, sizeof(DamageRec));
   1720     if (!pDamage)
   1721         return 0;
   1722     pDamage->pNext = 0;
   1723     pDamage->pNextWin = 0;
   1724     RegionNull(&pDamage->damage);
   1725     RegionNull(&pDamage->pendingDamage);
   1726 
   1727     pDamage->damageLevel = damageLevel;
   1728     pDamage->isInternal = isInternal;
   1729     pDamage->closure = closure;
   1730     pDamage->isWindow = FALSE;
   1731     pDamage->pDrawable = 0;
   1732     pDamage->reportAfter = FALSE;
   1733 
   1734     pDamage->damageReport = damageReport;
   1735     pDamage->damageDestroy = damageDestroy;
   1736     pDamage->pScreen = pScreen;
   1737 
   1738     (*pScrPriv->funcs.Create) (pDamage);
   1739 
   1740     return pDamage;
   1741 }
   1742 
   1743 void
   1744 DamageRegister(DrawablePtr pDrawable, DamagePtr pDamage)
   1745 {
   1746     ScreenPtr pScreen = pDrawable->pScreen;
   1747 
   1748     damageScrPriv(pScreen);
   1749 
   1750 #if DAMAGE_VALIDATE_ENABLE
   1751     if (pDrawable->pScreen != pDamage->pScreen) {
   1752         ErrorF("DamageRegister called with mismatched screens\n");
   1753         OsAbort();
   1754     }
   1755 #endif
   1756 
   1757     if (pDrawable->type == DRAWABLE_WINDOW) {
   1758         WindowPtr pWindow = (WindowPtr) pDrawable;
   1759 
   1760         winDamageRef(pWindow);
   1761 
   1762 #if DAMAGE_VALIDATE_ENABLE
   1763         DamagePtr pOld;
   1764 
   1765         for (pOld = *pPrev; pOld; pOld = pOld->pNextWin)
   1766             if (pOld == pDamage) {
   1767                 ErrorF("Damage already on window list\n");
   1768                 OsAbort();
   1769             }
   1770 #endif
   1771         pDamage->pNextWin = *pPrev;
   1772         *pPrev = pDamage;
   1773         pDamage->isWindow = TRUE;
   1774     }
   1775     else
   1776         pDamage->isWindow = FALSE;
   1777     pDamage->pDrawable = pDrawable;
   1778     damageInsertDamage(getDrawableDamageRef(pDrawable), pDamage);
   1779     (*pScrPriv->funcs.Register) (pDrawable, pDamage);
   1780 }
   1781 
   1782 void
   1783 DamageDrawInternal(ScreenPtr pScreen, Bool enable)
   1784 {
   1785     damageScrPriv(pScreen);
   1786 
   1787     pScrPriv->internalLevel += enable ? 1 : -1;
   1788 }
   1789 
   1790 void
   1791 DamageUnregister(DamagePtr pDamage)
   1792 {
   1793     DrawablePtr pDrawable = pDamage->pDrawable;
   1794     ScreenPtr pScreen = pDrawable->pScreen;
   1795 
   1796     damageScrPriv(pScreen);
   1797 
   1798     (*pScrPriv->funcs.Unregister) (pDrawable, pDamage);
   1799 
   1800     if (pDrawable->type == DRAWABLE_WINDOW) {
   1801         WindowPtr pWindow = (WindowPtr) pDrawable;
   1802 
   1803         winDamageRef(pWindow);
   1804 #if DAMAGE_VALIDATE_ENABLE
   1805         int found = 0;
   1806 #endif
   1807 
   1808         while (*pPrev) {
   1809             if (*pPrev == pDamage) {
   1810                 *pPrev = pDamage->pNextWin;
   1811 #if DAMAGE_VALIDATE_ENABLE
   1812                 found = 1;
   1813 #endif
   1814                 break;
   1815             }
   1816             pPrev = &(*pPrev)->pNextWin;
   1817         }
   1818 #if DAMAGE_VALIDATE_ENABLE
   1819         if (!found) {
   1820             ErrorF("Damage not on window list\n");
   1821             OsAbort();
   1822         }
   1823 #endif
   1824     }
   1825     pDamage->pDrawable = 0;
   1826     damageRemoveDamage(getDrawableDamageRef(pDrawable), pDamage);
   1827 }
   1828 
   1829 void
   1830 DamageDestroy(DamagePtr pDamage)
   1831 {
   1832     ScreenPtr pScreen = pDamage->pScreen;
   1833 
   1834     damageScrPriv(pScreen);
   1835 
   1836     if (pDamage->pDrawable)
   1837         DamageUnregister(pDamage);
   1838 
   1839     if (pDamage->damageDestroy)
   1840         (*pDamage->damageDestroy) (pDamage, pDamage->closure);
   1841     (*pScrPriv->funcs.Destroy) (pDamage);
   1842     RegionUninit(&pDamage->damage);
   1843     RegionUninit(&pDamage->pendingDamage);
   1844     free(pDamage);
   1845 }
   1846 
   1847 Bool
   1848 DamageSubtract(DamagePtr pDamage, const RegionPtr pRegion)
   1849 {
   1850     RegionPtr pClip;
   1851     RegionRec pixmapClip;
   1852     DrawablePtr pDrawable = pDamage->pDrawable;
   1853 
   1854     RegionSubtract(&pDamage->damage, &pDamage->damage, pRegion);
   1855     if (pDrawable) {
   1856         if (pDrawable->type == DRAWABLE_WINDOW)
   1857             pClip = &((WindowPtr) pDrawable)->borderClip;
   1858         else {
   1859             BoxRec box;
   1860 
   1861             box.x1 = pDrawable->x;
   1862             box.y1 = pDrawable->y;
   1863             box.x2 = pDrawable->x + pDrawable->width;
   1864             box.y2 = pDrawable->y + pDrawable->height;
   1865             RegionInit(&pixmapClip, &box, 1);
   1866             pClip = &pixmapClip;
   1867         }
   1868         RegionTranslate(&pDamage->damage, pDrawable->x, pDrawable->y);
   1869         RegionIntersect(&pDamage->damage, &pDamage->damage, pClip);
   1870         RegionTranslate(&pDamage->damage, -pDrawable->x, -pDrawable->y);
   1871         if (pDrawable->type != DRAWABLE_WINDOW)
   1872             RegionUninit(&pixmapClip);
   1873     }
   1874     return RegionNotEmpty(&pDamage->damage);
   1875 }
   1876 
   1877 void
   1878 DamageEmpty(DamagePtr pDamage)
   1879 {
   1880     RegionEmpty(&pDamage->damage);
   1881 }
   1882 
   1883 RegionPtr
   1884 DamageRegion(DamagePtr pDamage)
   1885 {
   1886     return &pDamage->damage;
   1887 }
   1888 
   1889 RegionPtr
   1890 DamagePendingRegion(DamagePtr pDamage)
   1891 {
   1892     return &pDamage->pendingDamage;
   1893 }
   1894 
   1895 void
   1896 DamageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion)
   1897 {
   1898     damageRegionAppend(pDrawable, pRegion, FALSE, -1);
   1899 }
   1900 
   1901 void
   1902 DamageRegionProcessPending(DrawablePtr pDrawable)
   1903 {
   1904     damageRegionProcessPending(pDrawable);
   1905 }
   1906 
   1907 /* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */
   1908 void
   1909 DamageDamageRegion(DrawablePtr pDrawable, RegionPtr pRegion)
   1910 {
   1911     damageRegionAppend(pDrawable, pRegion, FALSE, -1);
   1912 
   1913     /* Go back and report this damage for DamagePtrs with reportAfter set, since
   1914      * this call isn't part of an in-progress drawing op in the call chain and
   1915      * the DDX probably just wants to know about it right away.
   1916      */
   1917     damageRegionProcessPending(pDrawable);
   1918 }
   1919 
   1920 void
   1921 DamageSetReportAfterOp(DamagePtr pDamage, Bool reportAfter)
   1922 {
   1923     pDamage->reportAfter = reportAfter;
   1924 }
   1925 
   1926 DamageScreenFuncsPtr
   1927 DamageGetScreenFuncs(ScreenPtr pScreen)
   1928 {
   1929     damageScrPriv(pScreen);
   1930     return &pScrPriv->funcs;
   1931 }
   1932 
   1933 void
   1934 DamageReportDamage(DamagePtr pDamage, RegionPtr pDamageRegion)
   1935 {
   1936     BoxRec tmpBox;
   1937     RegionRec tmpRegion;
   1938     Bool was_empty;
   1939 
   1940     switch (pDamage->damageLevel) {
   1941     case DamageReportRawRegion:
   1942         RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
   1943         (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure);
   1944         break;
   1945     case DamageReportDeltaRegion:
   1946         RegionNull(&tmpRegion);
   1947         RegionSubtract(&tmpRegion, pDamageRegion, &pDamage->damage);
   1948         if (RegionNotEmpty(&tmpRegion)) {
   1949             RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
   1950             (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure);
   1951         }
   1952         RegionUninit(&tmpRegion);
   1953         break;
   1954     case DamageReportBoundingBox:
   1955         tmpBox = *RegionExtents(&pDamage->damage);
   1956         RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
   1957         if (!BOX_SAME(&tmpBox, RegionExtents(&pDamage->damage))) {
   1958             (*pDamage->damageReport) (pDamage, &pDamage->damage,
   1959                                       pDamage->closure);
   1960         }
   1961         break;
   1962     case DamageReportNonEmpty:
   1963         was_empty = !RegionNotEmpty(&pDamage->damage);
   1964         RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
   1965         if (was_empty && RegionNotEmpty(&pDamage->damage)) {
   1966             (*pDamage->damageReport) (pDamage, &pDamage->damage,
   1967                                       pDamage->closure);
   1968         }
   1969         break;
   1970     case DamageReportNone:
   1971         RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
   1972         break;
   1973     }
   1974 }