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