2 * Copyright © 2003 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
30 #include "scrnintstr.h"
31 #include "windowstr.h"
32 #include <X11/fonts/font.h>
33 #include "dixfontstr.h"
34 #include <X11/fonts/fontstruct.h>
36 #include "regionstr.h"
40 #include "damagestr.h"
45 #define wrap(priv, real, mem, func) {\
46 priv->mem = real->mem; \
50 #define unwrap(priv, real, mem) {\
51 real->mem = priv->mem; \
54 #define BOX_SAME(a,b) \
55 ((a)->x1 == (b)->x1 && \
56 (a)->y1 == (b)->y1 && \
57 (a)->x2 == (b)->x2 && \
60 #define DAMAGE_VALIDATE_ENABLE 0
61 #define DAMAGE_DEBUG_ENABLE 0
62 #if DAMAGE_DEBUG_ENABLE
63 #define DAMAGE_DEBUG(x) ErrorF x
65 #define DAMAGE_DEBUG(x)
68 #define getPixmapDamageRef(pPixmap) \
69 ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr))
71 #define pixmapDamage(pPixmap) damagePixPriv(pPixmap)
73 static int damageScrPrivateIndex
;
74 static int damagePixPrivateIndex
;
75 static int damageGCPrivateIndex
;
76 static int damageWinPrivateIndex
;
77 static int damageGeneration
;
80 getDrawableDamageRef (DrawablePtr pDrawable
)
84 if (pDrawable
->type
== DRAWABLE_WINDOW
)
86 ScreenPtr pScreen
= pDrawable
->pScreen
;
89 if (pScreen
->GetWindowPixmap
90 #ifdef ROOTLESS_WORKAROUND
91 && ((WindowPtr
)pDrawable
)->viewable
94 pPixmap
= (*pScreen
->GetWindowPixmap
) ((WindowPtr
)pDrawable
);
98 damageScrPriv(pScreen
);
100 return &pScrPriv
->pScreenDamage
;
104 pPixmap
= (PixmapPtr
) pDrawable
;
105 return getPixmapDamageRef (pPixmap
);
108 #define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable))
109 #define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable)
111 #define drawableDamage(pDrawable) \
112 DamagePtr pDamage = getDrawableDamage(pDrawable)
114 #define windowDamage(pWin) drawableDamage(&(pWin)->drawable)
116 #define winDamageRef(pWindow) \
117 DamagePtr *pPrev = (DamagePtr *) \
118 &(pWindow->devPrivates[damageWinPrivateIndex].ptr)
121 DamageReportDamage (DamagePtr pDamage
, RegionPtr pDamageRegion
)
127 switch (pDamage
->damageLevel
) {
128 case DamageReportRawRegion
:
129 (*pDamage
->damageReport
) (pDamage
, pDamageRegion
, pDamage
->closure
);
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
,
137 (*pDamage
->damageReport
) (pDamage
, &tmpRegion
, pDamage
->closure
);
139 REGION_UNINIT(pScreen
, &tmpRegion
);
141 case DamageReportBoundingBox
:
142 tmpBox
= *REGION_EXTENTS (pScreen
, &pDamage
->damage
);
143 REGION_UNION(pScreen
, &pDamage
->damage
, &pDamage
->damage
,
145 if (!BOX_SAME (&tmpBox
, REGION_EXTENTS (pScreen
, &pDamage
->damage
))) {
146 (*pDamage
->damageReport
) (pDamage
, &pDamage
->damage
,
150 case DamageReportNonEmpty
:
151 was_empty
= !REGION_NOTEMPTY(pScreen
, &pDamage
->damage
);
152 REGION_UNION(pScreen
, &pDamage
->damage
, &pDamage
->damage
,
154 if (was_empty
&& REGION_NOTEMPTY(pScreen
, &pDamage
->damage
)) {
155 (*pDamage
->damageReport
) (pDamage
, &pDamage
->damage
,
159 case DamageReportNone
:
160 REGION_UNION(pScreen
, &pDamage
->damage
, &pDamage
->damage
,
166 #if DAMAGE_DEBUG_ENABLE
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__)
172 damageDamageRegion (DrawablePtr pDrawable
, RegionPtr pRegion
, Bool clip
,
176 ScreenPtr pScreen
= pDrawable
->pScreen
;
177 damageScrPriv(pScreen
);
178 drawableDamage(pDrawable
);
180 RegionRec clippedRec
;
181 RegionPtr pDamageRegion
;
185 int screen_x
= 0, screen_y
= 0;
188 /* short circuit for empty regions */
189 if (!REGION_NOTEMPTY(pScreen
, pRegion
))
194 * When drawing to a pixmap which is storing window contents,
195 * the region presented is in pixmap relative coordinates which
196 * need to be converted to screen relative coordinates
198 if (pDrawable
->type
!= DRAWABLE_WINDOW
)
200 screen_x
= ((PixmapPtr
) pDrawable
)->screen_x
- pDrawable
->x
;
201 screen_y
= ((PixmapPtr
) pDrawable
)->screen_y
- pDrawable
->y
;
203 if (screen_x
|| screen_y
)
204 REGION_TRANSLATE (pScreen
, pRegion
, screen_x
, screen_y
);
207 if (pDrawable
->type
== DRAWABLE_WINDOW
&&
208 ((WindowPtr
)(pDrawable
))->backingStore
== NotUseful
)
210 if (subWindowMode
== ClipByChildren
)
212 REGION_INTERSECT(pScreen
, pRegion
, pRegion
,
213 &((WindowPtr
)(pDrawable
))->clipList
);
215 else if (subWindowMode
== IncludeInferiors
)
217 RegionPtr pTempRegion
=
218 NotClippedByChildren((WindowPtr
)(pDrawable
));
219 REGION_INTERSECT(pScreen
, pRegion
, pRegion
, pTempRegion
);
220 REGION_DESTROY(pScreen
, pTempRegion
);
222 /* If subWindowMode is set to an invalid value, don't perform
223 * any drawable-based clipping. */
227 REGION_NULL (pScreen
, &clippedRec
);
228 for (; pDamage
; pDamage
= pNext
)
230 pNext
= pDamage
->pNext
;
232 * Check for internal damage and don't send events
234 if (pScrPriv
->internalLevel
> 0 && !pDamage
->isInternal
)
236 DAMAGE_DEBUG (("non internal damage, skipping at %d\n",
237 pScrPriv
->internalLevel
));
241 * Check for unrealized windows
243 if (pDamage
->pDrawable
->type
== DRAWABLE_WINDOW
&&
244 !((WindowPtr
) (pDamage
->pDrawable
))->realized
)
247 DAMAGE_DEBUG (("damage while window unrealized\n"));
252 draw_x
= pDamage
->pDrawable
->x
;
253 draw_y
= pDamage
->pDrawable
->y
;
256 * Need to move everyone to screen coordinates
257 * XXX what about off-screen pixmaps with non-zero x/y?
259 if (pDamage
->pDrawable
->type
!= DRAWABLE_WINDOW
)
261 draw_x
+= ((PixmapPtr
) pDamage
->pDrawable
)->screen_x
;
262 draw_y
+= ((PixmapPtr
) pDamage
->pDrawable
)->screen_y
;
267 * Clip against border or pixmap bounds
270 pDamageRegion
= pRegion
;
271 if (clip
|| pDamage
->pDrawable
!= pDrawable
)
273 pDamageRegion
= &clippedRec
;
274 if (pDamage
->pDrawable
->type
== DRAWABLE_WINDOW
) {
275 REGION_INTERSECT (pScreen
, pDamageRegion
, pRegion
,
276 &((WindowPtr
)(pDamage
->pDrawable
))->borderClip
);
281 box
.x2
= draw_x
+ pDamage
->pDrawable
->width
;
282 box
.y2
= draw_y
+ pDamage
->pDrawable
->height
;
283 REGION_INIT(pScreen
, &pixClip
, &box
, 1);
284 REGION_INTERSECT (pScreen
, pDamageRegion
, pRegion
, &pixClip
);
285 REGION_UNINIT(pScreen
, &pixClip
);
288 * Short circuit empty results
290 if (!REGION_NOTEMPTY(pScreen
, pDamageRegion
))
294 DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
296 pDamageRegion
->extents
.x2
- pDamageRegion
->extents
.x1
,
297 pDamageRegion
->extents
.y2
- pDamageRegion
->extents
.y1
,
298 pDamageRegion
->extents
.x1
, pDamageRegion
->extents
.y1
,
299 pDrawable
->id
, pDamage
->pDrawable
->id
));
302 * Move region to target coordinate space
304 if (draw_x
|| draw_y
)
305 REGION_TRANSLATE (pScreen
, pDamageRegion
, -draw_x
, -draw_y
);
307 /* If the damage rec has been flagged to report damage after the op has
308 * completed, then union it into the delayed damage region, which will
309 * be used for reporting after calling down, and skip the reporting
311 if (!pDamage
->reportAfter
) {
312 DamageReportDamage (pDamage
, pDamageRegion
);
314 REGION_UNION(pScreen
, &pDamage
->pendingDamage
,
315 &pDamage
->pendingDamage
, pDamageRegion
);
319 * translate original region back
321 if (pDamageRegion
== pRegion
&& (draw_x
|| draw_y
))
322 REGION_TRANSLATE (pScreen
, pDamageRegion
, draw_x
, draw_y
);
325 if (screen_x
|| screen_y
)
326 REGION_TRANSLATE (pScreen
, pRegion
, -screen_x
, -screen_y
);
329 REGION_UNINIT (pScreen
, &clippedRec
);
333 damageReportPostOp (DrawablePtr pDrawable
)
335 drawableDamage(pDrawable
);
337 for (; pDamage
!= NULL
; pDamage
= pDamage
->pNext
)
339 if (pDamage
->reportAfter
) {
340 DamageReportDamage (pDamage
, &pDamage
->pendingDamage
);
341 REGION_EMPTY (pScreen
, &pDamage
->pendingDamage
);
347 #if DAMAGE_DEBUG_ENABLE
348 #define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
350 _damageDamageBox (DrawablePtr pDrawable
, BoxPtr pBox
, int subWindowMode
, const char *where
)
353 damageDamageBox (DrawablePtr pDrawable
, BoxPtr pBox
, int subWindowMode
)
358 REGION_INIT (pDrawable
->pScreen
, ®ion
, pBox
, 1);
359 #if DAMAGE_DEBUG_ENABLE
360 _damageDamageRegion (pDrawable
, ®ion
, TRUE
, subWindowMode
, where
);
362 damageDamageRegion (pDrawable
, ®ion
, TRUE
, subWindowMode
);
364 REGION_UNINIT (pDrawable
->pScreen
, ®ion
);
367 static void damageValidateGC(GCPtr
, unsigned long, DrawablePtr
);
368 static void damageChangeGC(GCPtr
, unsigned long);
369 static void damageCopyGC(GCPtr
, unsigned long, GCPtr
);
370 static void damageDestroyGC(GCPtr
);
371 static void damageChangeClip(GCPtr
, int, pointer
, int);
372 static void damageDestroyClip(GCPtr
);
373 static void damageCopyClip(GCPtr
, GCPtr
);
375 static GCFuncs damageGCFuncs
= {
376 damageValidateGC
, damageChangeGC
, damageCopyGC
, damageDestroyGC
,
377 damageChangeClip
, damageDestroyClip
, damageCopyClip
380 static GCOps damageGCOps
;
383 damageCreateGC(GCPtr pGC
)
385 ScreenPtr pScreen
= pGC
->pScreen
;
386 damageScrPriv(pScreen
);
390 pGC
->pCompositeClip
= 0;
391 unwrap (pScrPriv
, pScreen
, CreateGC
);
392 if((ret
= (*pScreen
->CreateGC
) (pGC
))) {
394 pGCPriv
->funcs
= pGC
->funcs
;
395 pGC
->funcs
= &damageGCFuncs
;
397 wrap (pScrPriv
, pScreen
, CreateGC
, damageCreateGC
);
404 damageWrapGC (GCPtr pGC
)
409 pGCPriv
->funcs
= pGC
->funcs
;
410 pGC
->funcs
= &damageGCFuncs
;
414 damageUnwrapGC (GCPtr pGC
)
418 pGC
->funcs
= pGCPriv
->funcs
;
420 pGC
->ops
= pGCPriv
->ops
;
424 #define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
426 GCFuncs *oldFuncs = pGC->funcs; \
427 unwrap(pGCPriv, pGC, funcs); \
428 unwrap(pGCPriv, pGC, ops); \
430 #define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
431 wrap(pGCPriv, pGC, funcs, oldFuncs); \
432 wrap(pGCPriv, pGC, ops, &damageGCOps)
434 #define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
436 unwrap(pGCPriv, pGC, funcs); \
437 if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
439 #define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
440 wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \
441 if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
444 damageValidateGC(GCPtr pGC
,
445 unsigned long changes
,
446 DrawablePtr pDrawable
)
448 DAMAGE_GC_FUNC_PROLOGUE (pGC
);
449 (*pGC
->funcs
->ValidateGC
)(pGC
, changes
, pDrawable
);
450 pGCPriv
->ops
= pGC
->ops
; /* just so it's not NULL */
451 DAMAGE_GC_FUNC_EPILOGUE (pGC
);
455 damageDestroyGC(GCPtr pGC
)
457 DAMAGE_GC_FUNC_PROLOGUE (pGC
);
458 (*pGC
->funcs
->DestroyGC
)(pGC
);
459 DAMAGE_GC_FUNC_EPILOGUE (pGC
);
463 damageChangeGC (GCPtr pGC
,
466 DAMAGE_GC_FUNC_PROLOGUE (pGC
);
467 (*pGC
->funcs
->ChangeGC
) (pGC
, mask
);
468 DAMAGE_GC_FUNC_EPILOGUE (pGC
);
472 damageCopyGC (GCPtr pGCSrc
,
476 DAMAGE_GC_FUNC_PROLOGUE (pGCDst
);
477 (*pGCDst
->funcs
->CopyGC
) (pGCSrc
, mask
, pGCDst
);
478 DAMAGE_GC_FUNC_EPILOGUE (pGCDst
);
482 damageChangeClip (GCPtr pGC
,
487 DAMAGE_GC_FUNC_PROLOGUE (pGC
);
488 (*pGC
->funcs
->ChangeClip
) (pGC
, type
, pvalue
, nrects
);
489 DAMAGE_GC_FUNC_EPILOGUE (pGC
);
493 damageCopyClip(GCPtr pgcDst
, GCPtr pgcSrc
)
495 DAMAGE_GC_FUNC_PROLOGUE (pgcDst
);
496 (* pgcDst
->funcs
->CopyClip
)(pgcDst
, pgcSrc
);
497 DAMAGE_GC_FUNC_EPILOGUE (pgcDst
);
501 damageDestroyClip(GCPtr pGC
)
503 DAMAGE_GC_FUNC_PROLOGUE (pGC
);
504 (* pGC
->funcs
->DestroyClip
)(pGC
);
505 DAMAGE_GC_FUNC_EPILOGUE (pGC
);
508 #define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
509 BoxPtr extents = &pGC->pCompositeClip->extents;\
510 if(box.x1 < extents->x1) box.x1 = extents->x1; \
511 if(box.x2 > extents->x2) box.x2 = extents->x2; \
512 if(box.y1 < extents->y1) box.y1 = extents->y1; \
513 if(box.y2 > extents->y2) box.y2 = extents->y2; \
516 #define TRANSLATE_BOX(box, pDrawable) { \
517 box.x1 += pDrawable->x; \
518 box.x2 += pDrawable->x; \
519 box.y1 += pDrawable->y; \
520 box.y2 += pDrawable->y; \
523 #define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
524 TRANSLATE_BOX(box, pDrawable); \
525 TRIM_BOX(box, pGC); \
528 #define BOX_NOT_EMPTY(box) \
529 (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
531 #define checkGCDamage(d,g) (getDrawableDamage(d) && \
532 (!g->pCompositeClip ||\
533 REGION_NOTEMPTY(d->pScreen, \
538 #define TRIM_PICTURE_BOX(box, pDst) { \
539 BoxPtr extents = &pDst->pCompositeClip->extents;\
540 if(box.x1 < extents->x1) box.x1 = extents->x1; \
541 if(box.x2 > extents->x2) box.x2 = extents->x2; \
542 if(box.y1 < extents->y1) box.y1 = extents->y1; \
543 if(box.y2 > extents->y2) box.y2 = extents->y2; \
546 #define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \
547 REGION_NOTEMPTY(pScreen, p->pCompositeClip))
550 damageComposite (CARD8 op
,
563 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
564 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
565 damageScrPriv(pScreen
);
567 if (checkPictureDamage (pDst
))
571 box
.x1
= xDst
+ pDst
->pDrawable
->x
;
572 box
.y1
= yDst
+ pDst
->pDrawable
->y
;
573 box
.x2
= box
.x1
+ width
;
574 box
.y2
= box
.y1
+ height
;
575 TRIM_PICTURE_BOX(box
, pDst
);
576 if (BOX_NOT_EMPTY(box
))
577 damageDamageBox (pDst
->pDrawable
, &box
, pDst
->subWindowMode
);
579 unwrap (pScrPriv
, ps
, Composite
);
580 (*ps
->Composite
) (op
,
592 damageReportPostOp (pDst
->pDrawable
);
593 wrap (pScrPriv
, ps
, Composite
, damageComposite
);
597 damageGlyphs (CARD8 op
,
600 PictFormatPtr maskFormat
,
607 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
608 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
609 damageScrPriv(pScreen
);
611 if (checkPictureDamage (pDst
))
613 int nlistTmp
= nlist
;
614 GlyphListPtr listTmp
= list
;
615 GlyphPtr
*glyphsTmp
= glyphs
;
626 x
= pDst
->pDrawable
->x
;
627 y
= pDst
->pDrawable
->y
;
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
;
648 x
+= glyph
->info
.xOff
;
649 y
+= glyph
->info
.yOff
;
653 TRIM_PICTURE_BOX (box
, pDst
);
654 if (BOX_NOT_EMPTY(box
))
655 damageDamageBox (pDst
->pDrawable
, &box
, pDst
->subWindowMode
);
657 unwrap (pScrPriv
, ps
, Glyphs
);
658 (*ps
->Glyphs
) (op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, nlist
, list
, glyphs
);
659 damageReportPostOp (pDst
->pDrawable
);
660 wrap (pScrPriv
, ps
, Glyphs
, damageGlyphs
);
664 /**********************************************************/
668 damageFillSpans(DrawablePtr pDrawable
,
675 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
677 if (npt
&& checkGCDamage (pDrawable
, pGC
))
680 DDXPointPtr pptTmp
= ppt
;
681 int *pwidthTmp
= pwidth
;
685 box
.x2
= box
.x1
+ *pwidthTmp
;
686 box
.y2
= box
.y1
= pptTmp
->y
;
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
;
701 if(!pGC
->miTranslate
) {
702 TRANSLATE_BOX(box
, pDrawable
);
706 if(BOX_NOT_EMPTY(box
))
707 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
710 (*pGC
->ops
->FillSpans
)(pDrawable
, pGC
, npt
, ppt
, pwidth
, fSorted
);
712 damageReportPostOp (pDrawable
);
713 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
717 damageSetSpans(DrawablePtr pDrawable
,
725 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
727 if (npt
&& checkGCDamage (pDrawable
, pGC
))
729 DDXPointPtr pptTmp
= ppt
;
730 int *pwidthTmp
= pwidth
;
735 box
.x2
= box
.x1
+ *pwidthTmp
;
736 box
.y2
= box
.y1
= pptTmp
->y
;
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
;
751 if(!pGC
->miTranslate
) {
752 TRANSLATE_BOX(box
, pDrawable
);
756 if(BOX_NOT_EMPTY(box
))
757 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
759 (*pGC
->ops
->SetSpans
)(pDrawable
, pGC
, pcharsrc
, ppt
, pwidth
, npt
, fSorted
);
760 damageReportPostOp (pDrawable
);
761 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
765 damagePutImage(DrawablePtr pDrawable
,
776 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
777 if (checkGCDamage (pDrawable
, pGC
))
781 box
.x1
= x
+ pDrawable
->x
;
783 box
.y1
= y
+ pDrawable
->y
;
787 if(BOX_NOT_EMPTY(box
))
788 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
790 (*pGC
->ops
->PutImage
)(pDrawable
, pGC
, depth
, x
, y
, w
, h
,
791 leftPad
, format
, pImage
);
792 damageReportPostOp (pDrawable
);
793 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
797 damageCopyArea(DrawablePtr pSrc
,
808 DAMAGE_GC_OP_PROLOGUE(pGC
, pDst
);
810 /* The driver will only call SourceValidate() when pSrc != pDst,
811 * but the software sprite (misprite.c) always need to know when a
812 * drawable is copied so it can remove the sprite. See #1030. */
813 if ((pSrc
== pDst
) && pSrc
->pScreen
->SourceValidate
&&
814 pSrc
->type
== DRAWABLE_WINDOW
&&
815 ((WindowPtr
)pSrc
)->viewable
)
817 (*pSrc
->pScreen
->SourceValidate
) (pSrc
, srcx
, srcy
, width
, height
);
820 if (checkGCDamage (pDst
, pGC
))
824 box
.x1
= dstx
+ pDst
->x
;
825 box
.x2
= box
.x1
+ width
;
826 box
.y1
= dsty
+ pDst
->y
;
827 box
.y2
= box
.y1
+ height
;
830 if(BOX_NOT_EMPTY(box
))
831 damageDamageBox (pDst
, &box
, pGC
->subWindowMode
);
834 ret
= (*pGC
->ops
->CopyArea
)(pSrc
, pDst
,
835 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
);
836 damageReportPostOp (pDst
);
837 DAMAGE_GC_OP_EPILOGUE(pGC
, pDst
);
842 damageCopyPlane(DrawablePtr pSrc
,
851 unsigned long bitPlane
)
854 DAMAGE_GC_OP_PROLOGUE(pGC
, pDst
);
856 /* The driver will only call SourceValidate() when pSrc != pDst,
857 * but the software sprite (misprite.c) always need to know when a
858 * drawable is copied so it can remove the sprite. See #1030. */
859 if ((pSrc
== pDst
) && pSrc
->pScreen
->SourceValidate
&&
860 pSrc
->type
== DRAWABLE_WINDOW
&&
861 ((WindowPtr
)pSrc
)->viewable
)
863 (*pSrc
->pScreen
->SourceValidate
) (pSrc
, srcx
, srcy
, width
, height
);
866 if (checkGCDamage (pDst
, pGC
))
870 box
.x1
= dstx
+ pDst
->x
;
871 box
.x2
= box
.x1
+ width
;
872 box
.y1
= dsty
+ pDst
->y
;
873 box
.y2
= box
.y1
+ height
;
876 if(BOX_NOT_EMPTY(box
))
877 damageDamageBox (pDst
, &box
, pGC
->subWindowMode
);
880 ret
= (*pGC
->ops
->CopyPlane
)(pSrc
, pDst
,
881 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
, bitPlane
);
882 damageReportPostOp (pDst
);
883 DAMAGE_GC_OP_EPILOGUE(pGC
, pDst
);
888 damagePolyPoint(DrawablePtr pDrawable
,
894 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
896 if (npt
&& checkGCDamage (pDrawable
, pGC
))
900 xPoint
*pptTmp
= ppt
;
902 box
.x2
= box
.x1
= pptTmp
->x
;
903 box
.y2
= box
.y1
= pptTmp
->y
;
905 /* this could be slow if the points were spread out */
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
;
919 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
920 if(BOX_NOT_EMPTY(box
))
921 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
923 (*pGC
->ops
->PolyPoint
)(pDrawable
, pGC
, mode
, npt
, ppt
);
924 damageReportPostOp (pDrawable
);
925 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
929 damagePolylines(DrawablePtr pDrawable
,
935 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
937 if (npt
&& checkGCDamage (pDrawable
, pGC
))
940 DDXPointPtr pptTmp
= ppt
;
942 int extra
= pGC
->lineWidth
>> 1;
944 box
.x2
= box
.x1
= pptTmp
->x
;
945 box
.y2
= box
.y1
= pptTmp
->y
;
949 if(pGC
->joinStyle
== JoinMiter
)
950 extra
= 6 * pGC
->lineWidth
;
951 else if(pGC
->capStyle
== CapProjecting
)
952 extra
= pGC
->lineWidth
;
955 if(mode
== CoordModePrevious
)
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
;
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
;
993 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
994 if(BOX_NOT_EMPTY(box
))
995 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
997 (*pGC
->ops
->Polylines
)(pDrawable
, pGC
, mode
, npt
, ppt
);
998 damageReportPostOp (pDrawable
);
999 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1003 damagePolySegment(DrawablePtr pDrawable
,
1008 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1010 if (nSeg
&& checkGCDamage (pDrawable
, pGC
))
1013 int extra
= pGC
->lineWidth
;
1015 xSegment
*pSegTmp
= pSeg
;
1017 if(pGC
->capStyle
!= CapProjecting
)
1020 if(pSegTmp
->x2
> pSegTmp
->x1
) {
1021 box
.x1
= pSegTmp
->x1
;
1022 box
.x2
= pSegTmp
->x2
;
1024 box
.x2
= pSegTmp
->x1
;
1025 box
.x1
= pSegTmp
->x2
;
1028 if(pSegTmp
->y2
> pSegTmp
->y1
) {
1029 box
.y1
= pSegTmp
->y1
;
1030 box
.y2
= pSegTmp
->y2
;
1032 box
.y2
= pSegTmp
->y1
;
1033 box
.y1
= pSegTmp
->y2
;
1039 if(pSegTmp
->x2
> pSegTmp
->x1
)
1041 if(pSegTmp
->x1
< box
.x1
) box
.x1
= pSegTmp
->x1
;
1042 if(pSegTmp
->x2
> box
.x2
) box
.x2
= pSegTmp
->x2
;
1046 if(pSegTmp
->x2
< box
.x1
) box
.x1
= pSegTmp
->x2
;
1047 if(pSegTmp
->x1
> box
.x2
) box
.x2
= pSegTmp
->x1
;
1049 if(pSegTmp
->y2
> pSegTmp
->y1
)
1051 if(pSegTmp
->y1
< box
.y1
) box
.y1
= pSegTmp
->y1
;
1052 if(pSegTmp
->y2
> box
.y2
) box
.y2
= pSegTmp
->y2
;
1056 if(pSegTmp
->y2
< box
.y1
) box
.y1
= pSegTmp
->y2
;
1057 if(pSegTmp
->y1
> box
.y2
) box
.y2
= pSegTmp
->y1
;
1072 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1073 if(BOX_NOT_EMPTY(box
))
1074 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1076 (*pGC
->ops
->PolySegment
)(pDrawable
, pGC
, nSeg
, pSeg
);
1077 damageReportPostOp (pDrawable
);
1078 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1082 damagePolyRectangle(DrawablePtr pDrawable
,
1087 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1089 if (nRects
&& checkGCDamage (pDrawable
, pGC
))
1092 int offset1
, offset2
, offset3
;
1093 int nRectsTmp
= nRects
;
1094 xRectangle
*pRectsTmp
= pRects
;
1096 offset2
= pGC
->lineWidth
;
1097 if(!offset2
) offset2
= 1;
1098 offset1
= offset2
>> 1;
1099 offset3
= offset2
- offset1
;
1103 box
.x1
= pRectsTmp
->x
- offset1
;
1104 box
.y1
= pRectsTmp
->y
- offset1
;
1105 box
.x2
= box
.x1
+ pRectsTmp
->width
+ offset2
;
1106 box
.y2
= box
.y1
+ offset2
;
1107 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1108 if(BOX_NOT_EMPTY(box
))
1109 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1111 box
.x1
= pRectsTmp
->x
- offset1
;
1112 box
.y1
= pRectsTmp
->y
+ offset3
;
1113 box
.x2
= box
.x1
+ offset2
;
1114 box
.y2
= box
.y1
+ pRectsTmp
->height
- offset2
;
1115 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1116 if(BOX_NOT_EMPTY(box
))
1117 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1119 box
.x1
= pRectsTmp
->x
+ pRectsTmp
->width
- offset1
;
1120 box
.y1
= pRectsTmp
->y
+ offset3
;
1121 box
.x2
= box
.x1
+ offset2
;
1122 box
.y2
= box
.y1
+ pRectsTmp
->height
- offset2
;
1123 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1124 if(BOX_NOT_EMPTY(box
))
1125 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1127 box
.x1
= pRectsTmp
->x
- offset1
;
1128 box
.y1
= pRectsTmp
->y
+ pRectsTmp
->height
- offset1
;
1129 box
.x2
= box
.x1
+ pRectsTmp
->width
+ offset2
;
1130 box
.y2
= box
.y1
+ offset2
;
1131 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1132 if(BOX_NOT_EMPTY(box
))
1133 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1138 (*pGC
->ops
->PolyRectangle
)(pDrawable
, pGC
, nRects
, pRects
);
1139 damageReportPostOp (pDrawable
);
1140 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1144 damagePolyArc(DrawablePtr pDrawable
,
1149 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1151 if (nArcs
&& checkGCDamage (pDrawable
, pGC
))
1153 int extra
= pGC
->lineWidth
>> 1;
1155 int nArcsTmp
= nArcs
;
1156 xArc
*pArcsTmp
= pArcs
;
1158 box
.x1
= pArcsTmp
->x
;
1159 box
.x2
= box
.x1
+ pArcsTmp
->width
;
1160 box
.y1
= pArcsTmp
->y
;
1161 box
.y2
= box
.y1
+ pArcsTmp
->height
;
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
;
1187 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1188 if(BOX_NOT_EMPTY(box
))
1189 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1191 (*pGC
->ops
->PolyArc
)(pDrawable
, pGC
, nArcs
, pArcs
);
1192 damageReportPostOp (pDrawable
);
1193 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1197 damageFillPolygon(DrawablePtr pDrawable
,
1204 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1206 if (npt
> 2 && checkGCDamage (pDrawable
, pGC
))
1208 DDXPointPtr pptTmp
= ppt
;
1212 box
.x2
= box
.x1
= pptTmp
->x
;
1213 box
.y2
= box
.y1
= pptTmp
->y
;
1215 if(mode
!= CoordModeOrigin
)
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
;
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
;
1245 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1246 if(BOX_NOT_EMPTY(box
))
1247 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1250 (*pGC
->ops
->FillPolygon
)(pDrawable
, pGC
, shape
, mode
, npt
, ppt
);
1251 damageReportPostOp (pDrawable
);
1252 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1257 damagePolyFillRect(DrawablePtr pDrawable
,
1262 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1263 if (nRects
&& checkGCDamage (pDrawable
, pGC
))
1266 xRectangle
*pRectsTmp
= pRects
;
1267 int nRectsTmp
= nRects
;
1269 box
.x1
= pRectsTmp
->x
;
1270 box
.x2
= box
.x1
+ pRectsTmp
->width
;
1271 box
.y1
= pRectsTmp
->y
;
1272 box
.y2
= box
.y1
+ pRectsTmp
->height
;
1277 if(box
.x1
> pRectsTmp
->x
) box
.x1
= pRectsTmp
->x
;
1278 if(box
.x2
< (pRectsTmp
->x
+ pRectsTmp
->width
))
1279 box
.x2
= pRectsTmp
->x
+ pRectsTmp
->width
;
1280 if(box
.y1
> pRectsTmp
->y
) box
.y1
= pRectsTmp
->y
;
1281 if(box
.y2
< (pRectsTmp
->y
+ pRectsTmp
->height
))
1282 box
.y2
= pRectsTmp
->y
+ pRectsTmp
->height
;
1285 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1286 if(BOX_NOT_EMPTY(box
))
1287 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1289 (*pGC
->ops
->PolyFillRect
)(pDrawable
, pGC
, nRects
, pRects
);
1290 damageReportPostOp (pDrawable
);
1291 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1296 damagePolyFillArc(DrawablePtr pDrawable
,
1301 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1303 if (nArcs
&& checkGCDamage (pDrawable
, pGC
))
1306 int nArcsTmp
= nArcs
;
1307 xArc
*pArcsTmp
= pArcs
;
1309 box
.x1
= pArcsTmp
->x
;
1310 box
.x2
= box
.x1
+ pArcsTmp
->width
;
1311 box
.y1
= pArcsTmp
->y
;
1312 box
.y2
= box
.y1
+ pArcsTmp
->height
;
1317 if(box
.x1
> pArcsTmp
->x
)
1318 box
.x1
= pArcsTmp
->x
;
1319 if(box
.x2
< (pArcsTmp
->x
+ pArcsTmp
->width
))
1320 box
.x2
= pArcsTmp
->x
+ pArcsTmp
->width
;
1321 if(box
.y1
> pArcsTmp
->y
)
1322 box
.y1
= pArcsTmp
->y
;
1323 if(box
.y2
< (pArcsTmp
->y
+ pArcsTmp
->height
))
1324 box
.y2
= pArcsTmp
->y
+ pArcsTmp
->height
;
1327 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1328 if(BOX_NOT_EMPTY(box
))
1329 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1331 (*pGC
->ops
->PolyFillArc
)(pDrawable
, pGC
, nArcs
, pArcs
);
1332 damageReportPostOp (pDrawable
);
1333 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1337 * general Poly/Image text function. Extract glyph information,
1338 * compute bounding box and remove cursor if it is overlapped.
1342 damageDamageChars (DrawablePtr pDrawable
,
1347 CharInfoPtr
*charinfo
,
1351 ExtentInfoRec extents
;
1354 QueryGlyphExtents(font
, charinfo
, n
, &extents
);
1357 if (extents
.overallWidth
> extents
.overallRight
)
1358 extents
.overallRight
= extents
.overallWidth
;
1359 if (extents
.overallWidth
< extents
.overallLeft
)
1360 extents
.overallLeft
= extents
.overallWidth
;
1361 if (extents
.overallLeft
> 0)
1362 extents
.overallLeft
= 0;
1363 if (extents
.fontAscent
> extents
.overallAscent
)
1364 extents
.overallAscent
= extents
.fontAscent
;
1365 if (extents
.fontDescent
> extents
.overallDescent
)
1366 extents
.overallDescent
= extents
.fontDescent
;
1368 box
.x1
= x
+ extents
.overallLeft
;
1369 box
.y1
= y
- extents
.overallAscent
;
1370 box
.x2
= x
+ extents
.overallRight
;
1371 box
.y2
= y
+ extents
.overallDescent
;
1372 damageDamageBox (pDrawable
, &box
, subWindowMode
);
1376 * values for textType:
1381 #define TT_IMAGE16 3
1384 damageText (DrawablePtr pDrawable
,
1388 unsigned long count
,
1390 FontEncoding fontEncoding
,
1393 CharInfoPtr
*charinfo
;
1400 imageblt
= (textType
== TT_IMAGE8
) || (textType
== TT_IMAGE16
);
1402 charinfo
= (CharInfoPtr
*) ALLOCATE_LOCAL(count
* sizeof(CharInfoPtr
));
1406 GetGlyphs(pGC
->font
, count
, (unsigned char *)chars
,
1407 fontEncoding
, &i
, charinfo
);
1408 n
= (unsigned int)i
;
1411 for (info
= charinfo
; i
--; info
++)
1412 w
+= (*info
)->metrics
.characterWidth
;
1415 damageDamageChars (pDrawable
, pGC
->font
, x
+ pDrawable
->x
, y
+ pDrawable
->y
, n
,
1416 charinfo
, imageblt
, pGC
->subWindowMode
);
1418 (*pGC
->ops
->ImageGlyphBlt
)(pDrawable
, pGC
, x
, y
, n
, charinfo
,
1419 FONTGLYPHS(pGC
->font
));
1421 (*pGC
->ops
->PolyGlyphBlt
)(pDrawable
, pGC
, x
, y
, n
, charinfo
,
1422 FONTGLYPHS(pGC
->font
));
1424 DEALLOCATE_LOCAL(charinfo
);
1429 damagePolyText8(DrawablePtr pDrawable
,
1436 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1438 if (checkGCDamage (pDrawable
, pGC
))
1439 x
= damageText (pDrawable
, pGC
, x
, y
, (unsigned long) count
, chars
,
1440 Linear8Bit
, TT_POLY8
);
1442 x
= (*pGC
->ops
->PolyText8
)(pDrawable
, pGC
, x
, y
, count
, chars
);
1443 damageReportPostOp (pDrawable
);
1444 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1449 damagePolyText16(DrawablePtr pDrawable
,
1454 unsigned short *chars
)
1456 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1458 if (checkGCDamage (pDrawable
, pGC
))
1459 x
= damageText (pDrawable
, pGC
, x
, y
, (unsigned long) count
, (char *) chars
,
1460 FONTLASTROW(pGC
->font
) == 0 ? Linear16Bit
: TwoD16Bit
,
1463 x
= (*pGC
->ops
->PolyText16
)(pDrawable
, pGC
, x
, y
, count
, chars
);
1464 damageReportPostOp (pDrawable
);
1465 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1470 damageImageText8(DrawablePtr pDrawable
,
1477 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1479 if (checkGCDamage (pDrawable
, pGC
))
1480 damageText (pDrawable
, pGC
, x
, y
, (unsigned long) count
, chars
,
1481 Linear8Bit
, TT_IMAGE8
);
1483 (*pGC
->ops
->ImageText8
)(pDrawable
, pGC
, x
, y
, count
, chars
);
1484 damageReportPostOp (pDrawable
);
1485 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1489 damageImageText16(DrawablePtr pDrawable
,
1494 unsigned short *chars
)
1496 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1498 if (checkGCDamage (pDrawable
, pGC
))
1499 damageText (pDrawable
, pGC
, x
, y
, (unsigned long) count
, (char *) chars
,
1500 FONTLASTROW(pGC
->font
) == 0 ? Linear16Bit
: TwoD16Bit
,
1503 (*pGC
->ops
->ImageText16
)(pDrawable
, pGC
, x
, y
, count
, chars
);
1504 damageReportPostOp (pDrawable
);
1505 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1510 damageImageGlyphBlt(DrawablePtr pDrawable
,
1514 unsigned int nglyph
,
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
,
1523 damageReportPostOp (pDrawable
);
1524 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1528 damagePolyGlyphBlt(DrawablePtr pDrawable
,
1532 unsigned int nglyph
,
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
,
1541 damageReportPostOp (pDrawable
);
1542 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1546 damagePushPixels(GCPtr pGC
,
1548 DrawablePtr pDrawable
,
1554 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1555 if(checkGCDamage (pDrawable
, pGC
))
1562 if(!pGC
->miTranslate
) {
1563 box
.x1
+= pDrawable
->x
;
1564 box
.y1
+= pDrawable
->y
;
1567 box
.x2
= box
.x1
+ dx
;
1568 box
.y2
= box
.y1
+ dy
;
1571 if(BOX_NOT_EMPTY(box
))
1572 damageDamageBox (pDrawable
, &box
, pGC
->subWindowMode
);
1574 (*pGC
->ops
->PushPixels
)(pGC
, pBitMap
, pDrawable
, dx
, dy
, xOrg
, yOrg
);
1575 damageReportPostOp (pDrawable
);
1576 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1580 damageRemoveDamage (DamagePtr
*pPrev
, DamagePtr pDamage
)
1584 if (*pPrev
== pDamage
)
1586 *pPrev
= pDamage
->pNext
;
1589 pPrev
= &(*pPrev
)->pNext
;
1591 #if DAMAGE_VALIDATE_ENABLE
1592 ErrorF ("Damage not on list\n");
1598 damageInsertDamage (DamagePtr
*pPrev
, DamagePtr pDamage
)
1600 #if DAMAGE_VALIDATE_ENABLE
1603 for (pOld
= *pPrev
; pOld
; pOld
= pOld
->pNext
)
1604 if (pOld
== pDamage
) {
1605 ErrorF ("Damage already on list\n");
1609 pDamage
->pNext
= *pPrev
;
1614 damageDestroyPixmap (PixmapPtr pPixmap
)
1616 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
1617 damageScrPriv(pScreen
);
1619 if (pPixmap
->refcnt
== 1)
1621 DamagePtr
*pPrev
= getPixmapDamageRef (pPixmap
);
1624 while ((pDamage
= *pPrev
))
1626 damageRemoveDamage (pPrev
, pDamage
);
1627 if (!pDamage
->isWindow
)
1628 DamageDestroy (pDamage
);
1631 unwrap (pScrPriv
, pScreen
, DestroyPixmap
);
1632 (*pScreen
->DestroyPixmap
) (pPixmap
);
1633 wrap (pScrPriv
, pScreen
, DestroyPixmap
, damageDestroyPixmap
);
1638 damagePaintWindow(WindowPtr pWindow
,
1642 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1643 damageScrPriv(pScreen
);
1646 * Painting background none doesn't actually *do* anything, so
1647 * no damage is recorded
1649 if ((what
!= PW_BACKGROUND
|| pWindow
->backgroundState
!= None
) &&
1650 getWindowDamage (pWindow
))
1651 damageDamageRegion (&pWindow
->drawable
, prgn
, FALSE
, -1);
1652 if(what
== PW_BACKGROUND
) {
1653 unwrap (pScrPriv
, pScreen
, PaintWindowBackground
);
1654 (*pScreen
->PaintWindowBackground
) (pWindow
, prgn
, what
);
1655 damageReportPostOp (&pWindow
->drawable
);
1656 wrap (pScrPriv
, pScreen
, PaintWindowBackground
, damagePaintWindow
);
1658 unwrap (pScrPriv
, pScreen
, PaintWindowBorder
);
1659 (*pScreen
->PaintWindowBorder
) (pWindow
, prgn
, what
);
1660 damageReportPostOp (&pWindow
->drawable
);
1661 wrap (pScrPriv
, pScreen
, PaintWindowBorder
, damagePaintWindow
);
1667 damageCopyWindow(WindowPtr pWindow
,
1668 DDXPointRec ptOldOrg
,
1671 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1672 damageScrPriv(pScreen
);
1674 if (getWindowDamage (pWindow
))
1676 int dx
= pWindow
->drawable
.x
- ptOldOrg
.x
;
1677 int dy
= pWindow
->drawable
.y
- ptOldOrg
.y
;
1680 * The region comes in source relative, but the damage occurs
1681 * at the destination location. Translate back and forth.
1683 REGION_TRANSLATE (pScreen
, prgnSrc
, dx
, dy
);
1684 damageDamageRegion (&pWindow
->drawable
, prgnSrc
, FALSE
, -1);
1685 REGION_TRANSLATE (pScreen
, prgnSrc
, -dx
, -dy
);
1687 unwrap (pScrPriv
, pScreen
, CopyWindow
);
1688 (*pScreen
->CopyWindow
) (pWindow
, ptOldOrg
, prgnSrc
);
1689 damageReportPostOp (&pWindow
->drawable
);
1690 wrap (pScrPriv
, pScreen
, CopyWindow
, damageCopyWindow
);
1693 static GCOps damageGCOps
= {
1694 damageFillSpans
, damageSetSpans
,
1695 damagePutImage
, damageCopyArea
,
1696 damageCopyPlane
, damagePolyPoint
,
1697 damagePolylines
, damagePolySegment
,
1698 damagePolyRectangle
, damagePolyArc
,
1699 damageFillPolygon
, damagePolyFillRect
,
1700 damagePolyFillArc
, damagePolyText8
,
1701 damagePolyText16
, damageImageText8
,
1702 damageImageText16
, damageImageGlyphBlt
,
1703 damagePolyGlyphBlt
, damagePushPixels
,
1704 {NULL
} /* devPrivate */
1708 damageRestoreAreas (PixmapPtr pPixmap
,
1714 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1715 damageScrPriv(pScreen
);
1717 damageDamageRegion (&pWindow
->drawable
, prgn
, FALSE
, -1);
1718 unwrap (pScrPriv
, pScreen
, BackingStoreFuncs
.RestoreAreas
);
1719 (*pScreen
->BackingStoreFuncs
.RestoreAreas
) (pPixmap
, prgn
,
1720 xorg
, yorg
, pWindow
);
1721 damageReportPostOp (&pWindow
->drawable
);
1722 wrap (pScrPriv
, pScreen
, BackingStoreFuncs
.RestoreAreas
,
1723 damageRestoreAreas
);
1727 damageSetWindowPixmap (WindowPtr pWindow
, PixmapPtr pPixmap
)
1730 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1731 damageScrPriv(pScreen
);
1733 if ((pDamage
= damageGetWinPriv(pWindow
)))
1735 PixmapPtr pOldPixmap
= (*pScreen
->GetWindowPixmap
) (pWindow
);
1736 DamagePtr
*pPrev
= getPixmapDamageRef(pOldPixmap
);
1740 damageRemoveDamage (pPrev
, pDamage
);
1741 pDamage
= pDamage
->pNextWin
;
1744 unwrap (pScrPriv
, pScreen
, SetWindowPixmap
);
1745 (*pScreen
->SetWindowPixmap
) (pWindow
, pPixmap
);
1746 wrap (pScrPriv
, pScreen
, SetWindowPixmap
, damageSetWindowPixmap
);
1747 if ((pDamage
= damageGetWinPriv(pWindow
)))
1749 DamagePtr
*pPrev
= getPixmapDamageRef(pPixmap
);
1753 damageInsertDamage (pPrev
, pDamage
);
1754 pDamage
= pDamage
->pNextWin
;
1760 damageDestroyWindow (WindowPtr pWindow
)
1763 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1765 damageScrPriv(pScreen
);
1767 while ((pDamage
= damageGetWinPriv(pWindow
)))
1769 DamageUnregister (&pWindow
->drawable
, pDamage
);
1770 DamageDestroy (pDamage
);
1772 unwrap (pScrPriv
, pScreen
, DestroyWindow
);
1773 ret
= (*pScreen
->DestroyWindow
) (pWindow
);
1774 wrap (pScrPriv
, pScreen
, DestroyWindow
, damageDestroyWindow
);
1779 damageCloseScreen (int i
, ScreenPtr pScreen
)
1781 damageScrPriv(pScreen
);
1783 unwrap (pScrPriv
, pScreen
, DestroyPixmap
);
1784 unwrap (pScrPriv
, pScreen
, CreateGC
);
1785 unwrap (pScrPriv
, pScreen
, PaintWindowBackground
);
1786 unwrap (pScrPriv
, pScreen
, PaintWindowBorder
);
1787 unwrap (pScrPriv
, pScreen
, CopyWindow
);
1788 unwrap (pScrPriv
, pScreen
, CloseScreen
);
1789 unwrap (pScrPriv
, pScreen
, BackingStoreFuncs
.RestoreAreas
);
1791 return (*pScreen
->CloseScreen
) (i
, pScreen
);
1795 DamageSetup (ScreenPtr pScreen
)
1797 DamageScrPrivPtr pScrPriv
;
1799 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
1802 if (damageGeneration
!= serverGeneration
)
1804 damageScrPrivateIndex
= AllocateScreenPrivateIndex ();
1805 if (damageScrPrivateIndex
== -1)
1807 damageGCPrivateIndex
= AllocateGCPrivateIndex ();
1808 if (damageGCPrivateIndex
== -1)
1810 damagePixPrivateIndex
= AllocatePixmapPrivateIndex ();
1811 if (damagePixPrivateIndex
== -1)
1813 damageWinPrivateIndex
= AllocateWindowPrivateIndex ();
1814 if (damageWinPrivateIndex
== -1)
1816 damageGeneration
= serverGeneration
;
1818 if (pScreen
->devPrivates
[damageScrPrivateIndex
].ptr
)
1821 if (!AllocateGCPrivate (pScreen
, damageGCPrivateIndex
, sizeof (DamageGCPrivRec
)))
1823 if (!AllocatePixmapPrivate (pScreen
, damagePixPrivateIndex
, 0))
1825 if (!AllocateWindowPrivate (pScreen
, damageWinPrivateIndex
, 0))
1828 pScrPriv
= (DamageScrPrivPtr
) xalloc (sizeof (DamageScrPrivRec
));
1832 pScrPriv
->internalLevel
= 0;
1833 pScrPriv
->pScreenDamage
= 0;
1835 wrap (pScrPriv
, pScreen
, DestroyPixmap
, damageDestroyPixmap
);
1836 wrap (pScrPriv
, pScreen
, CreateGC
, damageCreateGC
);
1837 wrap (pScrPriv
, pScreen
, PaintWindowBackground
, damagePaintWindow
);
1838 wrap (pScrPriv
, pScreen
, PaintWindowBorder
, damagePaintWindow
);
1839 wrap (pScrPriv
, pScreen
, DestroyWindow
, damageDestroyWindow
);
1840 wrap (pScrPriv
, pScreen
, SetWindowPixmap
, damageSetWindowPixmap
);
1841 wrap (pScrPriv
, pScreen
, CopyWindow
, damageCopyWindow
);
1842 wrap (pScrPriv
, pScreen
, CloseScreen
, damageCloseScreen
);
1843 wrap (pScrPriv
, pScreen
, BackingStoreFuncs
.RestoreAreas
,
1844 damageRestoreAreas
);
1847 wrap (pScrPriv
, ps
, Glyphs
, damageGlyphs
);
1848 wrap (pScrPriv
, ps
, Composite
, damageComposite
);
1852 pScreen
->devPrivates
[damageScrPrivateIndex
].ptr
= (pointer
) pScrPriv
;
1857 DamageCreate (DamageReportFunc damageReport
,
1858 DamageDestroyFunc damageDestroy
,
1859 DamageReportLevel damageLevel
,
1866 pDamage
= xalloc (sizeof (DamageRec
));
1870 pDamage
->pNextWin
= 0;
1871 REGION_NULL(pScreen
, &pDamage
->damage
);
1872 REGION_NULL(pScreen
, &pDamage
->pendingDamage
);
1874 pDamage
->damageLevel
= damageLevel
;
1875 pDamage
->isInternal
= isInternal
;
1876 pDamage
->closure
= closure
;
1877 pDamage
->isWindow
= FALSE
;
1878 pDamage
->pDrawable
= 0;
1879 pDamage
->reportAfter
= FALSE
;
1881 pDamage
->damageReport
= damageReport
;
1882 pDamage
->damageDestroy
= damageDestroy
;
1887 DamageRegister (DrawablePtr pDrawable
,
1890 if (pDrawable
->type
== DRAWABLE_WINDOW
)
1892 WindowPtr pWindow
= (WindowPtr
) pDrawable
;
1893 winDamageRef(pWindow
);
1895 #if DAMAGE_VALIDATE_ENABLE
1898 for (pOld
= *pPrev
; pOld
; pOld
= pOld
->pNextWin
)
1899 if (pOld
== pDamage
) {
1900 ErrorF ("Damage already on window list\n");
1904 pDamage
->pNextWin
= *pPrev
;
1906 pDamage
->isWindow
= TRUE
;
1909 pDamage
->isWindow
= FALSE
;
1910 pDamage
->pDrawable
= pDrawable
;
1911 damageInsertDamage (getDrawableDamageRef (pDrawable
), pDamage
);
1915 DamageDrawInternal (ScreenPtr pScreen
, Bool enable
)
1917 damageScrPriv (pScreen
);
1919 pScrPriv
->internalLevel
+= enable
? 1 : -1;
1923 DamageUnregister (DrawablePtr pDrawable
,
1926 if (pDrawable
->type
== DRAWABLE_WINDOW
)
1928 WindowPtr pWindow
= (WindowPtr
) pDrawable
;
1929 winDamageRef (pWindow
);
1930 #if DAMAGE_VALIDATE_ENABLE
1936 if (*pPrev
== pDamage
)
1938 *pPrev
= pDamage
->pNextWin
;
1939 #if DAMAGE_VALIDATE_ENABLE
1944 pPrev
= &(*pPrev
)->pNextWin
;
1946 #if DAMAGE_VALIDATE_ENABLE
1948 ErrorF ("Damage not on window list\n");
1953 pDamage
->pDrawable
= 0;
1954 damageRemoveDamage (getDrawableDamageRef (pDrawable
), pDamage
);
1958 DamageDestroy (DamagePtr pDamage
)
1960 if (pDamage
->damageDestroy
)
1961 (*pDamage
->damageDestroy
) (pDamage
, pDamage
->closure
);
1962 REGION_UNINIT (pDamage
->pDrawable
->pScreen
, &pDamage
->damage
);
1963 REGION_UNINIT (pDamage
->pDrawable
->pScreen
, &pDamage
->pendingDamage
);
1968 DamageSubtract (DamagePtr pDamage
,
1969 const RegionPtr pRegion
)
1972 RegionRec pixmapClip
;
1973 DrawablePtr pDrawable
= pDamage
->pDrawable
;
1975 REGION_SUBTRACT (pDrawable
->pScreen
, &pDamage
->damage
, &pDamage
->damage
, pRegion
);
1978 if (pDrawable
->type
== DRAWABLE_WINDOW
)
1979 pClip
= &((WindowPtr
) pDrawable
)->borderClip
;
1984 box
.x1
= pDrawable
->x
;
1985 box
.y1
= pDrawable
->y
;
1986 box
.x2
= pDrawable
->x
+ pDrawable
->width
;
1987 box
.y2
= pDrawable
->y
+ pDrawable
->height
;
1988 REGION_INIT (pDrawable
->pScreen
, &pixmapClip
, &box
, 1);
1989 pClip
= &pixmapClip
;
1991 REGION_TRANSLATE (pDrawable
->pScreen
, &pDamage
->damage
, pDrawable
->x
, pDrawable
->y
);
1992 REGION_INTERSECT (pDrawable
->pScreen
, &pDamage
->damage
, &pDamage
->damage
, pClip
);
1993 REGION_TRANSLATE (pDrawable
->pScreen
, &pDamage
->damage
, -pDrawable
->x
, -pDrawable
->y
);
1994 if (pDrawable
->type
!= DRAWABLE_WINDOW
)
1995 REGION_UNINIT(pDrawable
->pScreen
, &pixmapClip
);
1997 return REGION_NOTEMPTY (pDrawable
->pScreen
, &pDamage
->damage
);
2001 DamageEmpty (DamagePtr pDamage
)
2003 REGION_EMPTY (pDamage
->pDrawable
->pScreen
, &pDamage
->damage
);
2007 DamageRegion (DamagePtr pDamage
)
2009 return &pDamage
->damage
;
2013 DamageDamageRegion (DrawablePtr pDrawable
,
2016 damageDamageRegion (pDrawable
, pRegion
, FALSE
, -1);
2018 /* Go back and report this damage for DamagePtrs with reportAfter set, since
2019 * this call isn't part of an in-progress drawing op in the call chain and
2020 * the DDX probably just wants to know about it right away.
2022 damageReportPostOp (pDrawable
);
2026 DamageSetReportAfterOp (DamagePtr pDamage
, Bool reportAfter
)
2028 pDamage
->reportAfter
= reportAfter
;