damage.c revision 6747b715
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 pGC->pCompositeClip = 0; 454 unwrap (pScrPriv, pScreen, CreateGC); 455 if((ret = (*pScreen->CreateGC) (pGC))) { 456 pGCPriv->ops = NULL; 457 pGCPriv->funcs = pGC->funcs; 458 pGC->funcs = &damageGCFuncs; 459 } 460 wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); 461 462 return ret; 463} 464 465#ifdef NOTUSED 466static void 467damageWrapGC (GCPtr pGC) 468{ 469 damageGCPriv(pGC); 470 471 pGCPriv->ops = NULL; 472 pGCPriv->funcs = pGC->funcs; 473 pGC->funcs = &damageGCFuncs; 474} 475 476static void 477damageUnwrapGC (GCPtr pGC) 478{ 479 damageGCPriv(pGC); 480 481 pGC->funcs = pGCPriv->funcs; 482 if (pGCPriv->ops) 483 pGC->ops = pGCPriv->ops; 484} 485#endif 486 487#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \ 488 damageGCPriv(pGC); \ 489 GCFuncs *oldFuncs = pGC->funcs; \ 490 unwrap(pGCPriv, pGC, funcs); \ 491 unwrap(pGCPriv, pGC, ops); \ 492 493#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \ 494 wrap(pGCPriv, pGC, funcs, oldFuncs); \ 495 wrap(pGCPriv, pGC, ops, &damageGCOps) 496 497#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \ 498 damageGCPriv(pGC); \ 499 unwrap(pGCPriv, pGC, funcs); \ 500 if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops) 501 502#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \ 503 wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \ 504 if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps) 505 506static void 507damageValidateGC(GCPtr pGC, 508 unsigned long changes, 509 DrawablePtr pDrawable) 510{ 511 DAMAGE_GC_FUNC_PROLOGUE (pGC); 512 (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); 513 pGCPriv->ops = pGC->ops; /* just so it's not NULL */ 514 DAMAGE_GC_FUNC_EPILOGUE (pGC); 515} 516 517static void 518damageDestroyGC(GCPtr pGC) 519{ 520 DAMAGE_GC_FUNC_PROLOGUE (pGC); 521 (*pGC->funcs->DestroyGC)(pGC); 522 DAMAGE_GC_FUNC_EPILOGUE (pGC); 523} 524 525static void 526damageChangeGC (GCPtr pGC, 527 unsigned long mask) 528{ 529 DAMAGE_GC_FUNC_PROLOGUE (pGC); 530 (*pGC->funcs->ChangeGC) (pGC, mask); 531 DAMAGE_GC_FUNC_EPILOGUE (pGC); 532} 533 534static void 535damageCopyGC (GCPtr pGCSrc, 536 unsigned long mask, 537 GCPtr pGCDst) 538{ 539 DAMAGE_GC_FUNC_PROLOGUE (pGCDst); 540 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); 541 DAMAGE_GC_FUNC_EPILOGUE (pGCDst); 542} 543 544static void 545damageChangeClip (GCPtr pGC, 546 int type, 547 pointer pvalue, 548 int nrects) 549{ 550 DAMAGE_GC_FUNC_PROLOGUE (pGC); 551 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); 552 DAMAGE_GC_FUNC_EPILOGUE (pGC); 553} 554 555static void 556damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc) 557{ 558 DAMAGE_GC_FUNC_PROLOGUE (pgcDst); 559 (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); 560 DAMAGE_GC_FUNC_EPILOGUE (pgcDst); 561} 562 563static void 564damageDestroyClip(GCPtr pGC) 565{ 566 DAMAGE_GC_FUNC_PROLOGUE (pGC); 567 (* pGC->funcs->DestroyClip)(pGC); 568 DAMAGE_GC_FUNC_EPILOGUE (pGC); 569} 570 571#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \ 572 BoxPtr extents = &pGC->pCompositeClip->extents;\ 573 if(box.x1 < extents->x1) box.x1 = extents->x1; \ 574 if(box.x2 > extents->x2) box.x2 = extents->x2; \ 575 if(box.y1 < extents->y1) box.y1 = extents->y1; \ 576 if(box.y2 > extents->y2) box.y2 = extents->y2; \ 577 } 578 579#define TRANSLATE_BOX(box, pDrawable) { \ 580 box.x1 += pDrawable->x; \ 581 box.x2 += pDrawable->x; \ 582 box.y1 += pDrawable->y; \ 583 box.y2 += pDrawable->y; \ 584 } 585 586#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \ 587 TRANSLATE_BOX(box, pDrawable); \ 588 TRIM_BOX(box, pGC); \ 589 } 590 591#define BOX_NOT_EMPTY(box) \ 592 (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) 593 594#define checkGCDamage(d,g) (getDrawableDamage(d) && \ 595 (!g->pCompositeClip ||\ 596 RegionNotEmpty(g->pCompositeClip))) 597 598#define TRIM_PICTURE_BOX(box, pDst) { \ 599 BoxPtr extents = &pDst->pCompositeClip->extents;\ 600 if(box.x1 < extents->x1) box.x1 = extents->x1; \ 601 if(box.x2 > extents->x2) box.x2 = extents->x2; \ 602 if(box.y1 < extents->y1) box.y1 = extents->y1; \ 603 if(box.y2 > extents->y2) box.y2 = extents->y2; \ 604 } 605 606#define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \ 607 RegionNotEmpty(p->pCompositeClip)) 608 609static void 610damageComposite (CARD8 op, 611 PicturePtr pSrc, 612 PicturePtr pMask, 613 PicturePtr pDst, 614 INT16 xSrc, 615 INT16 ySrc, 616 INT16 xMask, 617 INT16 yMask, 618 INT16 xDst, 619 INT16 yDst, 620 CARD16 width, 621 CARD16 height) 622{ 623 ScreenPtr pScreen = pDst->pDrawable->pScreen; 624 PictureScreenPtr ps = GetPictureScreen(pScreen); 625 damageScrPriv(pScreen); 626 627 if (checkPictureDamage (pDst)) 628 { 629 BoxRec box; 630 631 box.x1 = xDst + pDst->pDrawable->x; 632 box.y1 = yDst + pDst->pDrawable->y; 633 box.x2 = box.x1 + width; 634 box.y2 = box.y1 + height; 635 TRIM_PICTURE_BOX(box, pDst); 636 if (BOX_NOT_EMPTY(box)) 637 damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); 638 } 639 unwrap (pScrPriv, ps, Composite); 640 (*ps->Composite) (op, 641 pSrc, 642 pMask, 643 pDst, 644 xSrc, 645 ySrc, 646 xMask, 647 yMask, 648 xDst, 649 yDst, 650 width, 651 height); 652 damageRegionProcessPending (pDst->pDrawable); 653 wrap (pScrPriv, ps, Composite, damageComposite); 654} 655 656static void 657damageGlyphs (CARD8 op, 658 PicturePtr pSrc, 659 PicturePtr pDst, 660 PictFormatPtr maskFormat, 661 INT16 xSrc, 662 INT16 ySrc, 663 int nlist, 664 GlyphListPtr list, 665 GlyphPtr *glyphs) 666{ 667 ScreenPtr pScreen = pDst->pDrawable->pScreen; 668 PictureScreenPtr ps = GetPictureScreen(pScreen); 669 damageScrPriv(pScreen); 670 671 if (checkPictureDamage (pDst)) 672 { 673 int nlistTmp = nlist; 674 GlyphListPtr listTmp = list; 675 GlyphPtr *glyphsTmp = glyphs; 676 int x, y; 677 int n; 678 GlyphPtr glyph; 679 BoxRec box; 680 int x1, y1, x2, y2; 681 682 box.x1 = 32767; 683 box.y1 = 32767; 684 box.x2 = -32767; 685 box.y2 = -32767; 686 x = pDst->pDrawable->x; 687 y = pDst->pDrawable->y; 688 while (nlistTmp--) 689 { 690 x += listTmp->xOff; 691 y += listTmp->yOff; 692 n = listTmp->len; 693 while (n--) 694 { 695 glyph = *glyphsTmp++; 696 x1 = x - glyph->info.x; 697 y1 = y - glyph->info.y; 698 x2 = x1 + glyph->info.width; 699 y2 = y1 + glyph->info.height; 700 if (x1 < box.x1) 701 box.x1 = x1; 702 if (y1 < box.y1) 703 box.y1 = y1; 704 if (x2 > box.x2) 705 box.x2 = x2; 706 if (y2 > box.y2) 707 box.y2 = y2; 708 x += glyph->info.xOff; 709 y += glyph->info.yOff; 710 } 711 listTmp++; 712 } 713 TRIM_PICTURE_BOX (box, pDst); 714 if (BOX_NOT_EMPTY(box)) 715 damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); 716 } 717 unwrap (pScrPriv, ps, Glyphs); 718 (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); 719 damageRegionProcessPending (pDst->pDrawable); 720 wrap (pScrPriv, ps, Glyphs, damageGlyphs); 721} 722 723static void 724damageAddTraps (PicturePtr pPicture, 725 INT16 x_off, 726 INT16 y_off, 727 int ntrap, 728 xTrap *traps) 729{ 730 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 731 PictureScreenPtr ps = GetPictureScreen(pScreen); 732 damageScrPriv(pScreen); 733 734 if (checkPictureDamage (pPicture)) 735 { 736 BoxRec box; 737 int i; 738 int x, y; 739 xTrap *t = traps; 740 741 box.x1 = 32767; 742 box.y1 = 32767; 743 box.x2 = -32767; 744 box.y2 = -32767; 745 x = pPicture->pDrawable->x + x_off; 746 y = pPicture->pDrawable->y + y_off; 747 for (i = 0; i < ntrap; i++) 748 { 749 pixman_fixed_t l = min (t->top.l, t->bot.l); 750 pixman_fixed_t r = max (t->top.r, t->bot.r); 751 int x1 = x + pixman_fixed_to_int (l); 752 int x2 = x + pixman_fixed_to_int (pixman_fixed_ceil (r)); 753 int y1 = y + pixman_fixed_to_int (t->top.y); 754 int y2 = y + pixman_fixed_to_int (pixman_fixed_ceil (t->bot.y)); 755 756 if (x1 < box.x1) 757 box.x1 = x1; 758 if (x2 > box.x2) 759 box.x2 = x2; 760 if (y1 < box.y1) 761 box.y1 = y1; 762 if (y2 > box.y2) 763 box.y2 = y2; 764 } 765 TRIM_PICTURE_BOX (box, pPicture); 766 if (BOX_NOT_EMPTY(box)) 767 damageDamageBox (pPicture->pDrawable, &box, pPicture->subWindowMode); 768 } 769 unwrap (pScrPriv, ps, AddTraps); 770 (*ps->AddTraps) (pPicture, x_off, y_off, ntrap, traps); 771 damageRegionProcessPending (pPicture->pDrawable); 772 wrap (pScrPriv, ps, AddTraps, damageAddTraps); 773} 774 775/**********************************************************/ 776 777 778static void 779damageFillSpans(DrawablePtr pDrawable, 780 GC *pGC, 781 int npt, 782 DDXPointPtr ppt, 783 int *pwidth, 784 int fSorted) 785{ 786 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 787 788 if (npt && checkGCDamage (pDrawable, pGC)) 789 { 790 int nptTmp = npt; 791 DDXPointPtr pptTmp = ppt; 792 int *pwidthTmp = pwidth; 793 BoxRec box; 794 795 box.x1 = pptTmp->x; 796 box.x2 = box.x1 + *pwidthTmp; 797 box.y2 = box.y1 = pptTmp->y; 798 799 while(--nptTmp) 800 { 801 pptTmp++; 802 pwidthTmp++; 803 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 804 if(box.x2 < (pptTmp->x + *pwidthTmp)) 805 box.x2 = pptTmp->x + *pwidthTmp; 806 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 807 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 808 } 809 810 box.y2++; 811 812 if(!pGC->miTranslate) { 813 TRANSLATE_BOX(box, pDrawable); 814 } 815 TRIM_BOX(box, pGC); 816 817 if(BOX_NOT_EMPTY(box)) 818 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 819 } 820 821 (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); 822 823 damageRegionProcessPending (pDrawable); 824 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 825} 826 827static void 828damageSetSpans(DrawablePtr pDrawable, 829 GCPtr pGC, 830 char *pcharsrc, 831 DDXPointPtr ppt, 832 int *pwidth, 833 int npt, 834 int fSorted) 835{ 836 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 837 838 if (npt && checkGCDamage (pDrawable, pGC)) 839 { 840 DDXPointPtr pptTmp = ppt; 841 int *pwidthTmp = pwidth; 842 int nptTmp = npt; 843 BoxRec box; 844 845 box.x1 = pptTmp->x; 846 box.x2 = box.x1 + *pwidthTmp; 847 box.y2 = box.y1 = pptTmp->y; 848 849 while(--nptTmp) 850 { 851 pptTmp++; 852 pwidthTmp++; 853 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 854 if(box.x2 < (pptTmp->x + *pwidthTmp)) 855 box.x2 = pptTmp->x + *pwidthTmp; 856 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 857 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 858 } 859 860 box.y2++; 861 862 if(!pGC->miTranslate) { 863 TRANSLATE_BOX(box, pDrawable); 864 } 865 TRIM_BOX(box, pGC); 866 867 if(BOX_NOT_EMPTY(box)) 868 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 869 } 870 (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); 871 damageRegionProcessPending (pDrawable); 872 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 873} 874 875static void 876damagePutImage(DrawablePtr pDrawable, 877 GCPtr pGC, 878 int depth, 879 int x, 880 int y, 881 int w, 882 int h, 883 int leftPad, 884 int format, 885 char *pImage) 886{ 887 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 888 if (checkGCDamage (pDrawable, pGC)) 889 { 890 BoxRec box; 891 892 box.x1 = x + pDrawable->x; 893 box.x2 = box.x1 + w; 894 box.y1 = y + pDrawable->y; 895 box.y2 = box.y1 + h; 896 897 TRIM_BOX(box, pGC); 898 if(BOX_NOT_EMPTY(box)) 899 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 900 } 901 (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, 902 leftPad, format, pImage); 903 damageRegionProcessPending (pDrawable); 904 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 905} 906 907static RegionPtr 908damageCopyArea(DrawablePtr pSrc, 909 DrawablePtr pDst, 910 GC *pGC, 911 int srcx, 912 int srcy, 913 int width, 914 int height, 915 int dstx, 916 int dsty) 917{ 918 RegionPtr ret; 919 DAMAGE_GC_OP_PROLOGUE(pGC, pDst); 920 921 /* The driver will only call SourceValidate() when pSrc != pDst, 922 * but the software sprite (misprite.c) always need to know when a 923 * drawable is copied so it can remove the sprite. See #1030. */ 924 if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && 925 pSrc->type == DRAWABLE_WINDOW && 926 ((WindowPtr)pSrc)->viewable) 927 { 928 (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); 929 } 930 931 if (checkGCDamage (pDst, pGC)) 932 { 933 BoxRec box; 934 935 box.x1 = dstx + pDst->x; 936 box.x2 = box.x1 + width; 937 box.y1 = dsty + pDst->y; 938 box.y2 = box.y1 + height; 939 940 TRIM_BOX(box, pGC); 941 if(BOX_NOT_EMPTY(box)) 942 damageDamageBox (pDst, &box, pGC->subWindowMode); 943 } 944 945 ret = (*pGC->ops->CopyArea)(pSrc, pDst, 946 pGC, srcx, srcy, width, height, dstx, dsty); 947 damageRegionProcessPending (pDst); 948 DAMAGE_GC_OP_EPILOGUE(pGC, pDst); 949 return ret; 950} 951 952static RegionPtr 953damageCopyPlane(DrawablePtr pSrc, 954 DrawablePtr pDst, 955 GCPtr pGC, 956 int srcx, 957 int srcy, 958 int width, 959 int height, 960 int dstx, 961 int dsty, 962 unsigned long bitPlane) 963{ 964 RegionPtr ret; 965 DAMAGE_GC_OP_PROLOGUE(pGC, pDst); 966 967 /* The driver will only call SourceValidate() when pSrc != pDst, 968 * but the software sprite (misprite.c) always need to know when a 969 * drawable is copied so it can remove the sprite. See #1030. */ 970 if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && 971 pSrc->type == DRAWABLE_WINDOW && 972 ((WindowPtr)pSrc)->viewable) 973 { 974 (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); 975 } 976 977 if (checkGCDamage (pDst, pGC)) 978 { 979 BoxRec box; 980 981 box.x1 = dstx + pDst->x; 982 box.x2 = box.x1 + width; 983 box.y1 = dsty + pDst->y; 984 box.y2 = box.y1 + height; 985 986 TRIM_BOX(box, pGC); 987 if(BOX_NOT_EMPTY(box)) 988 damageDamageBox (pDst, &box, pGC->subWindowMode); 989 } 990 991 ret = (*pGC->ops->CopyPlane)(pSrc, pDst, 992 pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); 993 damageRegionProcessPending (pDst); 994 DAMAGE_GC_OP_EPILOGUE(pGC, pDst); 995 return ret; 996} 997 998static void 999damagePolyPoint(DrawablePtr pDrawable, 1000 GCPtr pGC, 1001 int mode, 1002 int npt, 1003 xPoint *ppt) 1004{ 1005 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1006 1007 if (npt && checkGCDamage (pDrawable, pGC)) 1008 { 1009 BoxRec box; 1010 int nptTmp = npt; 1011 xPoint *pptTmp = ppt; 1012 1013 box.x2 = box.x1 = pptTmp->x; 1014 box.y2 = box.y1 = pptTmp->y; 1015 1016 /* this could be slow if the points were spread out */ 1017 1018 while(--nptTmp) 1019 { 1020 pptTmp++; 1021 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 1022 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; 1023 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 1024 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 1025 } 1026 1027 box.x2++; 1028 box.y2++; 1029 1030 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1031 if(BOX_NOT_EMPTY(box)) 1032 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1033 } 1034 (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); 1035 damageRegionProcessPending (pDrawable); 1036 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1037} 1038 1039static void 1040damagePolylines(DrawablePtr pDrawable, 1041 GCPtr pGC, 1042 int mode, 1043 int npt, 1044 DDXPointPtr ppt) 1045{ 1046 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1047 1048 if (npt && checkGCDamage (pDrawable, pGC)) 1049 { 1050 int nptTmp = npt; 1051 DDXPointPtr pptTmp = ppt; 1052 BoxRec box; 1053 int extra = pGC->lineWidth >> 1; 1054 1055 box.x2 = box.x1 = pptTmp->x; 1056 box.y2 = box.y1 = pptTmp->y; 1057 1058 if(nptTmp > 1) 1059 { 1060 if(pGC->joinStyle == JoinMiter) 1061 extra = 6 * pGC->lineWidth; 1062 else if(pGC->capStyle == CapProjecting) 1063 extra = pGC->lineWidth; 1064 } 1065 1066 if(mode == CoordModePrevious) 1067 { 1068 int x = box.x1; 1069 int y = box.y1; 1070 while(--nptTmp) 1071 { 1072 pptTmp++; 1073 x += pptTmp->x; 1074 y += pptTmp->y; 1075 if(box.x1 > x) box.x1 = x; 1076 else if(box.x2 < x) box.x2 = x; 1077 if(box.y1 > y) box.y1 = y; 1078 else if(box.y2 < y) box.y2 = y; 1079 } 1080 } 1081 else 1082 { 1083 while(--nptTmp) 1084 { 1085 pptTmp++; 1086 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 1087 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; 1088 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 1089 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 1090 } 1091 } 1092 1093 box.x2++; 1094 box.y2++; 1095 1096 if(extra) 1097 { 1098 box.x1 -= extra; 1099 box.x2 += extra; 1100 box.y1 -= extra; 1101 box.y2 += extra; 1102 } 1103 1104 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1105 if(BOX_NOT_EMPTY(box)) 1106 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1107 } 1108 (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); 1109 damageRegionProcessPending (pDrawable); 1110 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1111} 1112 1113static void 1114damagePolySegment(DrawablePtr pDrawable, 1115 GCPtr pGC, 1116 int nSeg, 1117 xSegment *pSeg) 1118{ 1119 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1120 1121 if (nSeg && checkGCDamage (pDrawable, pGC)) 1122 { 1123 BoxRec box; 1124 int extra = pGC->lineWidth; 1125 int nsegTmp = nSeg; 1126 xSegment *pSegTmp = pSeg; 1127 1128 if(pGC->capStyle != CapProjecting) 1129 extra >>= 1; 1130 1131 if(pSegTmp->x2 > pSegTmp->x1) { 1132 box.x1 = pSegTmp->x1; 1133 box.x2 = pSegTmp->x2; 1134 } else { 1135 box.x2 = pSegTmp->x1; 1136 box.x1 = pSegTmp->x2; 1137 } 1138 1139 if(pSegTmp->y2 > pSegTmp->y1) { 1140 box.y1 = pSegTmp->y1; 1141 box.y2 = pSegTmp->y2; 1142 } else { 1143 box.y2 = pSegTmp->y1; 1144 box.y1 = pSegTmp->y2; 1145 } 1146 1147 while(--nsegTmp) 1148 { 1149 pSegTmp++; 1150 if(pSegTmp->x2 > pSegTmp->x1) 1151 { 1152 if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1; 1153 if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2; 1154 } 1155 else 1156 { 1157 if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2; 1158 if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1; 1159 } 1160 if(pSegTmp->y2 > pSegTmp->y1) 1161 { 1162 if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1; 1163 if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2; 1164 } 1165 else 1166 { 1167 if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2; 1168 if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1; 1169 } 1170 } 1171 1172 box.x2++; 1173 box.y2++; 1174 1175 if(extra) 1176 { 1177 box.x1 -= extra; 1178 box.x2 += extra; 1179 box.y1 -= extra; 1180 box.y2 += extra; 1181 } 1182 1183 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1184 if(BOX_NOT_EMPTY(box)) 1185 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1186 } 1187 (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); 1188 damageRegionProcessPending (pDrawable); 1189 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1190} 1191 1192static void 1193damagePolyRectangle(DrawablePtr pDrawable, 1194 GCPtr pGC, 1195 int nRects, 1196 xRectangle *pRects) 1197{ 1198 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1199 1200 if (nRects && checkGCDamage (pDrawable, pGC)) 1201 { 1202 BoxRec box; 1203 int offset1, offset2, offset3; 1204 int nRectsTmp = nRects; 1205 xRectangle *pRectsTmp = pRects; 1206 1207 offset2 = pGC->lineWidth; 1208 if(!offset2) offset2 = 1; 1209 offset1 = offset2 >> 1; 1210 offset3 = offset2 - offset1; 1211 1212 while(nRectsTmp--) 1213 { 1214 box.x1 = pRectsTmp->x - offset1; 1215 box.y1 = pRectsTmp->y - offset1; 1216 box.x2 = box.x1 + pRectsTmp->width + offset2; 1217 box.y2 = box.y1 + offset2; 1218 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1219 if(BOX_NOT_EMPTY(box)) 1220 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1221 1222 box.x1 = pRectsTmp->x - offset1; 1223 box.y1 = pRectsTmp->y + offset3; 1224 box.x2 = box.x1 + offset2; 1225 box.y2 = box.y1 + pRectsTmp->height - offset2; 1226 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1227 if(BOX_NOT_EMPTY(box)) 1228 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1229 1230 box.x1 = pRectsTmp->x + pRectsTmp->width - offset1; 1231 box.y1 = pRectsTmp->y + offset3; 1232 box.x2 = box.x1 + offset2; 1233 box.y2 = box.y1 + pRectsTmp->height - offset2; 1234 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1235 if(BOX_NOT_EMPTY(box)) 1236 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1237 1238 box.x1 = pRectsTmp->x - offset1; 1239 box.y1 = pRectsTmp->y + pRectsTmp->height - offset1; 1240 box.x2 = box.x1 + pRectsTmp->width + offset2; 1241 box.y2 = box.y1 + offset2; 1242 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1243 if(BOX_NOT_EMPTY(box)) 1244 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1245 1246 pRectsTmp++; 1247 } 1248 } 1249 (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); 1250 damageRegionProcessPending (pDrawable); 1251 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1252} 1253 1254static void 1255damagePolyArc(DrawablePtr pDrawable, 1256 GCPtr pGC, 1257 int nArcs, 1258 xArc *pArcs) 1259{ 1260 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1261 1262 if (nArcs && checkGCDamage (pDrawable, pGC)) 1263 { 1264 int extra = pGC->lineWidth >> 1; 1265 BoxRec box; 1266 int nArcsTmp = nArcs; 1267 xArc *pArcsTmp = pArcs; 1268 1269 box.x1 = pArcsTmp->x; 1270 box.x2 = box.x1 + pArcsTmp->width; 1271 box.y1 = pArcsTmp->y; 1272 box.y2 = box.y1 + pArcsTmp->height; 1273 1274 while(--nArcsTmp) 1275 { 1276 pArcsTmp++; 1277 if(box.x1 > pArcsTmp->x) 1278 box.x1 = pArcsTmp->x; 1279 if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) 1280 box.x2 = pArcsTmp->x + pArcsTmp->width; 1281 if(box.y1 > pArcsTmp->y) 1282 box.y1 = pArcsTmp->y; 1283 if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) 1284 box.y2 = pArcsTmp->y + pArcsTmp->height; 1285 } 1286 1287 if(extra) 1288 { 1289 box.x1 -= extra; 1290 box.x2 += extra; 1291 box.y1 -= extra; 1292 box.y2 += extra; 1293 } 1294 1295 box.x2++; 1296 box.y2++; 1297 1298 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1299 if(BOX_NOT_EMPTY(box)) 1300 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1301 } 1302 (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); 1303 damageRegionProcessPending (pDrawable); 1304 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1305} 1306 1307static void 1308damageFillPolygon(DrawablePtr pDrawable, 1309 GCPtr pGC, 1310 int shape, 1311 int mode, 1312 int npt, 1313 DDXPointPtr ppt) 1314{ 1315 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1316 1317 if (npt > 2 && checkGCDamage (pDrawable, pGC)) 1318 { 1319 DDXPointPtr pptTmp = ppt; 1320 int nptTmp = npt; 1321 BoxRec box; 1322 1323 box.x2 = box.x1 = pptTmp->x; 1324 box.y2 = box.y1 = pptTmp->y; 1325 1326 if(mode != CoordModeOrigin) 1327 { 1328 int x = box.x1; 1329 int y = box.y1; 1330 while(--nptTmp) 1331 { 1332 pptTmp++; 1333 x += pptTmp->x; 1334 y += pptTmp->y; 1335 if(box.x1 > x) box.x1 = x; 1336 else if(box.x2 < x) box.x2 = x; 1337 if(box.y1 > y) box.y1 = y; 1338 else if(box.y2 < y) box.y2 = y; 1339 } 1340 } 1341 else 1342 { 1343 while(--nptTmp) 1344 { 1345 pptTmp++; 1346 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 1347 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; 1348 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 1349 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 1350 } 1351 } 1352 1353 box.x2++; 1354 box.y2++; 1355 1356 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1357 if(BOX_NOT_EMPTY(box)) 1358 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1359 } 1360 1361 (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); 1362 damageRegionProcessPending (pDrawable); 1363 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1364} 1365 1366 1367static void 1368damagePolyFillRect(DrawablePtr pDrawable, 1369 GCPtr pGC, 1370 int nRects, 1371 xRectangle *pRects) 1372{ 1373 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1374 if (nRects && checkGCDamage (pDrawable, pGC)) 1375 { 1376 BoxRec box; 1377 xRectangle *pRectsTmp = pRects; 1378 int nRectsTmp = nRects; 1379 1380 box.x1 = pRectsTmp->x; 1381 box.x2 = box.x1 + pRectsTmp->width; 1382 box.y1 = pRectsTmp->y; 1383 box.y2 = box.y1 + pRectsTmp->height; 1384 1385 while(--nRectsTmp) 1386 { 1387 pRectsTmp++; 1388 if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x; 1389 if(box.x2 < (pRectsTmp->x + pRectsTmp->width)) 1390 box.x2 = pRectsTmp->x + pRectsTmp->width; 1391 if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y; 1392 if(box.y2 < (pRectsTmp->y + pRectsTmp->height)) 1393 box.y2 = pRectsTmp->y + pRectsTmp->height; 1394 } 1395 1396 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1397 if(BOX_NOT_EMPTY(box)) 1398 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1399 } 1400 (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); 1401 damageRegionProcessPending (pDrawable); 1402 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1403} 1404 1405 1406static void 1407damagePolyFillArc(DrawablePtr pDrawable, 1408 GCPtr pGC, 1409 int nArcs, 1410 xArc *pArcs) 1411{ 1412 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1413 1414 if (nArcs && checkGCDamage (pDrawable, pGC)) 1415 { 1416 BoxRec box; 1417 int nArcsTmp = nArcs; 1418 xArc *pArcsTmp = pArcs; 1419 1420 box.x1 = pArcsTmp->x; 1421 box.x2 = box.x1 + pArcsTmp->width; 1422 box.y1 = pArcsTmp->y; 1423 box.y2 = box.y1 + pArcsTmp->height; 1424 1425 while(--nArcsTmp) 1426 { 1427 pArcsTmp++; 1428 if(box.x1 > pArcsTmp->x) 1429 box.x1 = pArcsTmp->x; 1430 if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) 1431 box.x2 = pArcsTmp->x + pArcsTmp->width; 1432 if(box.y1 > pArcsTmp->y) 1433 box.y1 = pArcsTmp->y; 1434 if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) 1435 box.y2 = pArcsTmp->y + pArcsTmp->height; 1436 } 1437 1438 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 1439 if(BOX_NOT_EMPTY(box)) 1440 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1441 } 1442 (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); 1443 damageRegionProcessPending (pDrawable); 1444 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1445} 1446 1447/* 1448 * general Poly/Image text function. Extract glyph information, 1449 * compute bounding box and remove cursor if it is overlapped. 1450 */ 1451 1452static void 1453damageDamageChars (DrawablePtr pDrawable, 1454 FontPtr font, 1455 int x, 1456 int y, 1457 unsigned int n, 1458 CharInfoPtr *charinfo, 1459 Bool imageblt, 1460 int subWindowMode) 1461{ 1462 ExtentInfoRec extents; 1463 BoxRec box; 1464 1465 QueryGlyphExtents(font, charinfo, n, &extents); 1466 if (imageblt) 1467 { 1468 if (extents.overallWidth > extents.overallRight) 1469 extents.overallRight = extents.overallWidth; 1470 if (extents.overallWidth < extents.overallLeft) 1471 extents.overallLeft = extents.overallWidth; 1472 if (extents.overallLeft > 0) 1473 extents.overallLeft = 0; 1474 if (extents.fontAscent > extents.overallAscent) 1475 extents.overallAscent = extents.fontAscent; 1476 if (extents.fontDescent > extents.overallDescent) 1477 extents.overallDescent = extents.fontDescent; 1478 } 1479 box.x1 = x + extents.overallLeft; 1480 box.y1 = y - extents.overallAscent; 1481 box.x2 = x + extents.overallRight; 1482 box.y2 = y + extents.overallDescent; 1483 damageDamageBox (pDrawable, &box, subWindowMode); 1484} 1485 1486/* 1487 * values for textType: 1488 */ 1489#define TT_POLY8 0 1490#define TT_IMAGE8 1 1491#define TT_POLY16 2 1492#define TT_IMAGE16 3 1493 1494static int 1495damageText (DrawablePtr pDrawable, 1496 GCPtr pGC, 1497 int x, 1498 int y, 1499 unsigned long count, 1500 char *chars, 1501 FontEncoding fontEncoding, 1502 Bool textType) 1503{ 1504 CharInfoPtr *charinfo; 1505 CharInfoPtr *info; 1506 unsigned long i; 1507 unsigned int n; 1508 int w; 1509 Bool imageblt; 1510 1511 imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); 1512 1513 charinfo = malloc(count * sizeof(CharInfoPtr)); 1514 if (!charinfo) 1515 return x; 1516 1517 GetGlyphs(pGC->font, count, (unsigned char *)chars, 1518 fontEncoding, &i, charinfo); 1519 n = (unsigned int)i; 1520 w = 0; 1521 if (!imageblt) 1522 for (info = charinfo; i--; info++) 1523 w += (*info)->metrics.characterWidth; 1524 1525 if (n != 0) { 1526 damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n, 1527 charinfo, imageblt, pGC->subWindowMode); 1528 if (imageblt) 1529 (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, 1530 FONTGLYPHS(pGC->font)); 1531 else 1532 (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, 1533 FONTGLYPHS(pGC->font)); 1534 } 1535 free(charinfo); 1536 return x + w; 1537} 1538 1539static int 1540damagePolyText8(DrawablePtr pDrawable, 1541 GCPtr pGC, 1542 int x, 1543 int y, 1544 int count, 1545 char *chars) 1546{ 1547 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1548 1549 if (checkGCDamage (pDrawable, pGC)) 1550 x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, 1551 Linear8Bit, TT_POLY8); 1552 else 1553 x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); 1554 damageRegionProcessPending (pDrawable); 1555 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1556 return x; 1557} 1558 1559static int 1560damagePolyText16(DrawablePtr pDrawable, 1561 GCPtr pGC, 1562 int x, 1563 int y, 1564 int count, 1565 unsigned short *chars) 1566{ 1567 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1568 1569 if (checkGCDamage (pDrawable, pGC)) 1570 x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, 1571 FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, 1572 TT_POLY16); 1573 else 1574 x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); 1575 damageRegionProcessPending (pDrawable); 1576 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1577 return x; 1578} 1579 1580static void 1581damageImageText8(DrawablePtr pDrawable, 1582 GCPtr pGC, 1583 int x, 1584 int y, 1585 int count, 1586 char *chars) 1587{ 1588 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1589 1590 if (checkGCDamage (pDrawable, pGC)) 1591 damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, 1592 Linear8Bit, TT_IMAGE8); 1593 else 1594 (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); 1595 damageRegionProcessPending (pDrawable); 1596 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1597} 1598 1599static void 1600damageImageText16(DrawablePtr pDrawable, 1601 GCPtr pGC, 1602 int x, 1603 int y, 1604 int count, 1605 unsigned short *chars) 1606{ 1607 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1608 1609 if (checkGCDamage (pDrawable, pGC)) 1610 damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, 1611 FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, 1612 TT_IMAGE16); 1613 else 1614 (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); 1615 damageRegionProcessPending (pDrawable); 1616 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1617} 1618 1619 1620static void 1621damageImageGlyphBlt(DrawablePtr pDrawable, 1622 GCPtr pGC, 1623 int x, 1624 int y, 1625 unsigned int nglyph, 1626 CharInfoPtr *ppci, 1627 pointer pglyphBase) 1628{ 1629 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1630 damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, 1631 nglyph, ppci, TRUE, pGC->subWindowMode); 1632 (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, 1633 ppci, pglyphBase); 1634 damageRegionProcessPending (pDrawable); 1635 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1636} 1637 1638static void 1639damagePolyGlyphBlt(DrawablePtr pDrawable, 1640 GCPtr pGC, 1641 int x, 1642 int y, 1643 unsigned int nglyph, 1644 CharInfoPtr *ppci, 1645 pointer pglyphBase) 1646{ 1647 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1648 damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, 1649 nglyph, ppci, FALSE, pGC->subWindowMode); 1650 (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, 1651 ppci, pglyphBase); 1652 damageRegionProcessPending (pDrawable); 1653 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1654} 1655 1656static void 1657damagePushPixels(GCPtr pGC, 1658 PixmapPtr pBitMap, 1659 DrawablePtr pDrawable, 1660 int dx, 1661 int dy, 1662 int xOrg, 1663 int yOrg) 1664{ 1665 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); 1666 if(checkGCDamage (pDrawable, pGC)) 1667 { 1668 BoxRec box; 1669 1670 box.x1 = xOrg; 1671 box.y1 = yOrg; 1672 1673 if(!pGC->miTranslate) { 1674 box.x1 += pDrawable->x; 1675 box.y1 += pDrawable->y; 1676 } 1677 1678 box.x2 = box.x1 + dx; 1679 box.y2 = box.y1 + dy; 1680 1681 TRIM_BOX(box, pGC); 1682 if(BOX_NOT_EMPTY(box)) 1683 damageDamageBox (pDrawable, &box, pGC->subWindowMode); 1684 } 1685 (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); 1686 damageRegionProcessPending (pDrawable); 1687 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); 1688} 1689 1690static void 1691damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage) 1692{ 1693 while (*pPrev) 1694 { 1695 if (*pPrev == pDamage) 1696 { 1697 *pPrev = pDamage->pNext; 1698 return; 1699 } 1700 pPrev = &(*pPrev)->pNext; 1701 } 1702#if DAMAGE_VALIDATE_ENABLE 1703 ErrorF ("Damage not on list\n"); 1704 OsAbort (); 1705#endif 1706} 1707 1708static void 1709damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage) 1710{ 1711#if DAMAGE_VALIDATE_ENABLE 1712 DamagePtr pOld; 1713 1714 for (pOld = *pPrev; pOld; pOld = pOld->pNext) 1715 if (pOld == pDamage) { 1716 ErrorF ("Damage already on list\n"); 1717 OsAbort (); 1718 } 1719#endif 1720 pDamage->pNext = *pPrev; 1721 *pPrev = pDamage; 1722} 1723 1724static Bool 1725damageDestroyPixmap (PixmapPtr pPixmap) 1726{ 1727 ScreenPtr pScreen = pPixmap->drawable.pScreen; 1728 damageScrPriv(pScreen); 1729 1730 if (pPixmap->refcnt == 1) 1731 { 1732 DamagePtr *pPrev = getPixmapDamageRef (pPixmap); 1733 DamagePtr pDamage; 1734 1735 while ((pDamage = *pPrev)) 1736 { 1737 damageRemoveDamage (pPrev, pDamage); 1738 if (!pDamage->isWindow) 1739 DamageDestroy (pDamage); 1740 } 1741 } 1742 unwrap (pScrPriv, pScreen, DestroyPixmap); 1743 (*pScreen->DestroyPixmap) (pPixmap); 1744 wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); 1745 return TRUE; 1746} 1747 1748static void 1749damageCopyWindow(WindowPtr pWindow, 1750 DDXPointRec ptOldOrg, 1751 RegionPtr prgnSrc) 1752{ 1753 ScreenPtr pScreen = pWindow->drawable.pScreen; 1754 damageScrPriv(pScreen); 1755 1756 if (getWindowDamage (pWindow)) 1757 { 1758 int dx = pWindow->drawable.x - ptOldOrg.x; 1759 int dy = pWindow->drawable.y - ptOldOrg.y; 1760 1761 /* 1762 * The region comes in source relative, but the damage occurs 1763 * at the destination location. Translate back and forth. 1764 */ 1765 RegionTranslate(prgnSrc, dx, dy); 1766 damageRegionAppend (&pWindow->drawable, prgnSrc, FALSE, -1); 1767 RegionTranslate(prgnSrc, -dx, -dy); 1768 } 1769 unwrap (pScrPriv, pScreen, CopyWindow); 1770 (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); 1771 damageRegionProcessPending (&pWindow->drawable); 1772 wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); 1773} 1774 1775static GCOps damageGCOps = { 1776 damageFillSpans, damageSetSpans, 1777 damagePutImage, damageCopyArea, 1778 damageCopyPlane, damagePolyPoint, 1779 damagePolylines, damagePolySegment, 1780 damagePolyRectangle, damagePolyArc, 1781 damageFillPolygon, damagePolyFillRect, 1782 damagePolyFillArc, damagePolyText8, 1783 damagePolyText16, damageImageText8, 1784 damageImageText16, damageImageGlyphBlt, 1785 damagePolyGlyphBlt, damagePushPixels, 1786 {NULL} /* devPrivate */ 1787}; 1788 1789static void 1790damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) 1791{ 1792 DamagePtr pDamage; 1793 ScreenPtr pScreen = pWindow->drawable.pScreen; 1794 damageScrPriv(pScreen); 1795 1796 if ((pDamage = damageGetWinPriv(pWindow))) 1797 { 1798 PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow); 1799 DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap); 1800 1801 while (pDamage) 1802 { 1803 damageRemoveDamage (pPrev, pDamage); 1804 pDamage = pDamage->pNextWin; 1805 } 1806 } 1807 unwrap (pScrPriv, pScreen, SetWindowPixmap); 1808 (*pScreen->SetWindowPixmap) (pWindow, pPixmap); 1809 wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); 1810 if ((pDamage = damageGetWinPriv(pWindow))) 1811 { 1812 DamagePtr *pPrev = getPixmapDamageRef(pPixmap); 1813 1814 while (pDamage) 1815 { 1816 damageInsertDamage (pPrev, pDamage); 1817 pDamage = pDamage->pNextWin; 1818 } 1819 } 1820} 1821 1822static Bool 1823damageDestroyWindow (WindowPtr pWindow) 1824{ 1825 DamagePtr pDamage; 1826 ScreenPtr pScreen = pWindow->drawable.pScreen; 1827 Bool ret; 1828 damageScrPriv(pScreen); 1829 1830 while ((pDamage = damageGetWinPriv(pWindow))) 1831 { 1832 DamageUnregister (&pWindow->drawable, pDamage); 1833 DamageDestroy (pDamage); 1834 } 1835 unwrap (pScrPriv, pScreen, DestroyWindow); 1836 ret = (*pScreen->DestroyWindow) (pWindow); 1837 wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); 1838 return ret; 1839} 1840 1841static Bool 1842damageCloseScreen (int i, ScreenPtr pScreen) 1843{ 1844 damageScrPriv(pScreen); 1845 1846 unwrap (pScrPriv, pScreen, DestroyPixmap); 1847 unwrap (pScrPriv, pScreen, CreateGC); 1848 unwrap (pScrPriv, pScreen, CopyWindow); 1849 unwrap (pScrPriv, pScreen, CloseScreen); 1850 free(pScrPriv); 1851 return (*pScreen->CloseScreen) (i, pScreen); 1852} 1853 1854/** 1855 * Default implementations of the damage management functions. 1856 */ 1857void miDamageCreate (DamagePtr pDamage) 1858{ 1859} 1860 1861void miDamageRegister (DrawablePtr pDrawable, DamagePtr pDamage) 1862{ 1863} 1864 1865void miDamageUnregister (DrawablePtr pDrawable, DamagePtr pDamage) 1866{ 1867} 1868 1869void miDamageDestroy (DamagePtr pDamage) 1870{ 1871} 1872 1873/** 1874 * Public functions for consumption outside this file. 1875 */ 1876 1877Bool 1878DamageSetup (ScreenPtr pScreen) 1879{ 1880 DamageScrPrivPtr pScrPriv; 1881 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 1882 const DamageScreenFuncsRec miFuncs = { 1883 miDamageCreate, miDamageRegister, miDamageUnregister, miDamageDestroy 1884 }; 1885 1886 if (!dixRegisterPrivateKey(&damageScrPrivateKeyRec, PRIVATE_SCREEN, 0)) 1887 return FALSE; 1888 1889 if (dixLookupPrivate(&pScreen->devPrivates, damageScrPrivateKey)) 1890 return TRUE; 1891 1892 if (!dixRegisterPrivateKey(&damageGCPrivateKeyRec, PRIVATE_GC, sizeof(DamageGCPrivRec))) 1893 return FALSE; 1894 1895 if (!dixRegisterPrivateKey(&damagePixPrivateKeyRec, PRIVATE_PIXMAP, 0)) 1896 return FALSE; 1897 1898 if (!dixRegisterPrivateKey(&damageWinPrivateKeyRec, PRIVATE_WINDOW, 0)) 1899 return FALSE; 1900 1901 pScrPriv = malloc(sizeof (DamageScrPrivRec)); 1902 if (!pScrPriv) 1903 return FALSE; 1904 1905 pScrPriv->internalLevel = 0; 1906 pScrPriv->pScreenDamage = 0; 1907 1908 wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); 1909 wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); 1910 wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); 1911 wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); 1912 wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); 1913 wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); 1914 if (ps) { 1915 wrap (pScrPriv, ps, Glyphs, damageGlyphs); 1916 wrap (pScrPriv, ps, Composite, damageComposite); 1917 wrap (pScrPriv, ps, AddTraps, damageAddTraps); 1918 } 1919 1920 pScrPriv->funcs = miFuncs; 1921 1922 dixSetPrivate(&pScreen->devPrivates, damageScrPrivateKey, pScrPriv); 1923 return TRUE; 1924} 1925 1926DamagePtr 1927DamageCreate (DamageReportFunc damageReport, 1928 DamageDestroyFunc damageDestroy, 1929 DamageReportLevel damageLevel, 1930 Bool isInternal, 1931 ScreenPtr pScreen, 1932 void *closure) 1933{ 1934 damageScrPriv(pScreen); 1935 DamagePtr pDamage; 1936 1937 pDamage = dixAllocateObjectWithPrivates(DamageRec, PRIVATE_DAMAGE); 1938 if (!pDamage) 1939 return 0; 1940 pDamage->pNext = 0; 1941 pDamage->pNextWin = 0; 1942 RegionNull(&pDamage->damage); 1943 RegionNull(&pDamage->pendingDamage); 1944 1945 pDamage->damageLevel = damageLevel; 1946 pDamage->isInternal = isInternal; 1947 pDamage->closure = closure; 1948 pDamage->isWindow = FALSE; 1949 pDamage->pDrawable = 0; 1950 pDamage->reportAfter = FALSE; 1951 1952 pDamage->damageReport = damageReport; 1953 pDamage->damageReportPostRendering = NULL; 1954 pDamage->damageDestroy = damageDestroy; 1955 pDamage->damageMarker = NULL; 1956 pDamage->pScreen = pScreen; 1957 1958 (*pScrPriv->funcs.Create) (pDamage); 1959 1960 return pDamage; 1961} 1962 1963void 1964DamageRegister (DrawablePtr pDrawable, 1965 DamagePtr pDamage) 1966{ 1967 ScreenPtr pScreen = pDrawable->pScreen; 1968 damageScrPriv(pScreen); 1969 1970#if DAMAGE_VALIDATE_ENABLE 1971 if (pDrawable->pScreen != pDamage->pScreen) 1972 { 1973 ErrorF ("DamageRegister called with mismatched screens\n"); 1974 OsAbort (); 1975 } 1976#endif 1977 1978 if (pDrawable->type == DRAWABLE_WINDOW) 1979 { 1980 WindowPtr pWindow = (WindowPtr) pDrawable; 1981 winDamageRef(pWindow); 1982 1983#if DAMAGE_VALIDATE_ENABLE 1984 DamagePtr pOld; 1985 1986 for (pOld = *pPrev; pOld; pOld = pOld->pNextWin) 1987 if (pOld == pDamage) { 1988 ErrorF ("Damage already on window list\n"); 1989 OsAbort (); 1990 } 1991#endif 1992 pDamage->pNextWin = *pPrev; 1993 *pPrev = pDamage; 1994 pDamage->isWindow = TRUE; 1995 } 1996 else 1997 pDamage->isWindow = FALSE; 1998 pDamage->pDrawable = pDrawable; 1999 damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); 2000 (*pScrPriv->funcs.Register) (pDrawable, pDamage); 2001} 2002 2003void 2004DamageDrawInternal (ScreenPtr pScreen, Bool enable) 2005{ 2006 damageScrPriv (pScreen); 2007 2008 pScrPriv->internalLevel += enable ? 1 : -1; 2009} 2010 2011void 2012DamageUnregister (DrawablePtr pDrawable, 2013 DamagePtr pDamage) 2014{ 2015 ScreenPtr pScreen = pDrawable->pScreen; 2016 damageScrPriv(pScreen); 2017 2018 (*pScrPriv->funcs.Unregister) (pDrawable, pDamage); 2019 2020 if (pDrawable->type == DRAWABLE_WINDOW) 2021 { 2022 WindowPtr pWindow = (WindowPtr) pDrawable; 2023 winDamageRef (pWindow); 2024#if DAMAGE_VALIDATE_ENABLE 2025 int found = 0; 2026#endif 2027 2028 while (*pPrev) 2029 { 2030 if (*pPrev == pDamage) 2031 { 2032 *pPrev = pDamage->pNextWin; 2033#if DAMAGE_VALIDATE_ENABLE 2034 found = 1; 2035#endif 2036 break; 2037 } 2038 pPrev = &(*pPrev)->pNextWin; 2039 } 2040#if DAMAGE_VALIDATE_ENABLE 2041 if (!found) { 2042 ErrorF ("Damage not on window list\n"); 2043 OsAbort (); 2044 } 2045#endif 2046 } 2047 pDamage->pDrawable = 0; 2048 damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); 2049} 2050 2051void 2052DamageDestroy (DamagePtr pDamage) 2053{ 2054 ScreenPtr pScreen = pDamage->pScreen; 2055 damageScrPriv(pScreen); 2056 2057 if (pDamage->damageDestroy) 2058 (*pDamage->damageDestroy) (pDamage, pDamage->closure); 2059 (*pScrPriv->funcs.Destroy) (pDamage); 2060 RegionUninit(&pDamage->damage); 2061 RegionUninit(&pDamage->pendingDamage); 2062 dixFreeObjectWithPrivates(pDamage, PRIVATE_DAMAGE); 2063} 2064 2065Bool 2066DamageSubtract (DamagePtr pDamage, 2067 const RegionPtr pRegion) 2068{ 2069 RegionPtr pClip; 2070 RegionRec pixmapClip; 2071 DrawablePtr pDrawable = pDamage->pDrawable; 2072 2073 RegionSubtract(&pDamage->damage, &pDamage->damage, pRegion); 2074 if (pDrawable) 2075 { 2076 if (pDrawable->type == DRAWABLE_WINDOW) 2077 pClip = &((WindowPtr) pDrawable)->borderClip; 2078 else 2079 { 2080 BoxRec box; 2081 2082 box.x1 = pDrawable->x; 2083 box.y1 = pDrawable->y; 2084 box.x2 = pDrawable->x + pDrawable->width; 2085 box.y2 = pDrawable->y + pDrawable->height; 2086 RegionInit(&pixmapClip, &box, 1); 2087 pClip = &pixmapClip; 2088 } 2089 RegionTranslate(&pDamage->damage, pDrawable->x, pDrawable->y); 2090 RegionIntersect(&pDamage->damage, &pDamage->damage, pClip); 2091 RegionTranslate(&pDamage->damage, -pDrawable->x, -pDrawable->y); 2092 if (pDrawable->type != DRAWABLE_WINDOW) 2093 RegionUninit(&pixmapClip); 2094 } 2095 return RegionNotEmpty(&pDamage->damage); 2096} 2097 2098void 2099DamageEmpty (DamagePtr pDamage) 2100{ 2101 RegionEmpty(&pDamage->damage); 2102} 2103 2104RegionPtr 2105DamageRegion (DamagePtr pDamage) 2106{ 2107 return &pDamage->damage; 2108} 2109 2110RegionPtr 2111DamagePendingRegion (DamagePtr pDamage) 2112{ 2113 return &pDamage->pendingDamage; 2114} 2115 2116void 2117DamageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion) 2118{ 2119 damageRegionAppend (pDrawable, pRegion, FALSE, -1); 2120} 2121 2122void 2123DamageRegionProcessPending (DrawablePtr pDrawable) 2124{ 2125 damageRegionProcessPending (pDrawable); 2126} 2127 2128/* If a damage marker is provided, then this function must be called after rendering is done. */ 2129/* Please do call back so any future enhancements can assume this function is called. */ 2130/* There are no strict timing requirements for calling this function, just as soon as (is cheaply) possible. */ 2131void 2132DamageRegionRendered (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion) 2133{ 2134 if (pDamage->damageReportPostRendering) 2135 damageReportDamagePostRendering (pDamage, pOldDamage, pRegion); 2136} 2137 2138/* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */ 2139void 2140DamageDamageRegion (DrawablePtr pDrawable, 2141 RegionPtr pRegion) 2142{ 2143 damageRegionAppend (pDrawable, pRegion, FALSE, -1); 2144 2145 /* Go back and report this damage for DamagePtrs with reportAfter set, since 2146 * this call isn't part of an in-progress drawing op in the call chain and 2147 * the DDX probably just wants to know about it right away. 2148 */ 2149 damageRegionProcessPending (pDrawable); 2150} 2151 2152void 2153DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter) 2154{ 2155 pDamage->reportAfter = reportAfter; 2156} 2157 2158void 2159DamageSetPostRenderingFunctions(DamagePtr pDamage, DamageReportFunc damageReportPostRendering, 2160 DamageMarkerFunc damageMarker) 2161{ 2162 pDamage->damageReportPostRendering = damageReportPostRendering; 2163 pDamage->damageMarker = damageMarker; 2164} 2165 2166DamageScreenFuncsPtr 2167DamageGetScreenFuncs (ScreenPtr pScreen) 2168{ 2169 damageScrPriv(pScreen); 2170 return &pScrPriv->funcs; 2171} 2172