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