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 72static DevPrivateKeyRec damageScrPrivateKeyRec; 73 74#define damageScrPrivateKey (&damageScrPrivateKeyRec) 75static DevPrivateKeyRec damagePixPrivateKeyRec; 76 77#define damagePixPrivateKey (&damagePixPrivateKeyRec) 78static DevPrivateKeyRec damageGCPrivateKeyRec; 79 80#define damageGCPrivateKey (&damageGCPrivateKeyRec) 81static DevPrivateKeyRec damageWinPrivateKeyRec; 82 83#define damageWinPrivateKey (&damageWinPrivateKeyRec) 84 85static DamagePtr * 86getDrawableDamageRef(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 125static 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 130static void 131damageRegionAppend(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 285static void 286damageRegionProcessPending(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__) 308static void 309_damageDamageBox(DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, 310 const char *where) 311#else 312static void 313damageDamageBox(DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode) 314#endif 315{ 316 RegionRec region; 317 318 RegionInit(®ion, pBox, 1); 319#if DAMAGE_DEBUG_ENABLE 320 _damageRegionAppend(pDrawable, ®ion, TRUE, subWindowMode, where); 321#else 322 damageRegionAppend(pDrawable, ®ion, TRUE, subWindowMode); 323#endif 324 RegionUninit(®ion); 325} 326 327static void damageValidateGC(GCPtr, unsigned long, DrawablePtr); 328static void damageChangeGC(GCPtr, unsigned long); 329static void damageCopyGC(GCPtr, unsigned long, GCPtr); 330static void damageDestroyGC(GCPtr); 331static void damageChangeClip(GCPtr, int, void *, int); 332static void damageDestroyClip(GCPtr); 333static void damageCopyClip(GCPtr, GCPtr); 334 335static GCFuncs damageGCFuncs = { 336 damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, 337 damageChangeClip, damageDestroyClip, damageCopyClip 338}; 339 340static GCOps damageGCOps; 341 342static Bool 343damageCreateGC(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 381static void 382damageValidateGC(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 390static void 391damageDestroyGC(GCPtr pGC) 392{ 393 DAMAGE_GC_FUNC_PROLOGUE(pGC); 394 (*pGC->funcs->DestroyGC) (pGC); 395 DAMAGE_GC_FUNC_EPILOGUE(pGC); 396} 397 398static void 399damageChangeGC(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 406static void 407damageCopyGC(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 414static void 415damageChangeClip(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 422static void 423damageCopyClip(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 430static void 431damageDestroyClip(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 476static void 477damageComposite(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 522static void 523damageGlyphs(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 584static void 585damageAddTraps(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 634static void 635damageFillSpans(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 680static void 681damageSetSpans(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 726static void 727damagePutImage(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 752static RegionPtr 753damageCopyArea(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 782static RegionPtr 783damageCopyPlane(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 816static void 817damagePolyPoint(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 876static void 877damagePolylines(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 949static void 950damagePolySegment(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 1028static void 1029damagePolyRectangle(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 1087static void 1088damagePolyArc(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 1134static void 1135damageFillPolygon(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 1193static void 1194damagePolyFillRect(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 1229static void 1230damagePolyFillArc(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 1270static void 1271damageDamageChars(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 1309static void 1310damageText(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 1343static int 1344damagePolyText8(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 1356static int 1357damagePolyText16(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 1370static void 1371damageImageText8(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 1382static void 1383damageImageText16(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 1395static void 1396damageImageGlyphBlt(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 1410static void 1411damagePolyGlyphBlt(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 1425static void 1426damagePushPixels(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 1454static void 1455damageRemoveDamage(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 1470static void 1471damageInsertDamage(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 1486static Bool 1487damageDestroyPixmap(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 1509static void 1510damageCopyWindow(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 1534static 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 1547static void 1548damageSetWindowPixmap(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 1577static Bool 1578damageDestroyWindow(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 1595static Bool 1596damageCloseScreen(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 */ 1611void 1612miDamageCreate(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 */ 1625static int 1626damageRegisterVisit(WindowPtr pWin, void *data) 1627{ 1628 pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1629 return WT_WALKCHILDREN; 1630} 1631 1632void 1633miDamageRegister(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 1641void 1642miDamageUnregister(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 1650void 1651miDamageDestroy(DamagePtr pDamage) 1652{ 1653} 1654 1655/** 1656 * Public functions for consumption outside this file. 1657 */ 1658 1659Bool 1660DamageSetup(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 1710DamagePtr 1711DamageCreate(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 1743void 1744DamageRegister(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 1782void 1783DamageDrawInternal(ScreenPtr pScreen, Bool enable) 1784{ 1785 damageScrPriv(pScreen); 1786 1787 pScrPriv->internalLevel += enable ? 1 : -1; 1788} 1789 1790void 1791DamageUnregister(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 1829void 1830DamageDestroy(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 1847Bool 1848DamageSubtract(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 1877void 1878DamageEmpty(DamagePtr pDamage) 1879{ 1880 RegionEmpty(&pDamage->damage); 1881} 1882 1883RegionPtr 1884DamageRegion(DamagePtr pDamage) 1885{ 1886 return &pDamage->damage; 1887} 1888 1889RegionPtr 1890DamagePendingRegion(DamagePtr pDamage) 1891{ 1892 return &pDamage->pendingDamage; 1893} 1894 1895void 1896DamageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion) 1897{ 1898 damageRegionAppend(pDrawable, pRegion, FALSE, -1); 1899} 1900 1901void 1902DamageRegionProcessPending(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. */ 1908void 1909DamageDamageRegion(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 1920void 1921DamageSetReportAfterOp(DamagePtr pDamage, Bool reportAfter) 1922{ 1923 pDamage->reportAfter = reportAfter; 1924} 1925 1926DamageScreenFuncsPtr 1927DamageGetScreenFuncs(ScreenPtr pScreen) 1928{ 1929 damageScrPriv(pScreen); 1930 return &pScrPriv->funcs; 1931} 1932 1933void 1934DamageReportDamage(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} 1975