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