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