damage.c revision 05b261ec
1/*
2 * Copyright © 2003 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Keith Packard makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_DIX_CONFIG_H
24#include <dix-config.h>
25#endif
26
27#include <stdlib.h>
28
29#include    <X11/X.h>
30#include    "scrnintstr.h"
31#include    "windowstr.h"
32#include    <X11/fonts/font.h>
33#include    "dixfontstr.h"
34#include    <X11/fonts/fontstruct.h>
35#include    "mi.h"
36#include    "regionstr.h"
37#include    "globals.h"
38#include    "gcstruct.h"
39#include    "damage.h"
40#include    "damagestr.h"
41#ifdef COMPOSITE
42#include    "cw.h"
43#endif
44
45#define wrap(priv, real, mem, func) {\
46    priv->mem = real->mem; \
47    real->mem = func; \
48}
49
50#define unwrap(priv, real, mem) {\
51    real->mem = priv->mem; \
52}
53
54#define BOX_SAME(a,b) \
55    ((a)->x1 == (b)->x1 && \
56     (a)->y1 == (b)->y1 && \
57     (a)->x2 == (b)->x2 && \
58     (a)->y2 == (b)->y2)
59
60#define DAMAGE_VALIDATE_ENABLE 0
61#define DAMAGE_DEBUG_ENABLE 0
62#if DAMAGE_DEBUG_ENABLE
63#define DAMAGE_DEBUG(x)	ErrorF x
64#else
65#define DAMAGE_DEBUG(x)
66#endif
67
68#define getPixmapDamageRef(pPixmap) \
69    ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr))
70
71#define pixmapDamage(pPixmap)		damagePixPriv(pPixmap)
72
73static int damageScrPrivateIndex;
74static int damagePixPrivateIndex;
75static int damageGCPrivateIndex;
76static int damageWinPrivateIndex;
77static int damageGeneration;
78
79static DamagePtr *
80getDrawableDamageRef (DrawablePtr pDrawable)
81{
82    PixmapPtr   pPixmap;
83
84    if (pDrawable->type == DRAWABLE_WINDOW)
85    {
86	ScreenPtr   pScreen = pDrawable->pScreen;
87
88	pPixmap = 0;
89	if (pScreen->GetWindowPixmap
90#ifdef ROOTLESS_WORKAROUND
91	    && ((WindowPtr)pDrawable)->viewable
92#endif
93	    )
94	    pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable);
95
96	if (!pPixmap)
97	{
98	    damageScrPriv(pScreen);
99
100	    return &pScrPriv->pScreenDamage;
101	}
102    }
103    else
104	pPixmap = (PixmapPtr) pDrawable;
105    return getPixmapDamageRef (pPixmap);
106}
107
108#define getDrawableDamage(pDrawable)	(*getDrawableDamageRef (pDrawable))
109#define getWindowDamage(pWin)		getDrawableDamage(&(pWin)->drawable)
110
111#define drawableDamage(pDrawable)	\
112    DamagePtr	pDamage = getDrawableDamage(pDrawable)
113
114#define windowDamage(pWin)		drawableDamage(&(pWin)->drawable)
115
116#define winDamageRef(pWindow) \
117    DamagePtr	*pPrev = (DamagePtr *) \
118	    &(pWindow->devPrivates[damageWinPrivateIndex].ptr)
119
120static void
121DamageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion)
122{
123    BoxRec tmpBox;
124    RegionRec tmpRegion;
125    Bool was_empty;
126
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);
138	}
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);
148	}
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);
157	}
158	break;
159    case DamageReportNone:
160	REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage,
161		     pDamageRegion);
162	break;
163    }
164}
165
166#if DAMAGE_DEBUG_ENABLE
167static 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
171static void
172damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
173			int subWindowMode)
174#endif
175{
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
187
188    /* short circuit for empty regions */
189    if (!REGION_NOTEMPTY(pScreen, pRegion))
190	return;
191
192#ifdef COMPOSITE
193    /*
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
197     */
198    if (pDrawable->type != DRAWABLE_WINDOW)
199    {
200	screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x;
201	screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y;
202    }
203    if (screen_x || screen_y)
204        REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y);
205#endif
206
207    if (pDrawable->type == DRAWABLE_WINDOW &&
208	((WindowPtr)(pDrawable))->backingStore == NotUseful)
209    {
210	if (subWindowMode == ClipByChildren)
211	{
212	    REGION_INTERSECT(pScreen, pRegion, pRegion,
213			     &((WindowPtr)(pDrawable))->clipList);
214	}
215	else if (subWindowMode == IncludeInferiors)
216	{
217	    RegionPtr pTempRegion =
218		NotClippedByChildren((WindowPtr)(pDrawable));
219	    REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion);
220	    REGION_DESTROY(pScreen, pTempRegion);
221	}
222	/* If subWindowMode is set to an invalid value, don't perform
223	 * any drawable-based clipping. */
224    }
225
226
227    REGION_NULL (pScreen, &clippedRec);
228    for (; pDamage; pDamage = pNext)
229    {
230	pNext = pDamage->pNext;
231	/*
232	 * Check for internal damage and don't send events
233	 */
234	if (pScrPriv->internalLevel > 0 && !pDamage->isInternal)
235	{
236	    DAMAGE_DEBUG (("non internal damage, skipping at %d\n",
237			   pScrPriv->internalLevel));
238	    continue;
239	}
240	/*
241	 * Check for unrealized windows
242	 */
243	if (pDamage->pDrawable->type == DRAWABLE_WINDOW &&
244	    !((WindowPtr) (pDamage->pDrawable))->realized)
245	{
246#if 0
247	    DAMAGE_DEBUG (("damage while window unrealized\n"));
248#endif
249	    continue;
250	}
251
252	draw_x = pDamage->pDrawable->x;
253	draw_y = pDamage->pDrawable->y;
254#ifdef COMPOSITE
255	/*
256	 * Need to move everyone to screen coordinates
257	 * XXX what about off-screen pixmaps with non-zero x/y?
258	 */
259	if (pDamage->pDrawable->type != DRAWABLE_WINDOW)
260	{
261	    draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x;
262	    draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y;
263	}
264#endif
265
266	/*
267	 * Clip against border or pixmap bounds
268	 */
269
270	pDamageRegion = pRegion;
271	if (clip || pDamage->pDrawable != pDrawable)
272	{
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);
286	    }
287	    /*
288	     * Short circuit empty results
289	     */
290	    if (!REGION_NOTEMPTY(pScreen, pDamageRegion))
291		continue;
292	}
293
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));
300
301	/*
302	 * Move region to target coordinate space
303	 */
304	if (draw_x || draw_y)
305	    REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y);
306
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
310	 */
311	if (!pDamage->reportAfter) {
312	    DamageReportDamage (pDamage, pDamageRegion);
313	} else {
314	    REGION_UNION(pScreen, &pDamage->pendingDamage,
315			 &pDamage->pendingDamage, pDamageRegion);
316	}
317
318	/*
319	 * translate original region back
320	 */
321	if (pDamageRegion == pRegion && (draw_x || draw_y))
322	    REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y);
323    }
324#ifdef COMPOSITE
325    if (screen_x || screen_y)
326	REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y);
327#endif
328
329    REGION_UNINIT (pScreen, &clippedRec);
330}
331
332static void
333damageReportPostOp (DrawablePtr pDrawable)
334{
335    drawableDamage(pDrawable);
336
337    for (; pDamage != NULL; pDamage = pDamage->pNext)
338    {
339	if (pDamage->reportAfter) {
340	    DamageReportDamage (pDamage, &pDamage->pendingDamage);
341	    REGION_EMPTY (pScreen, &pDamage->pendingDamage);
342	}
343    }
344
345}
346
347#if DAMAGE_DEBUG_ENABLE
348#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
349static void
350_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where)
351#else
352static void
353damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode)
354#endif
355{
356    RegionRec	region;
357
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);
365}
366
367static void damageValidateGC(GCPtr, unsigned long, DrawablePtr);
368static void damageChangeGC(GCPtr, unsigned long);
369static void damageCopyGC(GCPtr, unsigned long, GCPtr);
370static void damageDestroyGC(GCPtr);
371static void damageChangeClip(GCPtr, int, pointer, int);
372static void damageDestroyClip(GCPtr);
373static void damageCopyClip(GCPtr, GCPtr);
374
375static GCFuncs damageGCFuncs = {
376    damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC,
377    damageChangeClip, damageDestroyClip, damageCopyClip
378};
379
380static GCOps damageGCOps;
381
382static Bool
383damageCreateGC(GCPtr pGC)
384{
385    ScreenPtr pScreen = pGC->pScreen;
386    damageScrPriv(pScreen);
387    damageGCPriv(pGC);
388    Bool ret;
389
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;
396    }
397    wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
398
399    return ret;
400}
401
402#ifdef NOTUSED
403static void
404damageWrapGC (GCPtr pGC)
405{
406    damageGCPriv(pGC);
407
408    pGCPriv->ops = NULL;
409    pGCPriv->funcs = pGC->funcs;
410    pGC->funcs = &damageGCFuncs;
411}
412
413static void
414damageUnwrapGC (GCPtr pGC)
415{
416    damageGCPriv(pGC);
417
418    pGC->funcs = pGCPriv->funcs;
419    if (pGCPriv->ops)
420	pGC->ops = pGCPriv->ops;
421}
422#endif
423
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); \
429
430#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
431    wrap(pGCPriv, pGC, funcs, oldFuncs); \
432    wrap(pGCPriv, pGC, ops, &damageGCOps)
433
434#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
435    damageGCPriv(pGC); \
436    unwrap(pGCPriv, pGC, funcs); \
437    if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
438
439#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
440    wrap(pGCPriv, pGC, funcs, &damageGCFuncs);  \
441    if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
442
443static void
444damageValidateGC(GCPtr         pGC,
445		 unsigned long changes,
446		 DrawablePtr   pDrawable)
447{
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);
452}
453
454static void
455damageDestroyGC(GCPtr pGC)
456{
457    DAMAGE_GC_FUNC_PROLOGUE (pGC);
458    (*pGC->funcs->DestroyGC)(pGC);
459    DAMAGE_GC_FUNC_EPILOGUE (pGC);
460}
461
462static void
463damageChangeGC (GCPtr		pGC,
464		unsigned long   mask)
465{
466    DAMAGE_GC_FUNC_PROLOGUE (pGC);
467    (*pGC->funcs->ChangeGC) (pGC, mask);
468    DAMAGE_GC_FUNC_EPILOGUE (pGC);
469}
470
471static void
472damageCopyGC (GCPtr	    pGCSrc,
473	      unsigned long mask,
474	      GCPtr	    pGCDst)
475{
476    DAMAGE_GC_FUNC_PROLOGUE (pGCDst);
477    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
478    DAMAGE_GC_FUNC_EPILOGUE (pGCDst);
479}
480
481static void
482damageChangeClip (GCPtr	    pGC,
483		  int	    type,
484		  pointer   pvalue,
485		  int	    nrects)
486{
487    DAMAGE_GC_FUNC_PROLOGUE (pGC);
488    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
489    DAMAGE_GC_FUNC_EPILOGUE (pGC);
490}
491
492static void
493damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
494{
495    DAMAGE_GC_FUNC_PROLOGUE (pgcDst);
496    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
497    DAMAGE_GC_FUNC_EPILOGUE (pgcDst);
498}
499
500static void
501damageDestroyClip(GCPtr pGC)
502{
503    DAMAGE_GC_FUNC_PROLOGUE (pGC);
504    (* pGC->funcs->DestroyClip)(pGC);
505    DAMAGE_GC_FUNC_EPILOGUE (pGC);
506}
507
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; \
514    }
515
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; \
521    }
522
523#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
524    TRANSLATE_BOX(box, pDrawable); \
525    TRIM_BOX(box, pGC); \
526    }
527
528#define BOX_NOT_EMPTY(box) \
529    (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
530
531#define checkGCDamage(d,g)	(getDrawableDamage(d) && \
532				 (!g->pCompositeClip ||\
533				  REGION_NOTEMPTY(d->pScreen, \
534						  g->pCompositeClip)))
535
536#ifdef RENDER
537
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; \
544    }
545
546#define checkPictureDamage(p)	(getDrawableDamage(p->pDrawable) && \
547				 REGION_NOTEMPTY(pScreen, p->pCompositeClip))
548
549static void
550damageComposite (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)
562{
563    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
564    PictureScreenPtr	ps = GetPictureScreen(pScreen);
565    damageScrPriv(pScreen);
566
567    if (checkPictureDamage (pDst))
568    {
569	BoxRec	box;
570
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);
578    }
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);
594}
595
596static void
597damageGlyphs (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)
606{
607    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
608    PictureScreenPtr	ps = GetPictureScreen(pScreen);
609    damageScrPriv(pScreen);
610
611    if (checkPictureDamage (pDst))
612    {
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;
621
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--)
629	{
630	    x += listTmp->xOff;
631	    y += listTmp->yOff;
632	    n = listTmp->len;
633	    while (n--)
634	    {
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;
650	    }
651	    listTmp++;
652	}
653	TRIM_PICTURE_BOX (box, pDst);
654	if (BOX_NOT_EMPTY(box))
655	    damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
656    }
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);
661}
662#endif
663
664/**********************************************************/
665
666
667static void
668damageFillSpans(DrawablePtr pDrawable,
669		GC	    *pGC,
670		int	    npt,
671		DDXPointPtr ppt,
672		int	    *pwidth,
673		int	    fSorted)
674{
675    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
676
677    if (npt && checkGCDamage (pDrawable, pGC))
678    {
679	int	    nptTmp = npt;
680	DDXPointPtr pptTmp = ppt;
681	int	    *pwidthTmp = pwidth;
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	{
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;
697	}
698
699	box.y2++;
700
701        if(!pGC->miTranslate) {
702           TRANSLATE_BOX(box, pDrawable);
703        }
704        TRIM_BOX(box, pGC);
705
706	if(BOX_NOT_EMPTY(box))
707	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
708    }
709
710    (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted);
711
712    damageReportPostOp (pDrawable);
713    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
714}
715
716static void
717damageSetSpans(DrawablePtr  pDrawable,
718	       GCPtr	    pGC,
719	       char	    *pcharsrc,
720	       DDXPointPtr  ppt,
721	       int	    *pwidth,
722	       int	    npt,
723	       int	    fSorted)
724{
725    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
726
727    if (npt && checkGCDamage (pDrawable, pGC))
728    {
729	DDXPointPtr pptTmp = ppt;
730	int	    *pwidthTmp = pwidth;
731	int	    nptTmp = npt;
732	BoxRec	    box;
733
734	box.x1 = pptTmp->x;
735	box.x2 = box.x1 + *pwidthTmp;
736	box.y2 = box.y1 = pptTmp->y;
737
738	while(--nptTmp)
739	{
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;
747	}
748
749	box.y2++;
750
751        if(!pGC->miTranslate) {
752           TRANSLATE_BOX(box, pDrawable);
753        }
754        TRIM_BOX(box, pGC);
755
756	if(BOX_NOT_EMPTY(box))
757	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
758    }
759    (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
760    damageReportPostOp (pDrawable);
761    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
762}
763
764static void
765damagePutImage(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)
775{
776    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
777    if (checkGCDamage (pDrawable, pGC))
778    {
779	BoxRec box;
780
781	box.x1 = x + pDrawable->x;
782	box.x2 = box.x1 + w;
783	box.y1 = y + pDrawable->y;
784	box.y2 = box.y1 + h;
785
786	TRIM_BOX(box, pGC);
787	if(BOX_NOT_EMPTY(box))
788	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
789    }
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);
794}
795
796static RegionPtr
797damageCopyArea(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)
806{
807    RegionPtr ret;
808    DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
809
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)
816    {
817	(*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
818    }
819
820    if (checkGCDamage (pDst, pGC))
821    {
822	BoxRec box;
823
824	box.x1 = dstx + pDst->x;
825	box.x2 = box.x1 + width;
826	box.y1 = dsty + pDst->y;
827	box.y2 = box.y1 + height;
828
829	TRIM_BOX(box, pGC);
830	if(BOX_NOT_EMPTY(box))
831	   damageDamageBox (pDst, &box, pGC->subWindowMode);
832    }
833
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;
839}
840
841static RegionPtr
842damageCopyPlane(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)
852{
853    RegionPtr ret;
854    DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
855
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)
862    {
863        (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
864    }
865
866    if (checkGCDamage (pDst, pGC))
867    {
868	BoxRec box;
869
870	box.x1 = dstx + pDst->x;
871	box.x2 = box.x1 + width;
872	box.y1 = dsty + pDst->y;
873	box.y2 = box.y1 + height;
874
875	TRIM_BOX(box, pGC);
876	if(BOX_NOT_EMPTY(box))
877	   damageDamageBox (pDst, &box, pGC->subWindowMode);
878    }
879
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;
885}
886
887static void
888damagePolyPoint(DrawablePtr pDrawable,
889		GCPtr	    pGC,
890		int	    mode,
891		int	    npt,
892		xPoint	    *ppt)
893{
894    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
895
896    if (npt && checkGCDamage (pDrawable, pGC))
897    {
898	BoxRec	box;
899	int	nptTmp = npt;
900	xPoint	*pptTmp = ppt;
901
902	box.x2 = box.x1 = pptTmp->x;
903	box.y2 = box.y1 = pptTmp->y;
904
905	/* this could be slow if the points were spread out */
906
907	while(--nptTmp)
908	{
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;
914	}
915
916	box.x2++;
917	box.y2++;
918
919	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
920	if(BOX_NOT_EMPTY(box))
921	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
922    }
923    (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt);
924    damageReportPostOp (pDrawable);
925    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
926}
927
928static void
929damagePolylines(DrawablePtr pDrawable,
930		GCPtr	    pGC,
931		int	    mode,
932		int	    npt,
933		DDXPointPtr ppt)
934{
935    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
936
937    if (npt && checkGCDamage (pDrawable, pGC))
938    {
939	int	    nptTmp = npt;
940	DDXPointPtr pptTmp = ppt;
941	BoxRec	    box;
942	int	    extra = pGC->lineWidth >> 1;
943
944	box.x2 = box.x1 = pptTmp->x;
945	box.y2 = box.y1 = pptTmp->y;
946
947	if(nptTmp > 1)
948	{
949	   if(pGC->joinStyle == JoinMiter)
950		extra = 6 * pGC->lineWidth;
951	   else if(pGC->capStyle == CapProjecting)
952		extra = pGC->lineWidth;
953        }
954
955	if(mode == CoordModePrevious)
956	{
957	   int x = box.x1;
958	   int y = box.y1;
959	   while(--nptTmp)
960	   {
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;
968	    }
969	}
970	else
971	{
972	   while(--nptTmp)
973	   {
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;
979	    }
980	}
981
982	box.x2++;
983	box.y2++;
984
985	if(extra)
986	{
987	   box.x1 -= extra;
988	   box.x2 += extra;
989	   box.y1 -= extra;
990	   box.y2 += extra;
991        }
992
993	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
994	if(BOX_NOT_EMPTY(box))
995	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
996    }
997    (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt);
998    damageReportPostOp (pDrawable);
999    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1000}
1001
1002static void
1003damagePolySegment(DrawablePtr	pDrawable,
1004		  GCPtr		pGC,
1005		  int		nSeg,
1006		  xSegment	*pSeg)
1007{
1008    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1009
1010    if (nSeg && checkGCDamage (pDrawable, pGC))
1011    {
1012	BoxRec	    box;
1013	int	    extra = pGC->lineWidth;
1014	int	    nsegTmp = nSeg;
1015	xSegment    *pSegTmp = pSeg;
1016
1017        if(pGC->capStyle != CapProjecting)
1018	   extra >>= 1;
1019
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;
1026	}
1027
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;
1034	}
1035
1036	while(--nsegTmp)
1037	{
1038	    pSegTmp++;
1039	    if(pSegTmp->x2 > pSegTmp->x1)
1040	    {
1041		if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1;
1042		if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2;
1043	    }
1044	    else
1045	    {
1046		if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2;
1047		if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1;
1048	    }
1049	    if(pSegTmp->y2 > pSegTmp->y1)
1050	    {
1051		if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1;
1052		if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2;
1053	    }
1054	    else
1055	    {
1056		if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2;
1057		if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1;
1058	    }
1059	}
1060
1061	box.x2++;
1062	box.y2++;
1063
1064	if(extra)
1065	{
1066	   box.x1 -= extra;
1067	   box.x2 += extra;
1068	   box.y1 -= extra;
1069	   box.y2 += extra;
1070        }
1071
1072	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1073	if(BOX_NOT_EMPTY(box))
1074	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1075    }
1076    (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg);
1077    damageReportPostOp (pDrawable);
1078    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1079}
1080
1081static void
1082damagePolyRectangle(DrawablePtr  pDrawable,
1083		    GCPtr        pGC,
1084		    int	         nRects,
1085		    xRectangle  *pRects)
1086{
1087    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1088
1089    if (nRects && checkGCDamage (pDrawable, pGC))
1090    {
1091	BoxRec	    box;
1092	int	    offset1, offset2, offset3;
1093	int	    nRectsTmp = nRects;
1094	xRectangle  *pRectsTmp = pRects;
1095
1096	offset2 = pGC->lineWidth;
1097	if(!offset2) offset2 = 1;
1098	offset1 = offset2 >> 1;
1099	offset3 = offset2 - offset1;
1100
1101	while(nRectsTmp--)
1102	{
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);
1110
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);
1118
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);
1126
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);
1134
1135	    pRectsTmp++;
1136	}
1137    }
1138    (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects);
1139    damageReportPostOp (pDrawable);
1140    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1141}
1142
1143static void
1144damagePolyArc(DrawablePtr   pDrawable,
1145	      GCPtr	    pGC,
1146	      int	    nArcs,
1147	      xArc	    *pArcs)
1148{
1149    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1150
1151    if (nArcs && checkGCDamage (pDrawable, pGC))
1152    {
1153	int	extra = pGC->lineWidth >> 1;
1154	BoxRec	box;
1155	int	nArcsTmp = nArcs;
1156	xArc	*pArcsTmp = pArcs;
1157
1158	box.x1 = pArcsTmp->x;
1159	box.x2 = box.x1 + pArcsTmp->width;
1160	box.y1 = pArcsTmp->y;
1161	box.y2 = box.y1 + pArcsTmp->height;
1162
1163	while(--nArcsTmp)
1164	{
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;
1174        }
1175
1176	if(extra)
1177	{
1178	   box.x1 -= extra;
1179	   box.x2 += extra;
1180	   box.y1 -= extra;
1181	   box.y2 += extra;
1182        }
1183
1184	box.x2++;
1185	box.y2++;
1186
1187	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1188	if(BOX_NOT_EMPTY(box))
1189	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1190    }
1191    (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs);
1192    damageReportPostOp (pDrawable);
1193    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1194}
1195
1196static void
1197damageFillPolygon(DrawablePtr	pDrawable,
1198		  GCPtr		pGC,
1199		  int		shape,
1200		  int		mode,
1201		  int		npt,
1202		  DDXPointPtr	ppt)
1203{
1204    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1205
1206    if (npt > 2 && checkGCDamage (pDrawable, pGC))
1207    {
1208	DDXPointPtr pptTmp = ppt;
1209	int	    nptTmp = npt;
1210	BoxRec	    box;
1211
1212	box.x2 = box.x1 = pptTmp->x;
1213	box.y2 = box.y1 = pptTmp->y;
1214
1215	if(mode != CoordModeOrigin)
1216	{
1217	   int x = box.x1;
1218	   int y = box.y1;
1219	   while(--nptTmp)
1220	   {
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;
1228	    }
1229	}
1230	else
1231	{
1232	   while(--nptTmp)
1233	   {
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;
1239	    }
1240	}
1241
1242	box.x2++;
1243	box.y2++;
1244
1245	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1246	if(BOX_NOT_EMPTY(box))
1247	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1248    }
1249
1250    (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt);
1251    damageReportPostOp (pDrawable);
1252    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1253}
1254
1255
1256static void
1257damagePolyFillRect(DrawablePtr	pDrawable,
1258		   GCPtr	pGC,
1259		   int		nRects,
1260		   xRectangle	*pRects)
1261{
1262    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1263    if (nRects && checkGCDamage (pDrawable, pGC))
1264    {
1265	BoxRec	    box;
1266	xRectangle  *pRectsTmp = pRects;
1267	int	    nRectsTmp = nRects;
1268
1269	box.x1 = pRectsTmp->x;
1270	box.x2 = box.x1 + pRectsTmp->width;
1271	box.y1 = pRectsTmp->y;
1272	box.y2 = box.y1 + pRectsTmp->height;
1273
1274	while(--nRectsTmp)
1275	{
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;
1283	}
1284
1285	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1286	if(BOX_NOT_EMPTY(box))
1287	    damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1288    }
1289    (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects);
1290    damageReportPostOp (pDrawable);
1291    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1292}
1293
1294
1295static void
1296damagePolyFillArc(DrawablePtr	pDrawable,
1297		  GCPtr		pGC,
1298		  int		nArcs,
1299		  xArc		*pArcs)
1300{
1301    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1302
1303    if (nArcs && checkGCDamage (pDrawable, pGC))
1304    {
1305	BoxRec	box;
1306	int	nArcsTmp = nArcs;
1307	xArc	*pArcsTmp = pArcs;
1308
1309	box.x1 = pArcsTmp->x;
1310	box.x2 = box.x1 + pArcsTmp->width;
1311	box.y1 = pArcsTmp->y;
1312	box.y2 = box.y1 + pArcsTmp->height;
1313
1314	while(--nArcsTmp)
1315	{
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;
1325        }
1326
1327	TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
1328	if(BOX_NOT_EMPTY(box))
1329	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1330    }
1331    (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs);
1332    damageReportPostOp (pDrawable);
1333    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1334}
1335
1336/*
1337 * general Poly/Image text function.  Extract glyph information,
1338 * compute bounding box and remove cursor if it is overlapped.
1339 */
1340
1341static void
1342damageDamageChars (DrawablePtr	pDrawable,
1343		   FontPtr	font,
1344		   int		x,
1345		   int		y,
1346		   unsigned int	n,
1347		   CharInfoPtr	*charinfo,
1348		   Bool		imageblt,
1349		   int		subWindowMode)
1350{
1351    ExtentInfoRec   extents;
1352    BoxRec	    box;
1353
1354    QueryGlyphExtents(font, charinfo, n, &extents);
1355    if (imageblt)
1356    {
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;
1367    }
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);
1373}
1374
1375/*
1376 * values for textType:
1377 */
1378#define TT_POLY8   0
1379#define TT_IMAGE8  1
1380#define TT_POLY16  2
1381#define TT_IMAGE16 3
1382
1383static int
1384damageText (DrawablePtr	    pDrawable,
1385	    GCPtr	    pGC,
1386	    int		    x,
1387	    int		    y,
1388	    unsigned long   count,
1389	    char	    *chars,
1390	    FontEncoding    fontEncoding,
1391	    Bool	    textType)
1392{
1393    CharInfoPtr	    *charinfo;
1394    CharInfoPtr	    *info;
1395    unsigned long   i;
1396    unsigned int    n;
1397    int		    w;
1398    Bool	    imageblt;
1399
1400    imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
1401
1402    charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
1403    if (!charinfo)
1404	return x;
1405
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;
1413
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));
1423    }
1424    DEALLOCATE_LOCAL(charinfo);
1425    return x + w;
1426}
1427
1428static int
1429damagePolyText8(DrawablePtr pDrawable,
1430		GCPtr	    pGC,
1431		int	    x,
1432		int	    y,
1433		int	    count,
1434		char	    *chars)
1435{
1436    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1437
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;
1446}
1447
1448static int
1449damagePolyText16(DrawablePtr	pDrawable,
1450		 GCPtr		pGC,
1451		 int		x,
1452		 int		y,
1453		 int		count,
1454		 unsigned short	*chars)
1455{
1456    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1457
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;
1467}
1468
1469static void
1470damageImageText8(DrawablePtr	pDrawable,
1471		 GCPtr		pGC,
1472		 int		x,
1473		 int		y,
1474		 int		count,
1475		 char		*chars)
1476{
1477    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1478
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);
1486}
1487
1488static void
1489damageImageText16(DrawablePtr	pDrawable,
1490		  GCPtr		pGC,
1491		  int		x,
1492		  int		y,
1493		  int		count,
1494		  unsigned short *chars)
1495{
1496    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1497
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);
1506}
1507
1508
1509static void
1510damageImageGlyphBlt(DrawablePtr	    pDrawable,
1511		    GCPtr	    pGC,
1512		    int		    x,
1513		    int		    y,
1514		    unsigned int    nglyph,
1515		    CharInfoPtr	    *ppci,
1516		    pointer	    pglyphBase)
1517{
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);
1525}
1526
1527static void
1528damagePolyGlyphBlt(DrawablePtr	pDrawable,
1529		   GCPtr	pGC,
1530		   int		x,
1531		   int		y,
1532		   unsigned int	nglyph,
1533		   CharInfoPtr	*ppci,
1534		   pointer	pglyphBase)
1535{
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);
1543}
1544
1545static void
1546damagePushPixels(GCPtr		pGC,
1547		 PixmapPtr	pBitMap,
1548		 DrawablePtr	pDrawable,
1549		 int		dx,
1550		 int		dy,
1551		 int		xOrg,
1552		 int		yOrg)
1553{
1554    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
1555    if(checkGCDamage (pDrawable, pGC))
1556    {
1557	BoxRec box;
1558
1559        box.x1 = xOrg;
1560        box.y1 = yOrg;
1561
1562        if(!pGC->miTranslate) {
1563           box.x1 += pDrawable->x;
1564           box.y1 += pDrawable->y;
1565        }
1566
1567	box.x2 = box.x1 + dx;
1568	box.y2 = box.y1 + dy;
1569
1570	TRIM_BOX(box, pGC);
1571	if(BOX_NOT_EMPTY(box))
1572	   damageDamageBox (pDrawable, &box, pGC->subWindowMode);
1573    }
1574    (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
1575    damageReportPostOp (pDrawable);
1576    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
1577}
1578
1579static void
1580damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage)
1581{
1582    while (*pPrev)
1583    {
1584	if (*pPrev == pDamage)
1585	{
1586	    *pPrev = pDamage->pNext;
1587	    return;
1588	}
1589	pPrev = &(*pPrev)->pNext;
1590    }
1591#if DAMAGE_VALIDATE_ENABLE
1592    ErrorF ("Damage not on list\n");
1593    abort ();
1594#endif
1595}
1596
1597static void
1598damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage)
1599{
1600#if DAMAGE_VALIDATE_ENABLE
1601    DamagePtr	pOld;
1602
1603    for (pOld = *pPrev; pOld; pOld = pOld->pNext)
1604	if (pOld == pDamage) {
1605	    ErrorF ("Damage already on list\n");
1606	    abort ();
1607	}
1608#endif
1609    pDamage->pNext = *pPrev;
1610    *pPrev = pDamage;
1611}
1612
1613static Bool
1614damageDestroyPixmap (PixmapPtr pPixmap)
1615{
1616    ScreenPtr	pScreen = pPixmap->drawable.pScreen;
1617    damageScrPriv(pScreen);
1618
1619    if (pPixmap->refcnt == 1)
1620    {
1621	DamagePtr	*pPrev = getPixmapDamageRef (pPixmap);
1622	DamagePtr	pDamage;
1623
1624	while ((pDamage = *pPrev))
1625	{
1626	    damageRemoveDamage (pPrev, pDamage);
1627	    if (!pDamage->isWindow)
1628		DamageDestroy (pDamage);
1629	}
1630    }
1631    unwrap (pScrPriv, pScreen, DestroyPixmap);
1632    (*pScreen->DestroyPixmap) (pPixmap);
1633    wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
1634    return TRUE;
1635}
1636
1637static void
1638damagePaintWindow(WindowPtr pWindow,
1639		  RegionPtr prgn,
1640		  int	    what)
1641{
1642    ScreenPtr pScreen = pWindow->drawable.pScreen;
1643    damageScrPriv(pScreen);
1644
1645    /*
1646     * Painting background none doesn't actually *do* anything, so
1647     * no damage is recorded
1648     */
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);
1662    }
1663}
1664
1665
1666static void
1667damageCopyWindow(WindowPtr	pWindow,
1668		 DDXPointRec	ptOldOrg,
1669		 RegionPtr	prgnSrc)
1670{
1671    ScreenPtr pScreen = pWindow->drawable.pScreen;
1672    damageScrPriv(pScreen);
1673
1674    if (getWindowDamage (pWindow))
1675    {
1676	int dx = pWindow->drawable.x - ptOldOrg.x;
1677	int dy = pWindow->drawable.y - ptOldOrg.y;
1678
1679	/*
1680	 * The region comes in source relative, but the damage occurs
1681	 * at the destination location.  Translate back and forth.
1682	 */
1683	REGION_TRANSLATE (pScreen, prgnSrc, dx, dy);
1684	damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE, -1);
1685	REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
1686    }
1687    unwrap (pScrPriv, pScreen, CopyWindow);
1688    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
1689    damageReportPostOp (&pWindow->drawable);
1690    wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
1691}
1692
1693static 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 */
1705};
1706
1707static void
1708damageRestoreAreas (PixmapPtr	pPixmap,
1709		    RegionPtr	prgn,
1710		    int		xorg,
1711		    int		yorg,
1712		    WindowPtr	pWindow)
1713{
1714    ScreenPtr pScreen = pWindow->drawable.pScreen;
1715    damageScrPriv(pScreen);
1716
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);
1724}
1725
1726static void
1727damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
1728{
1729    DamagePtr	pDamage;
1730    ScreenPtr	pScreen = pWindow->drawable.pScreen;
1731    damageScrPriv(pScreen);
1732
1733    if ((pDamage = damageGetWinPriv(pWindow)))
1734    {
1735	PixmapPtr   pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow);
1736	DamagePtr   *pPrev = getPixmapDamageRef(pOldPixmap);
1737
1738	while (pDamage)
1739	{
1740	    damageRemoveDamage (pPrev, pDamage);
1741	    pDamage = pDamage->pNextWin;
1742	}
1743    }
1744    unwrap (pScrPriv, pScreen, SetWindowPixmap);
1745    (*pScreen->SetWindowPixmap) (pWindow, pPixmap);
1746    wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
1747    if ((pDamage = damageGetWinPriv(pWindow)))
1748    {
1749	DamagePtr   *pPrev = getPixmapDamageRef(pPixmap);
1750
1751	while (pDamage)
1752	{
1753	    damageInsertDamage (pPrev, pDamage);
1754	    pDamage = pDamage->pNextWin;
1755	}
1756    }
1757}
1758
1759static Bool
1760damageDestroyWindow (WindowPtr pWindow)
1761{
1762    DamagePtr	pDamage;
1763    ScreenPtr	pScreen = pWindow->drawable.pScreen;
1764    Bool	ret;
1765    damageScrPriv(pScreen);
1766
1767    while ((pDamage = damageGetWinPriv(pWindow)))
1768    {
1769	DamageUnregister (&pWindow->drawable, pDamage);
1770	DamageDestroy (pDamage);
1771    }
1772    unwrap (pScrPriv, pScreen, DestroyWindow);
1773    ret = (*pScreen->DestroyWindow) (pWindow);
1774    wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
1775    return ret;
1776}
1777
1778static Bool
1779damageCloseScreen (int i, ScreenPtr pScreen)
1780{
1781    damageScrPriv(pScreen);
1782
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);
1792}
1793
1794Bool
1795DamageSetup (ScreenPtr pScreen)
1796{
1797    DamageScrPrivPtr	pScrPriv;
1798#ifdef RENDER
1799    PictureScreenPtr	ps = GetPictureScreenIfSet(pScreen);
1800#endif
1801
1802    if (damageGeneration != serverGeneration)
1803    {
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;
1817    }
1818    if (pScreen->devPrivates[damageScrPrivateIndex].ptr)
1819	return TRUE;
1820
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;
1827
1828    pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec));
1829    if (!pScrPriv)
1830	return FALSE;
1831
1832    pScrPriv->internalLevel = 0;
1833    pScrPriv->pScreenDamage = 0;
1834
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);
1849    }
1850#endif
1851
1852    pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv;
1853    return TRUE;
1854}
1855
1856DamagePtr
1857DamageCreate (DamageReportFunc  damageReport,
1858	      DamageDestroyFunc	damageDestroy,
1859	      DamageReportLevel	damageLevel,
1860	      Bool		isInternal,
1861	      ScreenPtr		pScreen,
1862	      void		*closure)
1863{
1864    DamagePtr	pDamage;
1865
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);
1873
1874    pDamage->damageLevel = damageLevel;
1875    pDamage->isInternal = isInternal;
1876    pDamage->closure = closure;
1877    pDamage->isWindow = FALSE;
1878    pDamage->pDrawable = 0;
1879    pDamage->reportAfter = FALSE;
1880
1881    pDamage->damageReport = damageReport;
1882    pDamage->damageDestroy = damageDestroy;
1883    return pDamage;
1884}
1885
1886void
1887DamageRegister (DrawablePtr pDrawable,
1888		DamagePtr   pDamage)
1889{
1890    if (pDrawable->type == DRAWABLE_WINDOW)
1891    {
1892	WindowPtr   pWindow = (WindowPtr) pDrawable;
1893	winDamageRef(pWindow);
1894
1895#if DAMAGE_VALIDATE_ENABLE
1896	DamagePtr   pOld;
1897
1898	for (pOld = *pPrev; pOld; pOld = pOld->pNextWin)
1899	    if (pOld == pDamage) {
1900		ErrorF ("Damage already on window list\n");
1901		abort ();
1902	    }
1903#endif
1904	pDamage->pNextWin = *pPrev;
1905	*pPrev = pDamage;
1906	pDamage->isWindow = TRUE;
1907    }
1908    else
1909	pDamage->isWindow = FALSE;
1910    pDamage->pDrawable = pDrawable;
1911    damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage);
1912}
1913
1914void
1915DamageDrawInternal (ScreenPtr pScreen, Bool enable)
1916{
1917    damageScrPriv (pScreen);
1918
1919    pScrPriv->internalLevel += enable ? 1 : -1;
1920}
1921
1922void
1923DamageUnregister (DrawablePtr	    pDrawable,
1924		  DamagePtr	    pDamage)
1925{
1926    if (pDrawable->type == DRAWABLE_WINDOW)
1927    {
1928	WindowPtr   pWindow = (WindowPtr) pDrawable;
1929	winDamageRef (pWindow);
1930#if DAMAGE_VALIDATE_ENABLE
1931	int	found = 0;
1932#endif
1933
1934	while (*pPrev)
1935	{
1936	    if (*pPrev == pDamage)
1937	    {
1938		*pPrev = pDamage->pNextWin;
1939#if DAMAGE_VALIDATE_ENABLE
1940		found = 1;
1941#endif
1942		break;
1943	    }
1944	    pPrev = &(*pPrev)->pNextWin;
1945	}
1946#if DAMAGE_VALIDATE_ENABLE
1947	if (!found) {
1948	    ErrorF ("Damage not on window list\n");
1949	    abort ();
1950	}
1951#endif
1952    }
1953    pDamage->pDrawable = 0;
1954    damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage);
1955}
1956
1957void
1958DamageDestroy (DamagePtr    pDamage)
1959{
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);
1965}
1966
1967Bool
1968DamageSubtract (DamagePtr	    pDamage,
1969		const RegionPtr	    pRegion)
1970{
1971    RegionPtr	pClip;
1972    RegionRec	pixmapClip;
1973    DrawablePtr	pDrawable = pDamage->pDrawable;
1974
1975    REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion);
1976    if (pDrawable)
1977    {
1978	if (pDrawable->type == DRAWABLE_WINDOW)
1979	    pClip = &((WindowPtr) pDrawable)->borderClip;
1980	else
1981	{
1982	    BoxRec  box;
1983
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;
1990	}
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);
1996    }
1997    return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage);
1998}
1999
2000void
2001DamageEmpty (DamagePtr	    pDamage)
2002{
2003    REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage);
2004}
2005
2006RegionPtr
2007DamageRegion (DamagePtr		    pDamage)
2008{
2009    return &pDamage->damage;
2010}
2011
2012_X_EXPORT void
2013DamageDamageRegion (DrawablePtr	pDrawable,
2014		    RegionPtr	pRegion)
2015{
2016    damageDamageRegion (pDrawable, pRegion, FALSE, -1);
2017
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.
2021     */
2022    damageReportPostOp (pDrawable);
2023}
2024
2025void
2026DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter)
2027{
2028    pDamage->reportAfter = reportAfter;
2029}
2030