First import
[xorg_rtime.git] / xorg-server-1.4 / miext / damage / damage.c
blob2acff11e8b0c71bf2207ee6622c50767da01126d
1 /*
2 * Copyright © 2003 Keith Packard
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.
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.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
27 #include <stdlib.h>
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
45 #define wrap(priv, real, mem, func) {\
46 priv->mem = real->mem; \
47 real->mem = func; \
50 #define unwrap(priv, real, mem) {\
51 real->mem = priv->mem; \
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)
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
68 #define getPixmapDamageRef(pPixmap) \
69 ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr))
71 #define pixmapDamage(pPixmap) damagePixPriv(pPixmap)
73 static int damageScrPrivateIndex;
74 static int damagePixPrivateIndex;
75 static int damageGCPrivateIndex;
76 static int damageWinPrivateIndex;
77 static int damageGeneration;
79 static DamagePtr *
80 getDrawableDamageRef (DrawablePtr pDrawable)
82 PixmapPtr pPixmap;
84 if (pDrawable->type == DRAWABLE_WINDOW)
86 ScreenPtr pScreen = pDrawable->pScreen;
88 pPixmap = 0;
89 if (pScreen->GetWindowPixmap
90 #ifdef ROOTLESS_WORKAROUND
91 && ((WindowPtr)pDrawable)->viewable
92 #endif
94 pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable);
96 if (!pPixmap)
98 damageScrPriv(pScreen);
100 return &pScrPriv->pScreenDamage;
103 else
104 pPixmap = (PixmapPtr) pDrawable;
105 return getPixmapDamageRef (pPixmap);
108 #define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable))
109 #define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable)
111 #define drawableDamage(pDrawable) \
112 DamagePtr pDamage = getDrawableDamage(pDrawable)
114 #define windowDamage(pWin) drawableDamage(&(pWin)->drawable)
116 #define winDamageRef(pWindow) \
117 DamagePtr *pPrev = (DamagePtr *) \
118 &(pWindow->devPrivates[damageWinPrivateIndex].ptr)
120 static void
121 DamageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion)
123 BoxRec tmpBox;
124 RegionRec tmpRegion;
125 Bool was_empty;
127 switch (pDamage->damageLevel) {
128 case DamageReportRawRegion:
129 (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure);
130 break;
131 case DamageReportDeltaRegion:
132 REGION_NULL (pScreen, &tmpRegion);
133 REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage);
134 if (REGION_NOTEMPTY (pScreen, &tmpRegion)) {
135 REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
136 pDamageRegion);
137 (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure);
139 REGION_UNINIT(pScreen, &tmpRegion);
140 break;
141 case DamageReportBoundingBox:
142 tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage);
143 REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
144 pDamageRegion);
145 if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) {
146 (*pDamage->damageReport) (pDamage, &pDamage->damage,
147 pDamage->closure);
149 break;
150 case DamageReportNonEmpty:
151 was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage);
152 REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
153 pDamageRegion);
154 if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) {
155 (*pDamage->damageReport) (pDamage, &pDamage->damage,
156 pDamage->closure);
158 break;
159 case DamageReportNone:
160 REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
161 pDamageRegion);
162 break;
166 #if DAMAGE_DEBUG_ENABLE
167 static void
168 _damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where)
169 #define damageDamageRegion(d,r,c,m) _damageDamageRegion(d,r,c,m,__FUNCTION__)
170 #else
171 static void
172 damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
173 int subWindowMode)
174 #endif
176 ScreenPtr pScreen = pDrawable->pScreen;
177 damageScrPriv(pScreen);
178 drawableDamage(pDrawable);
179 DamagePtr pNext;
180 RegionRec clippedRec;
181 RegionPtr pDamageRegion;
182 RegionRec pixClip;
183 int draw_x, draw_y;
184 #ifdef COMPOSITE
185 int screen_x = 0, screen_y = 0;
186 #endif
188 /* short circuit for empty regions */
189 if (!REGION_NOTEMPTY(pScreen, pRegion))
190 return;
192 #ifdef COMPOSITE
194 * When drawing to a pixmap which is storing window contents,
195 * the region presented is in pixmap relative coordinates which
196 * need to be converted to screen relative coordinates
198 if (pDrawable->type != DRAWABLE_WINDOW)
200 screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x;
201 screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y;
203 if (screen_x || screen_y)
204 REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y);
205 #endif
207 if (pDrawable->type == DRAWABLE_WINDOW &&
208 ((WindowPtr)(pDrawable))->backingStore == NotUseful)
210 if (subWindowMode == ClipByChildren)
212 REGION_INTERSECT(pScreen, pRegion, pRegion,
213 &((WindowPtr)(pDrawable))->clipList);
215 else if (subWindowMode == IncludeInferiors)
217 RegionPtr pTempRegion =
218 NotClippedByChildren((WindowPtr)(pDrawable));
219 REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion);
220 REGION_DESTROY(pScreen, pTempRegion);
222 /* If subWindowMode is set to an invalid value, don't perform
223 * any drawable-based clipping. */
227 REGION_NULL (pScreen, &clippedRec);
228 for (; pDamage; pDamage = pNext)
230 pNext = pDamage->pNext;
232 * Check for internal damage and don't send events
234 if (pScrPriv->internalLevel > 0 && !pDamage->isInternal)
236 DAMAGE_DEBUG (("non internal damage, skipping at %d\n",
237 pScrPriv->internalLevel));
238 continue;
241 * Check for unrealized windows
243 if (pDamage->pDrawable->type == DRAWABLE_WINDOW &&
244 !((WindowPtr) (pDamage->pDrawable))->realized)
246 #if 0
247 DAMAGE_DEBUG (("damage while window unrealized\n"));
248 #endif
249 continue;
252 draw_x = pDamage->pDrawable->x;
253 draw_y = pDamage->pDrawable->y;
254 #ifdef COMPOSITE
256 * Need to move everyone to screen coordinates
257 * XXX what about off-screen pixmaps with non-zero x/y?
259 if (pDamage->pDrawable->type != DRAWABLE_WINDOW)
261 draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x;
262 draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y;
264 #endif
267 * Clip against border or pixmap bounds
270 pDamageRegion = pRegion;
271 if (clip || pDamage->pDrawable != pDrawable)
273 pDamageRegion = &clippedRec;
274 if (pDamage->pDrawable->type == DRAWABLE_WINDOW) {
275 REGION_INTERSECT (pScreen, pDamageRegion, pRegion,
276 &((WindowPtr)(pDamage->pDrawable))->borderClip);
277 } else {
278 BoxRec box;
279 box.x1 = draw_x;
280 box.y1 = draw_y;
281 box.x2 = draw_x + pDamage->pDrawable->width;
282 box.y2 = draw_y + pDamage->pDrawable->height;
283 REGION_INIT(pScreen, &pixClip, &box, 1);
284 REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip);
285 REGION_UNINIT(pScreen, &pixClip);
288 * Short circuit empty results
290 if (!REGION_NOTEMPTY(pScreen, pDamageRegion))
291 continue;
294 DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
295 where,
296 pDamageRegion->extents.x2 - pDamageRegion->extents.x1,
297 pDamageRegion->extents.y2 - pDamageRegion->extents.y1,
298 pDamageRegion->extents.x1, pDamageRegion->extents.y1,
299 pDrawable->id, pDamage->pDrawable->id));
302 * Move region to target coordinate space
304 if (draw_x || draw_y)
305 REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y);
307 /* If the damage rec has been flagged to report damage after the op has
308 * completed, then union it into the delayed damage region, which will
309 * be used for reporting after calling down, and skip the reporting
311 if (!pDamage->reportAfter) {
312 DamageReportDamage (pDamage, pDamageRegion);
313 } else {
314 REGION_UNION(pScreen, &pDamage->pendingDamage,
315 &pDamage->pendingDamage, pDamageRegion);
319 * translate original region back
321 if (pDamageRegion == pRegion && (draw_x || draw_y))
322 REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y);
324 #ifdef COMPOSITE
325 if (screen_x || screen_y)
326 REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y);
327 #endif
329 REGION_UNINIT (pScreen, &clippedRec);
332 static void
333 damageReportPostOp (DrawablePtr pDrawable)
335 drawableDamage(pDrawable);
337 for (; pDamage != NULL; pDamage = pDamage->pNext)
339 if (pDamage->reportAfter) {
340 DamageReportDamage (pDamage, &pDamage->pendingDamage);
341 REGION_EMPTY (pScreen, &pDamage->pendingDamage);
347 #if DAMAGE_DEBUG_ENABLE
348 #define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
349 static void
350 _damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where)
351 #else
352 static void
353 damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode)
354 #endif
356 RegionRec region;
358 REGION_INIT (pDrawable->pScreen, &region, pBox, 1);
359 #if DAMAGE_DEBUG_ENABLE
360 _damageDamageRegion (pDrawable, &region, TRUE, subWindowMode, where);
361 #else
362 damageDamageRegion (pDrawable, &region, TRUE, subWindowMode);
363 #endif
364 REGION_UNINIT (pDrawable->pScreen, &region);
367 static void damageValidateGC(GCPtr, unsigned long, DrawablePtr);
368 static void damageChangeGC(GCPtr, unsigned long);
369 static void damageCopyGC(GCPtr, unsigned long, GCPtr);
370 static void damageDestroyGC(GCPtr);
371 static void damageChangeClip(GCPtr, int, pointer, int);
372 static void damageDestroyClip(GCPtr);
373 static void damageCopyClip(GCPtr, GCPtr);
375 static GCFuncs damageGCFuncs = {
376 damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC,
377 damageChangeClip, damageDestroyClip, damageCopyClip
380 static GCOps damageGCOps;
382 static Bool
383 damageCreateGC(GCPtr pGC)
385 ScreenPtr pScreen = pGC->pScreen;
386 damageScrPriv(pScreen);
387 damageGCPriv(pGC);
388 Bool ret;
390 pGC->pCompositeClip = 0;
391 unwrap (pScrPriv, pScreen, CreateGC);
392 if((ret = (*pScreen->CreateGC) (pGC))) {
393 pGCPriv->ops = NULL;
394 pGCPriv->funcs = pGC->funcs;
395 pGC->funcs = &damageGCFuncs;
397 wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
399 return ret;
402 #ifdef NOTUSED
403 static void
404 damageWrapGC (GCPtr pGC)
406 damageGCPriv(pGC);
408 pGCPriv->ops = NULL;
409 pGCPriv->funcs = pGC->funcs;
410 pGC->funcs = &damageGCFuncs;
413 static void
414 damageUnwrapGC (GCPtr pGC)
416 damageGCPriv(pGC);
418 pGC->funcs = pGCPriv->funcs;
419 if (pGCPriv->ops)
420 pGC->ops = pGCPriv->ops;
422 #endif
424 #define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
425 damageGCPriv(pGC); \
426 GCFuncs *oldFuncs = pGC->funcs; \
427 unwrap(pGCPriv, pGC, funcs); \
428 unwrap(pGCPriv, pGC, ops); \
430 #define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
431 wrap(pGCPriv, pGC, funcs, oldFuncs); \
432 wrap(pGCPriv, pGC, ops, &damageGCOps)
434 #define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
435 damageGCPriv(pGC); \
436 unwrap(pGCPriv, pGC, funcs); \
437 if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
439 #define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
440 wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \
441 if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
443 static void
444 damageValidateGC(GCPtr pGC,
445 unsigned long changes,
446 DrawablePtr pDrawable)
448 DAMAGE_GC_FUNC_PROLOGUE (pGC);
449 (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
450 pGCPriv->ops = pGC->ops; /* just so it's not NULL */
451 DAMAGE_GC_FUNC_EPILOGUE (pGC);
454 static void
455 damageDestroyGC(GCPtr pGC)
457 DAMAGE_GC_FUNC_PROLOGUE (pGC);
458 (*pGC->funcs->DestroyGC)(pGC);
459 DAMAGE_GC_FUNC_EPILOGUE (pGC);
462 static void
463 damageChangeGC (GCPtr pGC,
464 unsigned long mask)
466 DAMAGE_GC_FUNC_PROLOGUE (pGC);
467 (*pGC->funcs->ChangeGC) (pGC, mask);
468 DAMAGE_GC_FUNC_EPILOGUE (pGC);
471 static void
472 damageCopyGC (GCPtr pGCSrc,
473 unsigned long mask,
474 GCPtr pGCDst)
476 DAMAGE_GC_FUNC_PROLOGUE (pGCDst);
477 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
478 DAMAGE_GC_FUNC_EPILOGUE (pGCDst);
481 static void
482 damageChangeClip (GCPtr pGC,
483 int type,
484 pointer pvalue,
485 int nrects)
487 DAMAGE_GC_FUNC_PROLOGUE (pGC);
488 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
489 DAMAGE_GC_FUNC_EPILOGUE (pGC);
492 static void
493 damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
495 DAMAGE_GC_FUNC_PROLOGUE (pgcDst);
496 (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
497 DAMAGE_GC_FUNC_EPILOGUE (pgcDst);
500 static void
501 damageDestroyClip(GCPtr pGC)
503 DAMAGE_GC_FUNC_PROLOGUE (pGC);
504 (* pGC->funcs->DestroyClip)(pGC);
505 DAMAGE_GC_FUNC_EPILOGUE (pGC);
508 #define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
509 BoxPtr extents = &pGC->pCompositeClip->extents;\
510 if(box.x1 < extents->x1) box.x1 = extents->x1; \
511 if(box.x2 > extents->x2) box.x2 = extents->x2; \
512 if(box.y1 < extents->y1) box.y1 = extents->y1; \
513 if(box.y2 > extents->y2) box.y2 = extents->y2; \
516 #define TRANSLATE_BOX(box, pDrawable) { \
517 box.x1 += pDrawable->x; \
518 box.x2 += pDrawable->x; \
519 box.y1 += pDrawable->y; \
520 box.y2 += pDrawable->y; \
523 #define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
524 TRANSLATE_BOX(box, pDrawable); \
525 TRIM_BOX(box, pGC); \
528 #define BOX_NOT_EMPTY(box) \
529 (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
531 #define checkGCDamage(d,g) (getDrawableDamage(d) && \
532 (!g->pCompositeClip ||\
533 REGION_NOTEMPTY(d->pScreen, \
534 g->pCompositeClip)))
536 #ifdef RENDER
538 #define TRIM_PICTURE_BOX(box, pDst) { \
539 BoxPtr extents = &pDst->pCompositeClip->extents;\
540 if(box.x1 < extents->x1) box.x1 = extents->x1; \
541 if(box.x2 > extents->x2) box.x2 = extents->x2; \
542 if(box.y1 < extents->y1) box.y1 = extents->y1; \
543 if(box.y2 > extents->y2) box.y2 = extents->y2; \
546 #define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \
547 REGION_NOTEMPTY(pScreen, p->pCompositeClip))
549 static void
550 damageComposite (CARD8 op,
551 PicturePtr pSrc,
552 PicturePtr pMask,
553 PicturePtr pDst,
554 INT16 xSrc,
555 INT16 ySrc,
556 INT16 xMask,
557 INT16 yMask,
558 INT16 xDst,
559 INT16 yDst,
560 CARD16 width,
561 CARD16 height)
563 ScreenPtr pScreen = pDst->pDrawable->pScreen;
564 PictureScreenPtr ps = GetPictureScreen(pScreen);
565 damageScrPriv(pScreen);
567 if (checkPictureDamage (pDst))
569 BoxRec box;
571 box.x1 = xDst + pDst->pDrawable->x;
572 box.y1 = yDst + pDst->pDrawable->y;
573 box.x2 = box.x1 + width;
574 box.y2 = box.y1 + height;
575 TRIM_PICTURE_BOX(box, pDst);
576 if (BOX_NOT_EMPTY(box))
577 damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
579 unwrap (pScrPriv, ps, Composite);
580 (*ps->Composite) (op,
581 pSrc,
582 pMask,
583 pDst,
584 xSrc,
585 ySrc,
586 xMask,
587 yMask,
588 xDst,
589 yDst,
590 width,
591 height);
592 damageReportPostOp (pDst->pDrawable);
593 wrap (pScrPriv, ps, Composite, damageComposite);
596 static void
597 damageGlyphs (CARD8 op,
598 PicturePtr pSrc,
599 PicturePtr pDst,
600 PictFormatPtr maskFormat,
601 INT16 xSrc,
602 INT16 ySrc,
603 int nlist,
604 GlyphListPtr list,
605 GlyphPtr *glyphs)
607 ScreenPtr pScreen = pDst->pDrawable->pScreen;
608 PictureScreenPtr ps = GetPictureScreen(pScreen);
609 damageScrPriv(pScreen);
611 if (checkPictureDamage (pDst))
613 int nlistTmp = nlist;
614 GlyphListPtr listTmp = list;
615 GlyphPtr *glyphsTmp = glyphs;
616 int x, y;
617 int n;
618 GlyphPtr glyph;
619 BoxRec box;
620 int x1, y1, x2, y2;
622 box.x1 = 32767;
623 box.y1 = 32767;
624 box.x2 = -32767;
625 box.y2 = -32767;
626 x = pDst->pDrawable->x;
627 y = pDst->pDrawable->y;
628 while (nlistTmp--)
630 x += listTmp->xOff;
631 y += listTmp->yOff;
632 n = listTmp->len;
633 while (n--)
635 glyph = *glyphsTmp++;
636 x1 = x - glyph->info.x;
637 y1 = y - glyph->info.y;
638 x2 = x1 + glyph->info.width;
639 y2 = y1 + glyph->info.height;
640 if (x1 < box.x1)
641 box.x1 = x1;
642 if (y1 < box.y1)
643 box.y1 = y1;
644 if (x2 > box.x2)
645 box.x2 = x2;
646 if (y2 > box.y2)
647 box.y2 = y2;
648 x += glyph->info.xOff;
649 y += glyph->info.yOff;
651 listTmp++;
653 TRIM_PICTURE_BOX (box, pDst);
654 if (BOX_NOT_EMPTY(box))
655 damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
657 unwrap (pScrPriv, ps, Glyphs);
658 (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
659 damageReportPostOp (pDst->pDrawable);
660 wrap (pScrPriv, ps, Glyphs, damageGlyphs);
662 #endif
664 /**********************************************************/
667 static void
668 damageFillSpans(DrawablePtr pDrawable,
669 GC *pGC,
670 int npt,
671 DDXPointPtr ppt,
672 int *pwidth,
673 int fSorted)
675 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
677 if (npt && checkGCDamage (pDrawable, pGC))
679 int nptTmp = npt;
680 DDXPointPtr pptTmp = ppt;
681 int *pwidthTmp = pwidth;
682 BoxRec box;
684 box.x1 = pptTmp->x;
685 box.x2 = box.x1 + *pwidthTmp;
686 box.y2 = box.y1 = pptTmp->y;
688 while(--nptTmp)
690 pptTmp++;
691 pwidthTmp++;
692 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
693 if(box.x2 < (pptTmp->x + *pwidthTmp))
694 box.x2 = pptTmp->x + *pwidthTmp;
695 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
696 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
699 box.y2++;
701 if(!pGC->miTranslate) {
702 TRANSLATE_BOX(box, pDrawable);
704 TRIM_BOX(box, pGC);
706 if(BOX_NOT_EMPTY(box))
707 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
710 (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted);
712 damageReportPostOp (pDrawable);
713 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
716 static void
717 damageSetSpans(DrawablePtr pDrawable,
718 GCPtr pGC,
719 char *pcharsrc,
720 DDXPointPtr ppt,
721 int *pwidth,
722 int npt,
723 int fSorted)
725 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
727 if (npt && checkGCDamage (pDrawable, pGC))
729 DDXPointPtr pptTmp = ppt;
730 int *pwidthTmp = pwidth;
731 int nptTmp = npt;
732 BoxRec box;
734 box.x1 = pptTmp->x;
735 box.x2 = box.x1 + *pwidthTmp;
736 box.y2 = box.y1 = pptTmp->y;
738 while(--nptTmp)
740 pptTmp++;
741 pwidthTmp++;
742 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
743 if(box.x2 < (pptTmp->x + *pwidthTmp))
744 box.x2 = pptTmp->x + *pwidthTmp;
745 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
746 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
749 box.y2++;
751 if(!pGC->miTranslate) {
752 TRANSLATE_BOX(box, pDrawable);
754 TRIM_BOX(box, pGC);
756 if(BOX_NOT_EMPTY(box))
757 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
759 (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
760 damageReportPostOp (pDrawable);
761 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
764 static void
765 damagePutImage(DrawablePtr pDrawable,
766 GCPtr pGC,
767 int depth,
768 int x,
769 int y,
770 int w,
771 int h,
772 int leftPad,
773 int format,
774 char *pImage)
776 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
777 if (checkGCDamage (pDrawable, pGC))
779 BoxRec box;
781 box.x1 = x + pDrawable->x;
782 box.x2 = box.x1 + w;
783 box.y1 = y + pDrawable->y;
784 box.y2 = box.y1 + h;
786 TRIM_BOX(box, pGC);
787 if(BOX_NOT_EMPTY(box))
788 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
790 (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
791 leftPad, format, pImage);
792 damageReportPostOp (pDrawable);
793 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
796 static RegionPtr
797 damageCopyArea(DrawablePtr pSrc,
798 DrawablePtr pDst,
799 GC *pGC,
800 int srcx,
801 int srcy,
802 int width,
803 int height,
804 int dstx,
805 int dsty)
807 RegionPtr ret;
808 DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
810 /* The driver will only call SourceValidate() when pSrc != pDst,
811 * but the software sprite (misprite.c) always need to know when a
812 * drawable is copied so it can remove the sprite. See #1030. */
813 if ((pSrc == pDst) && pSrc->pScreen->SourceValidate &&
814 pSrc->type == DRAWABLE_WINDOW &&
815 ((WindowPtr)pSrc)->viewable)
817 (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
820 if (checkGCDamage (pDst, pGC))
822 BoxRec box;
824 box.x1 = dstx + pDst->x;
825 box.x2 = box.x1 + width;
826 box.y1 = dsty + pDst->y;
827 box.y2 = box.y1 + height;
829 TRIM_BOX(box, pGC);
830 if(BOX_NOT_EMPTY(box))
831 damageDamageBox (pDst, &box, pGC->subWindowMode);
834 ret = (*pGC->ops->CopyArea)(pSrc, pDst,
835 pGC, srcx, srcy, width, height, dstx, dsty);
836 damageReportPostOp (pDst);
837 DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
838 return ret;
841 static RegionPtr
842 damageCopyPlane(DrawablePtr pSrc,
843 DrawablePtr pDst,
844 GCPtr pGC,
845 int srcx,
846 int srcy,
847 int width,
848 int height,
849 int dstx,
850 int dsty,
851 unsigned long bitPlane)
853 RegionPtr ret;
854 DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
856 /* The driver will only call SourceValidate() when pSrc != pDst,
857 * but the software sprite (misprite.c) always need to know when a
858 * drawable is copied so it can remove the sprite. See #1030. */
859 if ((pSrc == pDst) && pSrc->pScreen->SourceValidate &&
860 pSrc->type == DRAWABLE_WINDOW &&
861 ((WindowPtr)pSrc)->viewable)
863 (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
866 if (checkGCDamage (pDst, pGC))
868 BoxRec box;
870 box.x1 = dstx + pDst->x;
871 box.x2 = box.x1 + width;
872 box.y1 = dsty + pDst->y;
873 box.y2 = box.y1 + height;
875 TRIM_BOX(box, pGC);
876 if(BOX_NOT_EMPTY(box))
877 damageDamageBox (pDst, &box, pGC->subWindowMode);
880 ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
881 pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
882 damageReportPostOp (pDst);
883 DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
884 return ret;
887 static void
888 damagePolyPoint(DrawablePtr pDrawable,
889 GCPtr pGC,
890 int mode,
891 int npt,
892 xPoint *ppt)
894 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
896 if (npt && checkGCDamage (pDrawable, pGC))
898 BoxRec box;
899 int nptTmp = npt;
900 xPoint *pptTmp = ppt;
902 box.x2 = box.x1 = pptTmp->x;
903 box.y2 = box.y1 = pptTmp->y;
905 /* this could be slow if the points were spread out */
907 while(--nptTmp)
909 pptTmp++;
910 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
911 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
912 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
913 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
916 box.x2++;
917 box.y2++;
919 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
920 if(BOX_NOT_EMPTY(box))
921 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
923 (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt);
924 damageReportPostOp (pDrawable);
925 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
928 static void
929 damagePolylines(DrawablePtr pDrawable,
930 GCPtr pGC,
931 int mode,
932 int npt,
933 DDXPointPtr ppt)
935 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
937 if (npt && checkGCDamage (pDrawable, pGC))
939 int nptTmp = npt;
940 DDXPointPtr pptTmp = ppt;
941 BoxRec box;
942 int extra = pGC->lineWidth >> 1;
944 box.x2 = box.x1 = pptTmp->x;
945 box.y2 = box.y1 = pptTmp->y;
947 if(nptTmp > 1)
949 if(pGC->joinStyle == JoinMiter)
950 extra = 6 * pGC->lineWidth;
951 else if(pGC->capStyle == CapProjecting)
952 extra = pGC->lineWidth;
955 if(mode == CoordModePrevious)
957 int x = box.x1;
958 int y = box.y1;
959 while(--nptTmp)
961 pptTmp++;
962 x += pptTmp->x;
963 y += pptTmp->y;
964 if(box.x1 > x) box.x1 = x;
965 else if(box.x2 < x) box.x2 = x;
966 if(box.y1 > y) box.y1 = y;
967 else if(box.y2 < y) box.y2 = y;
970 else
972 while(--nptTmp)
974 pptTmp++;
975 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
976 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
977 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
978 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
982 box.x2++;
983 box.y2++;
985 if(extra)
987 box.x1 -= extra;
988 box.x2 += extra;
989 box.y1 -= extra;
990 box.y2 += extra;
993 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
994 if(BOX_NOT_EMPTY(box))
995 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
997 (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt);
998 damageReportPostOp (pDrawable);
999 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1002 static void
1003 damagePolySegment(DrawablePtr pDrawable,
1004 GCPtr pGC,
1005 int nSeg,
1006 xSegment *pSeg)
1008 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1010 if (nSeg && checkGCDamage (pDrawable, pGC))
1012 BoxRec box;
1013 int extra = pGC->lineWidth;
1014 int nsegTmp = nSeg;
1015 xSegment *pSegTmp = pSeg;
1017 if(pGC->capStyle != CapProjecting)
1018 extra >>= 1;
1020 if(pSegTmp->x2 > pSegTmp->x1) {
1021 box.x1 = pSegTmp->x1;
1022 box.x2 = pSegTmp->x2;
1023 } else {
1024 box.x2 = pSegTmp->x1;
1025 box.x1 = pSegTmp->x2;
1028 if(pSegTmp->y2 > pSegTmp->y1) {
1029 box.y1 = pSegTmp->y1;
1030 box.y2 = pSegTmp->y2;
1031 } else {
1032 box.y2 = pSegTmp->y1;
1033 box.y1 = pSegTmp->y2;
1036 while(--nsegTmp)
1038 pSegTmp++;
1039 if(pSegTmp->x2 > pSegTmp->x1)
1041 if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1;
1042 if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2;
1044 else
1046 if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2;
1047 if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1;
1049 if(pSegTmp->y2 > pSegTmp->y1)
1051 if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1;
1052 if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2;
1054 else
1056 if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2;
1057 if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1;
1061 box.x2++;
1062 box.y2++;
1064 if(extra)
1066 box.x1 -= extra;
1067 box.x2 += extra;
1068 box.y1 -= extra;
1069 box.y2 += extra;
1072 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1073 if(BOX_NOT_EMPTY(box))
1074 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1076 (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg);
1077 damageReportPostOp (pDrawable);
1078 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1081 static void
1082 damagePolyRectangle(DrawablePtr pDrawable,
1083 GCPtr pGC,
1084 int nRects,
1085 xRectangle *pRects)
1087 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1089 if (nRects && checkGCDamage (pDrawable, pGC))
1091 BoxRec box;
1092 int offset1, offset2, offset3;
1093 int nRectsTmp = nRects;
1094 xRectangle *pRectsTmp = pRects;
1096 offset2 = pGC->lineWidth;
1097 if(!offset2) offset2 = 1;
1098 offset1 = offset2 >> 1;
1099 offset3 = offset2 - offset1;
1101 while(nRectsTmp--)
1103 box.x1 = pRectsTmp->x - offset1;
1104 box.y1 = pRectsTmp->y - offset1;
1105 box.x2 = box.x1 + pRectsTmp->width + offset2;
1106 box.y2 = box.y1 + offset2;
1107 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1108 if(BOX_NOT_EMPTY(box))
1109 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1111 box.x1 = pRectsTmp->x - offset1;
1112 box.y1 = pRectsTmp->y + offset3;
1113 box.x2 = box.x1 + offset2;
1114 box.y2 = box.y1 + pRectsTmp->height - offset2;
1115 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1116 if(BOX_NOT_EMPTY(box))
1117 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1119 box.x1 = pRectsTmp->x + pRectsTmp->width - offset1;
1120 box.y1 = pRectsTmp->y + offset3;
1121 box.x2 = box.x1 + offset2;
1122 box.y2 = box.y1 + pRectsTmp->height - offset2;
1123 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1124 if(BOX_NOT_EMPTY(box))
1125 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1127 box.x1 = pRectsTmp->x - offset1;
1128 box.y1 = pRectsTmp->y + pRectsTmp->height - offset1;
1129 box.x2 = box.x1 + pRectsTmp->width + offset2;
1130 box.y2 = box.y1 + offset2;
1131 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1132 if(BOX_NOT_EMPTY(box))
1133 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1135 pRectsTmp++;
1138 (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects);
1139 damageReportPostOp (pDrawable);
1140 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1143 static void
1144 damagePolyArc(DrawablePtr pDrawable,
1145 GCPtr pGC,
1146 int nArcs,
1147 xArc *pArcs)
1149 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1151 if (nArcs && checkGCDamage (pDrawable, pGC))
1153 int extra = pGC->lineWidth >> 1;
1154 BoxRec box;
1155 int nArcsTmp = nArcs;
1156 xArc *pArcsTmp = pArcs;
1158 box.x1 = pArcsTmp->x;
1159 box.x2 = box.x1 + pArcsTmp->width;
1160 box.y1 = pArcsTmp->y;
1161 box.y2 = box.y1 + pArcsTmp->height;
1163 while(--nArcsTmp)
1165 pArcsTmp++;
1166 if(box.x1 > pArcsTmp->x)
1167 box.x1 = pArcsTmp->x;
1168 if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
1169 box.x2 = pArcsTmp->x + pArcsTmp->width;
1170 if(box.y1 > pArcsTmp->y)
1171 box.y1 = pArcsTmp->y;
1172 if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
1173 box.y2 = pArcsTmp->y + pArcsTmp->height;
1176 if(extra)
1178 box.x1 -= extra;
1179 box.x2 += extra;
1180 box.y1 -= extra;
1181 box.y2 += extra;
1184 box.x2++;
1185 box.y2++;
1187 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1188 if(BOX_NOT_EMPTY(box))
1189 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1191 (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs);
1192 damageReportPostOp (pDrawable);
1193 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1196 static void
1197 damageFillPolygon(DrawablePtr pDrawable,
1198 GCPtr pGC,
1199 int shape,
1200 int mode,
1201 int npt,
1202 DDXPointPtr ppt)
1204 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1206 if (npt > 2 && checkGCDamage (pDrawable, pGC))
1208 DDXPointPtr pptTmp = ppt;
1209 int nptTmp = npt;
1210 BoxRec box;
1212 box.x2 = box.x1 = pptTmp->x;
1213 box.y2 = box.y1 = pptTmp->y;
1215 if(mode != CoordModeOrigin)
1217 int x = box.x1;
1218 int y = box.y1;
1219 while(--nptTmp)
1221 pptTmp++;
1222 x += pptTmp->x;
1223 y += pptTmp->y;
1224 if(box.x1 > x) box.x1 = x;
1225 else if(box.x2 < x) box.x2 = x;
1226 if(box.y1 > y) box.y1 = y;
1227 else if(box.y2 < y) box.y2 = y;
1230 else
1232 while(--nptTmp)
1234 pptTmp++;
1235 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
1236 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
1237 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
1238 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
1242 box.x2++;
1243 box.y2++;
1245 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1246 if(BOX_NOT_EMPTY(box))
1247 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1250 (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt);
1251 damageReportPostOp (pDrawable);
1252 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1256 static void
1257 damagePolyFillRect(DrawablePtr pDrawable,
1258 GCPtr pGC,
1259 int nRects,
1260 xRectangle *pRects)
1262 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1263 if (nRects && checkGCDamage (pDrawable, pGC))
1265 BoxRec box;
1266 xRectangle *pRectsTmp = pRects;
1267 int nRectsTmp = nRects;
1269 box.x1 = pRectsTmp->x;
1270 box.x2 = box.x1 + pRectsTmp->width;
1271 box.y1 = pRectsTmp->y;
1272 box.y2 = box.y1 + pRectsTmp->height;
1274 while(--nRectsTmp)
1276 pRectsTmp++;
1277 if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x;
1278 if(box.x2 < (pRectsTmp->x + pRectsTmp->width))
1279 box.x2 = pRectsTmp->x + pRectsTmp->width;
1280 if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y;
1281 if(box.y2 < (pRectsTmp->y + pRectsTmp->height))
1282 box.y2 = pRectsTmp->y + pRectsTmp->height;
1285 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1286 if(BOX_NOT_EMPTY(box))
1287 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1289 (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects);
1290 damageReportPostOp (pDrawable);
1291 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1295 static void
1296 damagePolyFillArc(DrawablePtr pDrawable,
1297 GCPtr pGC,
1298 int nArcs,
1299 xArc *pArcs)
1301 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1303 if (nArcs && checkGCDamage (pDrawable, pGC))
1305 BoxRec box;
1306 int nArcsTmp = nArcs;
1307 xArc *pArcsTmp = pArcs;
1309 box.x1 = pArcsTmp->x;
1310 box.x2 = box.x1 + pArcsTmp->width;
1311 box.y1 = pArcsTmp->y;
1312 box.y2 = box.y1 + pArcsTmp->height;
1314 while(--nArcsTmp)
1316 pArcsTmp++;
1317 if(box.x1 > pArcsTmp->x)
1318 box.x1 = pArcsTmp->x;
1319 if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
1320 box.x2 = pArcsTmp->x + pArcsTmp->width;
1321 if(box.y1 > pArcsTmp->y)
1322 box.y1 = pArcsTmp->y;
1323 if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
1324 box.y2 = pArcsTmp->y + pArcsTmp->height;
1327 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1328 if(BOX_NOT_EMPTY(box))
1329 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1331 (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs);
1332 damageReportPostOp (pDrawable);
1333 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1337 * general Poly/Image text function. Extract glyph information,
1338 * compute bounding box and remove cursor if it is overlapped.
1341 static void
1342 damageDamageChars (DrawablePtr pDrawable,
1343 FontPtr font,
1344 int x,
1345 int y,
1346 unsigned int n,
1347 CharInfoPtr *charinfo,
1348 Bool imageblt,
1349 int subWindowMode)
1351 ExtentInfoRec extents;
1352 BoxRec box;
1354 QueryGlyphExtents(font, charinfo, n, &extents);
1355 if (imageblt)
1357 if (extents.overallWidth > extents.overallRight)
1358 extents.overallRight = extents.overallWidth;
1359 if (extents.overallWidth < extents.overallLeft)
1360 extents.overallLeft = extents.overallWidth;
1361 if (extents.overallLeft > 0)
1362 extents.overallLeft = 0;
1363 if (extents.fontAscent > extents.overallAscent)
1364 extents.overallAscent = extents.fontAscent;
1365 if (extents.fontDescent > extents.overallDescent)
1366 extents.overallDescent = extents.fontDescent;
1368 box.x1 = x + extents.overallLeft;
1369 box.y1 = y - extents.overallAscent;
1370 box.x2 = x + extents.overallRight;
1371 box.y2 = y + extents.overallDescent;
1372 damageDamageBox (pDrawable, &box, subWindowMode);
1376 * values for textType:
1378 #define TT_POLY8 0
1379 #define TT_IMAGE8 1
1380 #define TT_POLY16 2
1381 #define TT_IMAGE16 3
1383 static int
1384 damageText (DrawablePtr pDrawable,
1385 GCPtr pGC,
1386 int x,
1387 int y,
1388 unsigned long count,
1389 char *chars,
1390 FontEncoding fontEncoding,
1391 Bool textType)
1393 CharInfoPtr *charinfo;
1394 CharInfoPtr *info;
1395 unsigned long i;
1396 unsigned int n;
1397 int w;
1398 Bool imageblt;
1400 imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
1402 charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
1403 if (!charinfo)
1404 return x;
1406 GetGlyphs(pGC->font, count, (unsigned char *)chars,
1407 fontEncoding, &i, charinfo);
1408 n = (unsigned int)i;
1409 w = 0;
1410 if (!imageblt)
1411 for (info = charinfo; i--; info++)
1412 w += (*info)->metrics.characterWidth;
1414 if (n != 0) {
1415 damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n,
1416 charinfo, imageblt, pGC->subWindowMode);
1417 if (imageblt)
1418 (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
1419 FONTGLYPHS(pGC->font));
1420 else
1421 (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
1422 FONTGLYPHS(pGC->font));
1424 DEALLOCATE_LOCAL(charinfo);
1425 return x + w;
1428 static int
1429 damagePolyText8(DrawablePtr pDrawable,
1430 GCPtr pGC,
1431 int x,
1432 int y,
1433 int count,
1434 char *chars)
1436 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1438 if (checkGCDamage (pDrawable, pGC))
1439 x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
1440 Linear8Bit, TT_POLY8);
1441 else
1442 x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
1443 damageReportPostOp (pDrawable);
1444 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1445 return x;
1448 static int
1449 damagePolyText16(DrawablePtr pDrawable,
1450 GCPtr pGC,
1451 int x,
1452 int y,
1453 int count,
1454 unsigned short *chars)
1456 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1458 if (checkGCDamage (pDrawable, pGC))
1459 x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
1460 FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
1461 TT_POLY16);
1462 else
1463 x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
1464 damageReportPostOp (pDrawable);
1465 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1466 return x;
1469 static void
1470 damageImageText8(DrawablePtr pDrawable,
1471 GCPtr pGC,
1472 int x,
1473 int y,
1474 int count,
1475 char *chars)
1477 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1479 if (checkGCDamage (pDrawable, pGC))
1480 damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
1481 Linear8Bit, TT_IMAGE8);
1482 else
1483 (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
1484 damageReportPostOp (pDrawable);
1485 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1488 static void
1489 damageImageText16(DrawablePtr pDrawable,
1490 GCPtr pGC,
1491 int x,
1492 int y,
1493 int count,
1494 unsigned short *chars)
1496 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1498 if (checkGCDamage (pDrawable, pGC))
1499 damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
1500 FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
1501 TT_IMAGE16);
1502 else
1503 (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
1504 damageReportPostOp (pDrawable);
1505 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1509 static void
1510 damageImageGlyphBlt(DrawablePtr pDrawable,
1511 GCPtr pGC,
1512 int x,
1513 int y,
1514 unsigned int nglyph,
1515 CharInfoPtr *ppci,
1516 pointer pglyphBase)
1518 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1519 damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
1520 nglyph, ppci, TRUE, pGC->subWindowMode);
1521 (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph,
1522 ppci, pglyphBase);
1523 damageReportPostOp (pDrawable);
1524 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1527 static void
1528 damagePolyGlyphBlt(DrawablePtr pDrawable,
1529 GCPtr pGC,
1530 int x,
1531 int y,
1532 unsigned int nglyph,
1533 CharInfoPtr *ppci,
1534 pointer pglyphBase)
1536 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1537 damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
1538 nglyph, ppci, FALSE, pGC->subWindowMode);
1539 (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
1540 ppci, pglyphBase);
1541 damageReportPostOp (pDrawable);
1542 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1545 static void
1546 damagePushPixels(GCPtr pGC,
1547 PixmapPtr pBitMap,
1548 DrawablePtr pDrawable,
1549 int dx,
1550 int dy,
1551 int xOrg,
1552 int yOrg)
1554 DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1555 if(checkGCDamage (pDrawable, pGC))
1557 BoxRec box;
1559 box.x1 = xOrg;
1560 box.y1 = yOrg;
1562 if(!pGC->miTranslate) {
1563 box.x1 += pDrawable->x;
1564 box.y1 += pDrawable->y;
1567 box.x2 = box.x1 + dx;
1568 box.y2 = box.y1 + dy;
1570 TRIM_BOX(box, pGC);
1571 if(BOX_NOT_EMPTY(box))
1572 damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1574 (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
1575 damageReportPostOp (pDrawable);
1576 DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1579 static void
1580 damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage)
1582 while (*pPrev)
1584 if (*pPrev == pDamage)
1586 *pPrev = pDamage->pNext;
1587 return;
1589 pPrev = &(*pPrev)->pNext;
1591 #if DAMAGE_VALIDATE_ENABLE
1592 ErrorF ("Damage not on list\n");
1593 abort ();
1594 #endif
1597 static void
1598 damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage)
1600 #if DAMAGE_VALIDATE_ENABLE
1601 DamagePtr pOld;
1603 for (pOld = *pPrev; pOld; pOld = pOld->pNext)
1604 if (pOld == pDamage) {
1605 ErrorF ("Damage already on list\n");
1606 abort ();
1608 #endif
1609 pDamage->pNext = *pPrev;
1610 *pPrev = pDamage;
1613 static Bool
1614 damageDestroyPixmap (PixmapPtr pPixmap)
1616 ScreenPtr pScreen = pPixmap->drawable.pScreen;
1617 damageScrPriv(pScreen);
1619 if (pPixmap->refcnt == 1)
1621 DamagePtr *pPrev = getPixmapDamageRef (pPixmap);
1622 DamagePtr pDamage;
1624 while ((pDamage = *pPrev))
1626 damageRemoveDamage (pPrev, pDamage);
1627 if (!pDamage->isWindow)
1628 DamageDestroy (pDamage);
1631 unwrap (pScrPriv, pScreen, DestroyPixmap);
1632 (*pScreen->DestroyPixmap) (pPixmap);
1633 wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
1634 return TRUE;
1637 static void
1638 damagePaintWindow(WindowPtr pWindow,
1639 RegionPtr prgn,
1640 int what)
1642 ScreenPtr pScreen = pWindow->drawable.pScreen;
1643 damageScrPriv(pScreen);
1646 * Painting background none doesn't actually *do* anything, so
1647 * no damage is recorded
1649 if ((what != PW_BACKGROUND || pWindow->backgroundState != None) &&
1650 getWindowDamage (pWindow))
1651 damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1);
1652 if(what == PW_BACKGROUND) {
1653 unwrap (pScrPriv, pScreen, PaintWindowBackground);
1654 (*pScreen->PaintWindowBackground) (pWindow, prgn, what);
1655 damageReportPostOp (&pWindow->drawable);
1656 wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow);
1657 } else {
1658 unwrap (pScrPriv, pScreen, PaintWindowBorder);
1659 (*pScreen->PaintWindowBorder) (pWindow, prgn, what);
1660 damageReportPostOp (&pWindow->drawable);
1661 wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow);
1666 static void
1667 damageCopyWindow(WindowPtr pWindow,
1668 DDXPointRec ptOldOrg,
1669 RegionPtr prgnSrc)
1671 ScreenPtr pScreen = pWindow->drawable.pScreen;
1672 damageScrPriv(pScreen);
1674 if (getWindowDamage (pWindow))
1676 int dx = pWindow->drawable.x - ptOldOrg.x;
1677 int dy = pWindow->drawable.y - ptOldOrg.y;
1680 * The region comes in source relative, but the damage occurs
1681 * at the destination location. Translate back and forth.
1683 REGION_TRANSLATE (pScreen, prgnSrc, dx, dy);
1684 damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE, -1);
1685 REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
1687 unwrap (pScrPriv, pScreen, CopyWindow);
1688 (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
1689 damageReportPostOp (&pWindow->drawable);
1690 wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
1693 static GCOps damageGCOps = {
1694 damageFillSpans, damageSetSpans,
1695 damagePutImage, damageCopyArea,
1696 damageCopyPlane, damagePolyPoint,
1697 damagePolylines, damagePolySegment,
1698 damagePolyRectangle, damagePolyArc,
1699 damageFillPolygon, damagePolyFillRect,
1700 damagePolyFillArc, damagePolyText8,
1701 damagePolyText16, damageImageText8,
1702 damageImageText16, damageImageGlyphBlt,
1703 damagePolyGlyphBlt, damagePushPixels,
1704 {NULL} /* devPrivate */
1707 static void
1708 damageRestoreAreas (PixmapPtr pPixmap,
1709 RegionPtr prgn,
1710 int xorg,
1711 int yorg,
1712 WindowPtr pWindow)
1714 ScreenPtr pScreen = pWindow->drawable.pScreen;
1715 damageScrPriv(pScreen);
1717 damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1);
1718 unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
1719 (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn,
1720 xorg, yorg, pWindow);
1721 damageReportPostOp (&pWindow->drawable);
1722 wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
1723 damageRestoreAreas);
1726 static void
1727 damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
1729 DamagePtr pDamage;
1730 ScreenPtr pScreen = pWindow->drawable.pScreen;
1731 damageScrPriv(pScreen);
1733 if ((pDamage = damageGetWinPriv(pWindow)))
1735 PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow);
1736 DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap);
1738 while (pDamage)
1740 damageRemoveDamage (pPrev, pDamage);
1741 pDamage = pDamage->pNextWin;
1744 unwrap (pScrPriv, pScreen, SetWindowPixmap);
1745 (*pScreen->SetWindowPixmap) (pWindow, pPixmap);
1746 wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
1747 if ((pDamage = damageGetWinPriv(pWindow)))
1749 DamagePtr *pPrev = getPixmapDamageRef(pPixmap);
1751 while (pDamage)
1753 damageInsertDamage (pPrev, pDamage);
1754 pDamage = pDamage->pNextWin;
1759 static Bool
1760 damageDestroyWindow (WindowPtr pWindow)
1762 DamagePtr pDamage;
1763 ScreenPtr pScreen = pWindow->drawable.pScreen;
1764 Bool ret;
1765 damageScrPriv(pScreen);
1767 while ((pDamage = damageGetWinPriv(pWindow)))
1769 DamageUnregister (&pWindow->drawable, pDamage);
1770 DamageDestroy (pDamage);
1772 unwrap (pScrPriv, pScreen, DestroyWindow);
1773 ret = (*pScreen->DestroyWindow) (pWindow);
1774 wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
1775 return ret;
1778 static Bool
1779 damageCloseScreen (int i, ScreenPtr pScreen)
1781 damageScrPriv(pScreen);
1783 unwrap (pScrPriv, pScreen, DestroyPixmap);
1784 unwrap (pScrPriv, pScreen, CreateGC);
1785 unwrap (pScrPriv, pScreen, PaintWindowBackground);
1786 unwrap (pScrPriv, pScreen, PaintWindowBorder);
1787 unwrap (pScrPriv, pScreen, CopyWindow);
1788 unwrap (pScrPriv, pScreen, CloseScreen);
1789 unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
1790 xfree (pScrPriv);
1791 return (*pScreen->CloseScreen) (i, pScreen);
1794 Bool
1795 DamageSetup (ScreenPtr pScreen)
1797 DamageScrPrivPtr pScrPriv;
1798 #ifdef RENDER
1799 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
1800 #endif
1802 if (damageGeneration != serverGeneration)
1804 damageScrPrivateIndex = AllocateScreenPrivateIndex ();
1805 if (damageScrPrivateIndex == -1)
1806 return FALSE;
1807 damageGCPrivateIndex = AllocateGCPrivateIndex ();
1808 if (damageGCPrivateIndex == -1)
1809 return FALSE;
1810 damagePixPrivateIndex = AllocatePixmapPrivateIndex ();
1811 if (damagePixPrivateIndex == -1)
1812 return FALSE;
1813 damageWinPrivateIndex = AllocateWindowPrivateIndex ();
1814 if (damageWinPrivateIndex == -1)
1815 return FALSE;
1816 damageGeneration = serverGeneration;
1818 if (pScreen->devPrivates[damageScrPrivateIndex].ptr)
1819 return TRUE;
1821 if (!AllocateGCPrivate (pScreen, damageGCPrivateIndex, sizeof (DamageGCPrivRec)))
1822 return FALSE;
1823 if (!AllocatePixmapPrivate (pScreen, damagePixPrivateIndex, 0))
1824 return FALSE;
1825 if (!AllocateWindowPrivate (pScreen, damageWinPrivateIndex, 0))
1826 return FALSE;
1828 pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec));
1829 if (!pScrPriv)
1830 return FALSE;
1832 pScrPriv->internalLevel = 0;
1833 pScrPriv->pScreenDamage = 0;
1835 wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
1836 wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
1837 wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow);
1838 wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow);
1839 wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
1840 wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
1841 wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
1842 wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen);
1843 wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
1844 damageRestoreAreas);
1845 #ifdef RENDER
1846 if (ps) {
1847 wrap (pScrPriv, ps, Glyphs, damageGlyphs);
1848 wrap (pScrPriv, ps, Composite, damageComposite);
1850 #endif
1852 pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv;
1853 return TRUE;
1856 DamagePtr
1857 DamageCreate (DamageReportFunc damageReport,
1858 DamageDestroyFunc damageDestroy,
1859 DamageReportLevel damageLevel,
1860 Bool isInternal,
1861 ScreenPtr pScreen,
1862 void *closure)
1864 DamagePtr pDamage;
1866 pDamage = xalloc (sizeof (DamageRec));
1867 if (!pDamage)
1868 return 0;
1869 pDamage->pNext = 0;
1870 pDamage->pNextWin = 0;
1871 REGION_NULL(pScreen, &pDamage->damage);
1872 REGION_NULL(pScreen, &pDamage->pendingDamage);
1874 pDamage->damageLevel = damageLevel;
1875 pDamage->isInternal = isInternal;
1876 pDamage->closure = closure;
1877 pDamage->isWindow = FALSE;
1878 pDamage->pDrawable = 0;
1879 pDamage->reportAfter = FALSE;
1881 pDamage->damageReport = damageReport;
1882 pDamage->damageDestroy = damageDestroy;
1883 return pDamage;
1886 void
1887 DamageRegister (DrawablePtr pDrawable,
1888 DamagePtr pDamage)
1890 if (pDrawable->type == DRAWABLE_WINDOW)
1892 WindowPtr pWindow = (WindowPtr) pDrawable;
1893 winDamageRef(pWindow);
1895 #if DAMAGE_VALIDATE_ENABLE
1896 DamagePtr pOld;
1898 for (pOld = *pPrev; pOld; pOld = pOld->pNextWin)
1899 if (pOld == pDamage) {
1900 ErrorF ("Damage already on window list\n");
1901 abort ();
1903 #endif
1904 pDamage->pNextWin = *pPrev;
1905 *pPrev = pDamage;
1906 pDamage->isWindow = TRUE;
1908 else
1909 pDamage->isWindow = FALSE;
1910 pDamage->pDrawable = pDrawable;
1911 damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage);
1914 void
1915 DamageDrawInternal (ScreenPtr pScreen, Bool enable)
1917 damageScrPriv (pScreen);
1919 pScrPriv->internalLevel += enable ? 1 : -1;
1922 void
1923 DamageUnregister (DrawablePtr pDrawable,
1924 DamagePtr pDamage)
1926 if (pDrawable->type == DRAWABLE_WINDOW)
1928 WindowPtr pWindow = (WindowPtr) pDrawable;
1929 winDamageRef (pWindow);
1930 #if DAMAGE_VALIDATE_ENABLE
1931 int found = 0;
1932 #endif
1934 while (*pPrev)
1936 if (*pPrev == pDamage)
1938 *pPrev = pDamage->pNextWin;
1939 #if DAMAGE_VALIDATE_ENABLE
1940 found = 1;
1941 #endif
1942 break;
1944 pPrev = &(*pPrev)->pNextWin;
1946 #if DAMAGE_VALIDATE_ENABLE
1947 if (!found) {
1948 ErrorF ("Damage not on window list\n");
1949 abort ();
1951 #endif
1953 pDamage->pDrawable = 0;
1954 damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage);
1957 void
1958 DamageDestroy (DamagePtr pDamage)
1960 if (pDamage->damageDestroy)
1961 (*pDamage->damageDestroy) (pDamage, pDamage->closure);
1962 REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage);
1963 REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->pendingDamage);
1964 xfree (pDamage);
1967 Bool
1968 DamageSubtract (DamagePtr pDamage,
1969 const RegionPtr pRegion)
1971 RegionPtr pClip;
1972 RegionRec pixmapClip;
1973 DrawablePtr pDrawable = pDamage->pDrawable;
1975 REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion);
1976 if (pDrawable)
1978 if (pDrawable->type == DRAWABLE_WINDOW)
1979 pClip = &((WindowPtr) pDrawable)->borderClip;
1980 else
1982 BoxRec box;
1984 box.x1 = pDrawable->x;
1985 box.y1 = pDrawable->y;
1986 box.x2 = pDrawable->x + pDrawable->width;
1987 box.y2 = pDrawable->y + pDrawable->height;
1988 REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1);
1989 pClip = &pixmapClip;
1991 REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y);
1992 REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip);
1993 REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y);
1994 if (pDrawable->type != DRAWABLE_WINDOW)
1995 REGION_UNINIT(pDrawable->pScreen, &pixmapClip);
1997 return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage);
2000 void
2001 DamageEmpty (DamagePtr pDamage)
2003 REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage);
2006 RegionPtr
2007 DamageRegion (DamagePtr pDamage)
2009 return &pDamage->damage;
2012 _X_EXPORT void
2013 DamageDamageRegion (DrawablePtr pDrawable,
2014 RegionPtr pRegion)
2016 damageDamageRegion (pDrawable, pRegion, FALSE, -1);
2018 /* Go back and report this damage for DamagePtrs with reportAfter set, since
2019 * this call isn't part of an in-progress drawing op in the call chain and
2020 * the DDX probably just wants to know about it right away.
2022 damageReportPostOp (pDrawable);
2025 void
2026 DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter)
2028 pDamage->reportAfter = reportAfter;