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"
42 #define wrap(priv, real, mem, func) {\
43 priv->mem = real->mem; \
47 #define unwrap(priv, real, mem) {\
48 real->mem = priv->mem; \
51 #define BOX_SAME(a,b) \
52 ((a)->x1 == (b)->x1 && \
53 (a)->y1 == (b)->y1 && \
54 (a)->x2 == (b)->x2 && \
57 #define DAMAGE_VALIDATE_ENABLE 0
58 #define DAMAGE_DEBUG_ENABLE 0
59 #if DAMAGE_DEBUG_ENABLE
60 #define DAMAGE_DEBUG(x) ErrorF x
62 #define DAMAGE_DEBUG(x)
65 #define getPixmapDamageRef(pPixmap) ((DamagePtr *) \
66 dixLookupPrivateAddr(&(pPixmap)->devPrivates, damagePixPrivateKey))
68 #define pixmapDamage(pPixmap) damagePixPriv(pPixmap)
70 static DevPrivateKeyRec damageScrPrivateKeyRec
;
72 #define damageScrPrivateKey (&damageScrPrivateKeyRec)
73 static DevPrivateKeyRec damagePixPrivateKeyRec
;
75 #define damagePixPrivateKey (&damagePixPrivateKeyRec)
76 static DevPrivateKeyRec damageGCPrivateKeyRec
;
78 #define damageGCPrivateKey (&damageGCPrivateKeyRec)
79 static DevPrivateKeyRec damageWinPrivateKeyRec
;
81 #define damageWinPrivateKey (&damageWinPrivateKeyRec)
84 getDrawableDamageRef(DrawablePtr pDrawable
)
88 if (WindowDrawable(pDrawable
->type
)) {
89 ScreenPtr pScreen
= pDrawable
->pScreen
;
92 if (pScreen
->GetWindowPixmap
93 #ifdef ROOTLESS_WORKAROUND
94 && ((WindowPtr
) pDrawable
)->viewable
97 pPixmap
= (*pScreen
->GetWindowPixmap
) ((WindowPtr
) pDrawable
);
100 damageScrPriv(pScreen
);
102 return &pScrPriv
->pScreenDamage
;
106 pPixmap
= (PixmapPtr
) pDrawable
;
107 return getPixmapDamageRef(pPixmap
);
110 #define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable))
111 #define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable)
113 #define drawableDamage(pDrawable) \
114 DamagePtr pDamage = getDrawableDamage(pDrawable)
116 #define windowDamage(pWin) drawableDamage(&(pWin)->drawable)
118 #define winDamageRef(pWindow) \
119 DamagePtr *pPrev = (DamagePtr *) \
120 dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey)
122 #if DAMAGE_DEBUG_ENABLE
124 _damageRegionAppend(DrawablePtr pDrawable
, RegionPtr pRegion
, Bool clip
,
125 int subWindowMode
, const char *where
)
126 #define damageRegionAppend(d,r,c,m) _damageRegionAppend(d,r,c,m,__FUNCTION__)
129 damageRegionAppend(DrawablePtr pDrawable
, RegionPtr pRegion
, Bool clip
,
133 ScreenPtr pScreen
= pDrawable
->pScreen
;
135 damageScrPriv(pScreen
);
136 drawableDamage(pDrawable
);
138 RegionRec clippedRec
;
139 RegionPtr pDamageRegion
;
144 int screen_x
= 0, screen_y
= 0;
147 /* short circuit for empty regions */
148 if (!RegionNotEmpty(pRegion
))
153 * When drawing to a pixmap which is storing window contents,
154 * the region presented is in pixmap relative coordinates which
155 * need to be converted to screen relative coordinates
157 if (pDrawable
->type
!= DRAWABLE_WINDOW
) {
158 screen_x
= ((PixmapPtr
) pDrawable
)->screen_x
- pDrawable
->x
;
159 screen_y
= ((PixmapPtr
) pDrawable
)->screen_y
- pDrawable
->y
;
161 if (screen_x
|| screen_y
)
162 RegionTranslate(pRegion
, screen_x
, screen_y
);
165 if (pDrawable
->type
== DRAWABLE_WINDOW
&&
166 ((WindowPtr
) (pDrawable
))->backingStore
== NotUseful
) {
167 if (subWindowMode
== ClipByChildren
) {
168 RegionIntersect(pRegion
, pRegion
,
169 &((WindowPtr
) (pDrawable
))->clipList
);
171 else if (subWindowMode
== IncludeInferiors
) {
172 RegionPtr pTempRegion
=
173 NotClippedByChildren((WindowPtr
) (pDrawable
));
174 RegionIntersect(pRegion
, pRegion
, pTempRegion
);
175 RegionDestroy(pTempRegion
);
177 /* If subWindowMode is set to an invalid value, don't perform
178 * any drawable-based clipping. */
181 RegionNull(&clippedRec
);
182 for (; pDamage
; pDamage
= pNext
) {
183 pNext
= pDamage
->pNext
;
185 * Check for internal damage and don't send events
187 if (pScrPriv
->internalLevel
> 0 && !pDamage
->isInternal
) {
188 DAMAGE_DEBUG(("non internal damage, skipping at %d\n",
189 pScrPriv
->internalLevel
));
193 * Check for unrealized windows
195 if (pDamage
->pDrawable
->type
== DRAWABLE_WINDOW
&&
196 !((WindowPtr
) (pDamage
->pDrawable
))->realized
) {
200 draw_x
= pDamage
->pDrawable
->x
;
201 draw_y
= pDamage
->pDrawable
->y
;
204 * Need to move everyone to screen coordinates
205 * XXX what about off-screen pixmaps with non-zero x/y?
207 if (!WindowDrawable(pDamage
->pDrawable
->type
)) {
208 draw_x
+= ((PixmapPtr
) pDamage
->pDrawable
)->screen_x
;
209 draw_y
+= ((PixmapPtr
) pDamage
->pDrawable
)->screen_y
;
214 * Clip against border or pixmap bounds
217 pDamageRegion
= pRegion
;
218 if (clip
|| pDamage
->pDrawable
!= pDrawable
) {
219 pDamageRegion
= &clippedRec
;
220 if (pDamage
->pDrawable
->type
== DRAWABLE_WINDOW
) {
221 RegionIntersect(pDamageRegion
, pRegion
,
222 &((WindowPtr
) (pDamage
->pDrawable
))->
230 box
.x2
= draw_x
+ pDamage
->pDrawable
->width
;
231 box
.y2
= draw_y
+ pDamage
->pDrawable
->height
;
232 RegionInit(&pixClip
, &box
, 1);
233 RegionIntersect(pDamageRegion
, pRegion
, &pixClip
);
234 RegionUninit(&pixClip
);
237 * Short circuit empty results
239 if (!RegionNotEmpty(pDamageRegion
))
243 DAMAGE_DEBUG(("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
245 pDamageRegion
->extents
.x2
- pDamageRegion
->extents
.x1
,
246 pDamageRegion
->extents
.y2
- pDamageRegion
->extents
.y1
,
247 pDamageRegion
->extents
.x1
, pDamageRegion
->extents
.y1
,
248 pDrawable
->id
, pDamage
->pDrawable
->id
));
251 * Move region to target coordinate space
253 if (draw_x
|| draw_y
)
254 RegionTranslate(pDamageRegion
, -draw_x
, -draw_y
);
256 /* Store damage region if needed after submission. */
257 if (pDamage
->reportAfter
)
258 RegionUnion(&pDamage
->pendingDamage
,
259 &pDamage
->pendingDamage
, pDamageRegion
);
261 /* Report damage now, if desired. */
262 if (!pDamage
->reportAfter
) {
263 if (pDamage
->damageReport
)
264 DamageReportDamage(pDamage
, pDamageRegion
);
266 RegionUnion(&pDamage
->damage
, &pDamage
->damage
, pDamageRegion
);
270 * translate original region back
272 if (pDamageRegion
== pRegion
&& (draw_x
|| draw_y
))
273 RegionTranslate(pDamageRegion
, draw_x
, draw_y
);
276 if (screen_x
|| screen_y
)
277 RegionTranslate(pRegion
, -screen_x
, -screen_y
);
280 RegionUninit(&clippedRec
);
284 damageRegionProcessPending(DrawablePtr pDrawable
)
286 drawableDamage(pDrawable
);
288 for (; pDamage
!= NULL
; pDamage
= pDamage
->pNext
) {
289 if (pDamage
->reportAfter
) {
290 /* It's possible that there is only interest in postRendering reporting. */
291 if (pDamage
->damageReport
)
292 DamageReportDamage(pDamage
, &pDamage
->pendingDamage
);
294 RegionUnion(&pDamage
->damage
, &pDamage
->damage
,
295 &pDamage
->pendingDamage
);
298 if (pDamage
->reportAfter
)
299 RegionEmpty(&pDamage
->pendingDamage
);
304 #if DAMAGE_DEBUG_ENABLE
305 #define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
307 _damageDamageBox(DrawablePtr pDrawable
, BoxPtr pBox
, int subWindowMode
,
311 damageDamageBox(DrawablePtr pDrawable
, BoxPtr pBox
, int subWindowMode
)
316 RegionInit(®ion
, pBox
, 1);
317 #if DAMAGE_DEBUG_ENABLE
318 _damageRegionAppend(pDrawable
, ®ion
, TRUE
, subWindowMode
, where
);
320 damageRegionAppend(pDrawable
, ®ion
, TRUE
, subWindowMode
);
322 RegionUninit(®ion
);
325 static void damageValidateGC(GCPtr
, unsigned long, DrawablePtr
);
326 static void damageChangeGC(GCPtr
, unsigned long);
327 static void damageCopyGC(GCPtr
, unsigned long, GCPtr
);
328 static void damageDestroyGC(GCPtr
);
329 static void damageChangeClip(GCPtr
, int, pointer
, int);
330 static void damageDestroyClip(GCPtr
);
331 static void damageCopyClip(GCPtr
, GCPtr
);
333 static GCFuncs damageGCFuncs
= {
334 damageValidateGC
, damageChangeGC
, damageCopyGC
, damageDestroyGC
,
335 damageChangeClip
, damageDestroyClip
, damageCopyClip
338 static GCOps damageGCOps
;
341 damageCreateGC(GCPtr pGC
)
343 ScreenPtr pScreen
= pGC
->pScreen
;
345 damageScrPriv(pScreen
);
349 unwrap(pScrPriv
, pScreen
, CreateGC
);
350 if ((ret
= (*pScreen
->CreateGC
) (pGC
))) {
352 pGCPriv
->funcs
= pGC
->funcs
;
353 pGC
->funcs
= &damageGCFuncs
;
355 wrap(pScrPriv
, pScreen
, CreateGC
, damageCreateGC
);
360 #define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
362 GCFuncs *oldFuncs = pGC->funcs; \
363 unwrap(pGCPriv, pGC, funcs); \
364 unwrap(pGCPriv, pGC, ops); \
366 #define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
367 wrap(pGCPriv, pGC, funcs, oldFuncs); \
368 wrap(pGCPriv, pGC, ops, &damageGCOps)
370 #define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
372 unwrap(pGCPriv, pGC, funcs); \
373 if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
375 #define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
376 wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \
377 if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
380 damageValidateGC(GCPtr pGC
, unsigned long changes
, DrawablePtr pDrawable
)
382 drawableDamage(pDrawable
);
383 DAMAGE_GC_FUNC_PROLOGUE(pGC
);
384 (*pGC
->funcs
->ValidateGC
) (pGC
, changes
, pDrawable
);
385 pGCPriv
->ops
= pGC
->ops
; /* just so it's not NULL */
386 DAMAGE_GC_FUNC_EPILOGUE(pGC
);
390 damageDestroyGC(GCPtr pGC
)
392 DAMAGE_GC_FUNC_PROLOGUE(pGC
);
393 (*pGC
->funcs
->DestroyGC
) (pGC
);
394 DAMAGE_GC_FUNC_EPILOGUE(pGC
);
398 damageChangeGC(GCPtr pGC
, unsigned long mask
)
400 DAMAGE_GC_FUNC_PROLOGUE(pGC
);
401 (*pGC
->funcs
->ChangeGC
) (pGC
, mask
);
402 DAMAGE_GC_FUNC_EPILOGUE(pGC
);
406 damageCopyGC(GCPtr pGCSrc
, unsigned long mask
, GCPtr pGCDst
)
408 DAMAGE_GC_FUNC_PROLOGUE(pGCDst
);
409 (*pGCDst
->funcs
->CopyGC
) (pGCSrc
, mask
, pGCDst
);
410 DAMAGE_GC_FUNC_EPILOGUE(pGCDst
);
414 damageChangeClip(GCPtr pGC
, int type
, pointer pvalue
, int nrects
)
416 DAMAGE_GC_FUNC_PROLOGUE(pGC
);
417 (*pGC
->funcs
->ChangeClip
) (pGC
, type
, pvalue
, nrects
);
418 DAMAGE_GC_FUNC_EPILOGUE(pGC
);
422 damageCopyClip(GCPtr pgcDst
, GCPtr pgcSrc
)
424 DAMAGE_GC_FUNC_PROLOGUE(pgcDst
);
425 (*pgcDst
->funcs
->CopyClip
) (pgcDst
, pgcSrc
);
426 DAMAGE_GC_FUNC_EPILOGUE(pgcDst
);
430 damageDestroyClip(GCPtr pGC
)
432 DAMAGE_GC_FUNC_PROLOGUE(pGC
);
433 (*pGC
->funcs
->DestroyClip
) (pGC
);
434 DAMAGE_GC_FUNC_EPILOGUE(pGC
);
437 #define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
438 BoxPtr extents = &pGC->pCompositeClip->extents;\
439 if(box.x1 < extents->x1) box.x1 = extents->x1; \
440 if(box.x2 > extents->x2) box.x2 = extents->x2; \
441 if(box.y1 < extents->y1) box.y1 = extents->y1; \
442 if(box.y2 > extents->y2) box.y2 = extents->y2; \
445 #define TRANSLATE_BOX(box, pDrawable) { \
446 box.x1 += pDrawable->x; \
447 box.x2 += pDrawable->x; \
448 box.y1 += pDrawable->y; \
449 box.y2 += pDrawable->y; \
452 #define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
453 TRANSLATE_BOX(box, pDrawable); \
454 TRIM_BOX(box, pGC); \
457 #define BOX_NOT_EMPTY(box) \
458 (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
460 #define checkGCDamage(d,g) (getDrawableDamage(d) && \
461 (!g->pCompositeClip ||\
462 RegionNotEmpty(g->pCompositeClip)))
464 #define TRIM_PICTURE_BOX(box, pDst) { \
465 BoxPtr extents = &pDst->pCompositeClip->extents;\
466 if(box.x1 < extents->x1) box.x1 = extents->x1; \
467 if(box.x2 > extents->x2) box.x2 = extents->x2; \
468 if(box.y1 < extents->y1) box.y1 = extents->y1; \
469 if(box.y2 > extents->y2) box.y2 = extents->y2; \
472 #define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \
473 RegionNotEmpty(p->pCompositeClip))
476 damageComposite(CARD8 op
,
484 INT16 xDst
, INT16 yDst
, CARD16 width
, CARD16 height
)
486 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
487 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
489 damageScrPriv(pScreen
);
491 if (checkPictureDamage(pDst
)) {
494 box
.x1
= xDst
+ pDst
->pDrawable
->x
;
495 box
.y1
= yDst
+ pDst
->pDrawable
->y
;
496 box
.x2
= box
.x1
+ width
;
497 box
.y2
= box
.y1
+ height
;
498 TRIM_PICTURE_BOX(box
, pDst
);
499 if (BOX_NOT_EMPTY(box
))
500 damageDamageBox(pDst
->pDrawable
, &box
, pDst
->subWindowMode
);
502 unwrap(pScrPriv
, ps
, Composite
);
503 (*ps
->Composite
) (op
,
507 xSrc
, ySrc
, xMask
, yMask
, xDst
, yDst
, width
, height
);
508 damageRegionProcessPending(pDst
->pDrawable
);
509 wrap(pScrPriv
, ps
, Composite
, damageComposite
);
513 damageGlyphs(CARD8 op
,
516 PictFormatPtr maskFormat
,
518 INT16 ySrc
, int nlist
, GlyphListPtr list
, GlyphPtr
* glyphs
)
520 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
521 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
523 damageScrPriv(pScreen
);
525 if (checkPictureDamage(pDst
)) {
526 int nlistTmp
= nlist
;
527 GlyphListPtr listTmp
= list
;
528 GlyphPtr
*glyphsTmp
= glyphs
;
539 x
= pDst
->pDrawable
->x
;
540 y
= pDst
->pDrawable
->y
;
546 glyph
= *glyphsTmp
++;
547 x1
= x
- glyph
->info
.x
;
548 y1
= y
- glyph
->info
.y
;
549 x2
= x1
+ glyph
->info
.width
;
550 y2
= y1
+ glyph
->info
.height
;
559 x
+= glyph
->info
.xOff
;
560 y
+= glyph
->info
.yOff
;
564 TRIM_PICTURE_BOX(box
, pDst
);
565 if (BOX_NOT_EMPTY(box
))
566 damageDamageBox(pDst
->pDrawable
, &box
, pDst
->subWindowMode
);
568 unwrap(pScrPriv
, ps
, Glyphs
);
569 (*ps
->Glyphs
) (op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, nlist
, list
, glyphs
);
570 damageRegionProcessPending(pDst
->pDrawable
);
571 wrap(pScrPriv
, ps
, Glyphs
, damageGlyphs
);
575 damageAddTraps(PicturePtr pPicture
,
576 INT16 x_off
, INT16 y_off
, int ntrap
, xTrap
* traps
)
578 ScreenPtr pScreen
= pPicture
->pDrawable
->pScreen
;
579 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
581 damageScrPriv(pScreen
);
583 if (checkPictureDamage(pPicture
)) {
593 x
= pPicture
->pDrawable
->x
+ x_off
;
594 y
= pPicture
->pDrawable
->y
+ y_off
;
595 for (i
= 0; i
< ntrap
; i
++) {
596 pixman_fixed_t l
= min(t
->top
.l
, t
->bot
.l
);
597 pixman_fixed_t r
= max(t
->top
.r
, t
->bot
.r
);
598 int x1
= x
+ pixman_fixed_to_int(l
);
599 int x2
= x
+ pixman_fixed_to_int(pixman_fixed_ceil(r
));
600 int y1
= y
+ pixman_fixed_to_int(t
->top
.y
);
601 int y2
= y
+ pixman_fixed_to_int(pixman_fixed_ceil(t
->bot
.y
));
612 TRIM_PICTURE_BOX(box
, pPicture
);
613 if (BOX_NOT_EMPTY(box
))
614 damageDamageBox(pPicture
->pDrawable
, &box
, pPicture
->subWindowMode
);
616 unwrap(pScrPriv
, ps
, AddTraps
);
617 (*ps
->AddTraps
) (pPicture
, x_off
, y_off
, ntrap
, traps
);
618 damageRegionProcessPending(pPicture
->pDrawable
);
619 wrap(pScrPriv
, ps
, AddTraps
, damageAddTraps
);
622 /**********************************************************/
625 damageFillSpans(DrawablePtr pDrawable
,
626 GC
* pGC
, int npt
, DDXPointPtr ppt
, int *pwidth
, int fSorted
)
628 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
630 if (npt
&& checkGCDamage(pDrawable
, pGC
)) {
632 DDXPointPtr pptTmp
= ppt
;
633 int *pwidthTmp
= pwidth
;
637 box
.x2
= box
.x1
+ *pwidthTmp
;
638 box
.y2
= box
.y1
= pptTmp
->y
;
643 if (box
.x1
> pptTmp
->x
)
645 if (box
.x2
< (pptTmp
->x
+ *pwidthTmp
))
646 box
.x2
= pptTmp
->x
+ *pwidthTmp
;
647 if (box
.y1
> pptTmp
->y
)
649 else if (box
.y2
< pptTmp
->y
)
655 if (!pGC
->miTranslate
) {
656 TRANSLATE_BOX(box
, pDrawable
);
660 if (BOX_NOT_EMPTY(box
))
661 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
664 (*pGC
->ops
->FillSpans
) (pDrawable
, pGC
, npt
, ppt
, pwidth
, fSorted
);
666 damageRegionProcessPending(pDrawable
);
667 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
671 damageSetSpans(DrawablePtr pDrawable
,
674 DDXPointPtr ppt
, int *pwidth
, int npt
, int fSorted
)
676 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
678 if (npt
&& checkGCDamage(pDrawable
, pGC
)) {
679 DDXPointPtr pptTmp
= ppt
;
680 int *pwidthTmp
= pwidth
;
685 box
.x2
= box
.x1
+ *pwidthTmp
;
686 box
.y2
= box
.y1
= pptTmp
->y
;
691 if (box
.x1
> pptTmp
->x
)
693 if (box
.x2
< (pptTmp
->x
+ *pwidthTmp
))
694 box
.x2
= pptTmp
->x
+ *pwidthTmp
;
695 if (box
.y1
> pptTmp
->y
)
697 else if (box
.y2
< pptTmp
->y
)
703 if (!pGC
->miTranslate
) {
704 TRANSLATE_BOX(box
, pDrawable
);
708 if (BOX_NOT_EMPTY(box
))
709 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
711 (*pGC
->ops
->SetSpans
) (pDrawable
, pGC
, pcharsrc
, ppt
, pwidth
, npt
, fSorted
);
712 damageRegionProcessPending(pDrawable
);
713 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
717 damagePutImage(DrawablePtr pDrawable
,
721 int y
, int w
, int h
, int leftPad
, int format
, char *pImage
)
723 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
724 if (checkGCDamage(pDrawable
, pGC
)) {
727 box
.x1
= x
+ pDrawable
->x
;
729 box
.y1
= y
+ pDrawable
->y
;
733 if (BOX_NOT_EMPTY(box
))
734 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
736 (*pGC
->ops
->PutImage
) (pDrawable
, pGC
, depth
, x
, y
, w
, h
,
737 leftPad
, format
, pImage
);
738 damageRegionProcessPending(pDrawable
);
739 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
743 damageCopyArea(DrawablePtr pSrc
,
746 int srcx
, int srcy
, int width
, int height
, int dstx
, int dsty
)
750 DAMAGE_GC_OP_PROLOGUE(pGC
, pDst
);
752 if (checkGCDamage(pDst
, pGC
)) {
755 box
.x1
= dstx
+ pDst
->x
;
756 box
.x2
= box
.x1
+ width
;
757 box
.y1
= dsty
+ pDst
->y
;
758 box
.y2
= box
.y1
+ height
;
761 if (BOX_NOT_EMPTY(box
))
762 damageDamageBox(pDst
, &box
, pGC
->subWindowMode
);
765 ret
= (*pGC
->ops
->CopyArea
) (pSrc
, pDst
,
766 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
);
767 damageRegionProcessPending(pDst
);
768 DAMAGE_GC_OP_EPILOGUE(pGC
, pDst
);
773 damageCopyPlane(DrawablePtr pSrc
,
779 int height
, int dstx
, int dsty
, unsigned long bitPlane
)
783 DAMAGE_GC_OP_PROLOGUE(pGC
, pDst
);
785 if (checkGCDamage(pDst
, pGC
)) {
788 box
.x1
= dstx
+ pDst
->x
;
789 box
.x2
= box
.x1
+ width
;
790 box
.y1
= dsty
+ pDst
->y
;
791 box
.y2
= box
.y1
+ height
;
794 if (BOX_NOT_EMPTY(box
))
795 damageDamageBox(pDst
, &box
, pGC
->subWindowMode
);
798 ret
= (*pGC
->ops
->CopyPlane
) (pSrc
, pDst
,
799 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
,
801 damageRegionProcessPending(pDst
);
802 DAMAGE_GC_OP_EPILOGUE(pGC
, pDst
);
807 damagePolyPoint(DrawablePtr pDrawable
,
808 GCPtr pGC
, int mode
, int npt
, xPoint
* ppt
)
810 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
812 if (npt
&& checkGCDamage(pDrawable
, pGC
)) {
815 xPoint
*pptTmp
= ppt
;
817 box
.x2
= box
.x1
= pptTmp
->x
;
818 box
.y2
= box
.y1
= pptTmp
->y
;
820 /* this could be slow if the points were spread out */
824 if (box
.x1
> pptTmp
->x
)
826 else if (box
.x2
< pptTmp
->x
)
828 if (box
.y1
> pptTmp
->y
)
830 else if (box
.y2
< pptTmp
->y
)
837 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
838 if (BOX_NOT_EMPTY(box
))
839 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
841 (*pGC
->ops
->PolyPoint
) (pDrawable
, pGC
, mode
, npt
, ppt
);
842 damageRegionProcessPending(pDrawable
);
843 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
847 damagePolylines(DrawablePtr pDrawable
,
848 GCPtr pGC
, int mode
, int npt
, DDXPointPtr ppt
)
850 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
852 if (npt
&& checkGCDamage(pDrawable
, pGC
)) {
854 DDXPointPtr pptTmp
= ppt
;
856 int extra
= pGC
->lineWidth
>> 1;
858 box
.x2
= box
.x1
= pptTmp
->x
;
859 box
.y2
= box
.y1
= pptTmp
->y
;
862 if (pGC
->joinStyle
== JoinMiter
)
863 extra
= 6 * pGC
->lineWidth
;
864 else if (pGC
->capStyle
== CapProjecting
)
865 extra
= pGC
->lineWidth
;
868 if (mode
== CoordModePrevious
) {
889 if (box
.x1
> pptTmp
->x
)
891 else if (box
.x2
< pptTmp
->x
)
893 if (box
.y1
> pptTmp
->y
)
895 else if (box
.y2
< pptTmp
->y
)
910 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
911 if (BOX_NOT_EMPTY(box
))
912 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
914 (*pGC
->ops
->Polylines
) (pDrawable
, pGC
, mode
, npt
, ppt
);
915 damageRegionProcessPending(pDrawable
);
916 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
920 damagePolySegment(DrawablePtr pDrawable
, GCPtr pGC
, int nSeg
, xSegment
* pSeg
)
922 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
924 if (nSeg
&& checkGCDamage(pDrawable
, pGC
)) {
926 int extra
= pGC
->lineWidth
;
928 xSegment
*pSegTmp
= pSeg
;
930 if (pGC
->capStyle
!= CapProjecting
)
933 if (pSegTmp
->x2
> pSegTmp
->x1
) {
934 box
.x1
= pSegTmp
->x1
;
935 box
.x2
= pSegTmp
->x2
;
938 box
.x2
= pSegTmp
->x1
;
939 box
.x1
= pSegTmp
->x2
;
942 if (pSegTmp
->y2
> pSegTmp
->y1
) {
943 box
.y1
= pSegTmp
->y1
;
944 box
.y2
= pSegTmp
->y2
;
947 box
.y2
= pSegTmp
->y1
;
948 box
.y1
= pSegTmp
->y2
;
953 if (pSegTmp
->x2
> pSegTmp
->x1
) {
954 if (pSegTmp
->x1
< box
.x1
)
955 box
.x1
= pSegTmp
->x1
;
956 if (pSegTmp
->x2
> box
.x2
)
957 box
.x2
= pSegTmp
->x2
;
960 if (pSegTmp
->x2
< box
.x1
)
961 box
.x1
= pSegTmp
->x2
;
962 if (pSegTmp
->x1
> box
.x2
)
963 box
.x2
= pSegTmp
->x1
;
965 if (pSegTmp
->y2
> pSegTmp
->y1
) {
966 if (pSegTmp
->y1
< box
.y1
)
967 box
.y1
= pSegTmp
->y1
;
968 if (pSegTmp
->y2
> box
.y2
)
969 box
.y2
= pSegTmp
->y2
;
972 if (pSegTmp
->y2
< box
.y1
)
973 box
.y1
= pSegTmp
->y2
;
974 if (pSegTmp
->y1
> box
.y2
)
975 box
.y2
= pSegTmp
->y1
;
989 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
990 if (BOX_NOT_EMPTY(box
))
991 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
993 (*pGC
->ops
->PolySegment
) (pDrawable
, pGC
, nSeg
, pSeg
);
994 damageRegionProcessPending(pDrawable
);
995 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
999 damagePolyRectangle(DrawablePtr pDrawable
,
1000 GCPtr pGC
, int nRects
, xRectangle
*pRects
)
1002 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1004 if (nRects
&& checkGCDamage(pDrawable
, pGC
)) {
1006 int offset1
, offset2
, offset3
;
1007 int nRectsTmp
= nRects
;
1008 xRectangle
*pRectsTmp
= pRects
;
1010 offset2
= pGC
->lineWidth
;
1013 offset1
= offset2
>> 1;
1014 offset3
= offset2
- offset1
;
1016 while (nRectsTmp
--) {
1017 box
.x1
= pRectsTmp
->x
- offset1
;
1018 box
.y1
= pRectsTmp
->y
- offset1
;
1019 box
.x2
= box
.x1
+ pRectsTmp
->width
+ offset2
;
1020 box
.y2
= box
.y1
+ offset2
;
1021 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1022 if (BOX_NOT_EMPTY(box
))
1023 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1025 box
.x1
= pRectsTmp
->x
- offset1
;
1026 box
.y1
= pRectsTmp
->y
+ offset3
;
1027 box
.x2
= box
.x1
+ offset2
;
1028 box
.y2
= box
.y1
+ pRectsTmp
->height
- offset2
;
1029 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1030 if (BOX_NOT_EMPTY(box
))
1031 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1033 box
.x1
= pRectsTmp
->x
+ pRectsTmp
->width
- offset1
;
1034 box
.y1
= pRectsTmp
->y
+ offset3
;
1035 box
.x2
= box
.x1
+ offset2
;
1036 box
.y2
= box
.y1
+ pRectsTmp
->height
- offset2
;
1037 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1038 if (BOX_NOT_EMPTY(box
))
1039 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1041 box
.x1
= pRectsTmp
->x
- offset1
;
1042 box
.y1
= pRectsTmp
->y
+ pRectsTmp
->height
- offset1
;
1043 box
.x2
= box
.x1
+ pRectsTmp
->width
+ offset2
;
1044 box
.y2
= box
.y1
+ offset2
;
1045 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1046 if (BOX_NOT_EMPTY(box
))
1047 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1052 (*pGC
->ops
->PolyRectangle
) (pDrawable
, pGC
, nRects
, pRects
);
1053 damageRegionProcessPending(pDrawable
);
1054 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1058 damagePolyArc(DrawablePtr pDrawable
, GCPtr pGC
, int nArcs
, xArc
* pArcs
)
1060 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1062 if (nArcs
&& checkGCDamage(pDrawable
, pGC
)) {
1063 int extra
= pGC
->lineWidth
>> 1;
1065 int nArcsTmp
= nArcs
;
1066 xArc
*pArcsTmp
= pArcs
;
1068 box
.x1
= pArcsTmp
->x
;
1069 box
.x2
= box
.x1
+ pArcsTmp
->width
;
1070 box
.y1
= pArcsTmp
->y
;
1071 box
.y2
= box
.y1
+ pArcsTmp
->height
;
1073 while (--nArcsTmp
) {
1075 if (box
.x1
> pArcsTmp
->x
)
1076 box
.x1
= pArcsTmp
->x
;
1077 if (box
.x2
< (pArcsTmp
->x
+ pArcsTmp
->width
))
1078 box
.x2
= pArcsTmp
->x
+ pArcsTmp
->width
;
1079 if (box
.y1
> pArcsTmp
->y
)
1080 box
.y1
= pArcsTmp
->y
;
1081 if (box
.y2
< (pArcsTmp
->y
+ pArcsTmp
->height
))
1082 box
.y2
= pArcsTmp
->y
+ pArcsTmp
->height
;
1095 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1096 if (BOX_NOT_EMPTY(box
))
1097 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1099 (*pGC
->ops
->PolyArc
) (pDrawable
, pGC
, nArcs
, pArcs
);
1100 damageRegionProcessPending(pDrawable
);
1101 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1105 damageFillPolygon(DrawablePtr pDrawable
,
1106 GCPtr pGC
, int shape
, int mode
, int npt
, DDXPointPtr ppt
)
1108 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1110 if (npt
> 2 && checkGCDamage(pDrawable
, pGC
)) {
1111 DDXPointPtr pptTmp
= ppt
;
1115 box
.x2
= box
.x1
= pptTmp
->x
;
1116 box
.y2
= box
.y1
= pptTmp
->y
;
1118 if (mode
!= CoordModeOrigin
) {
1128 else if (box
.x2
< x
)
1132 else if (box
.y2
< y
)
1139 if (box
.x1
> pptTmp
->x
)
1141 else if (box
.x2
< pptTmp
->x
)
1143 if (box
.y1
> pptTmp
->y
)
1145 else if (box
.y2
< pptTmp
->y
)
1153 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1154 if (BOX_NOT_EMPTY(box
))
1155 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1158 (*pGC
->ops
->FillPolygon
) (pDrawable
, pGC
, shape
, mode
, npt
, ppt
);
1159 damageRegionProcessPending(pDrawable
);
1160 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1164 damagePolyFillRect(DrawablePtr pDrawable
,
1165 GCPtr pGC
, int nRects
, xRectangle
*pRects
)
1167 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1168 if (nRects
&& checkGCDamage(pDrawable
, pGC
)) {
1170 xRectangle
*pRectsTmp
= pRects
;
1171 int nRectsTmp
= nRects
;
1173 box
.x1
= pRectsTmp
->x
;
1174 box
.x2
= box
.x1
+ pRectsTmp
->width
;
1175 box
.y1
= pRectsTmp
->y
;
1176 box
.y2
= box
.y1
+ pRectsTmp
->height
;
1178 while (--nRectsTmp
) {
1180 if (box
.x1
> pRectsTmp
->x
)
1181 box
.x1
= pRectsTmp
->x
;
1182 if (box
.x2
< (pRectsTmp
->x
+ pRectsTmp
->width
))
1183 box
.x2
= pRectsTmp
->x
+ pRectsTmp
->width
;
1184 if (box
.y1
> pRectsTmp
->y
)
1185 box
.y1
= pRectsTmp
->y
;
1186 if (box
.y2
< (pRectsTmp
->y
+ pRectsTmp
->height
))
1187 box
.y2
= pRectsTmp
->y
+ pRectsTmp
->height
;
1190 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1191 if (BOX_NOT_EMPTY(box
))
1192 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1194 (*pGC
->ops
->PolyFillRect
) (pDrawable
, pGC
, nRects
, pRects
);
1195 damageRegionProcessPending(pDrawable
);
1196 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1200 damagePolyFillArc(DrawablePtr pDrawable
, GCPtr pGC
, int nArcs
, xArc
* pArcs
)
1202 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1204 if (nArcs
&& checkGCDamage(pDrawable
, pGC
)) {
1206 int nArcsTmp
= nArcs
;
1207 xArc
*pArcsTmp
= pArcs
;
1209 box
.x1
= pArcsTmp
->x
;
1210 box
.x2
= box
.x1
+ pArcsTmp
->width
;
1211 box
.y1
= pArcsTmp
->y
;
1212 box
.y2
= box
.y1
+ pArcsTmp
->height
;
1214 while (--nArcsTmp
) {
1216 if (box
.x1
> pArcsTmp
->x
)
1217 box
.x1
= pArcsTmp
->x
;
1218 if (box
.x2
< (pArcsTmp
->x
+ pArcsTmp
->width
))
1219 box
.x2
= pArcsTmp
->x
+ pArcsTmp
->width
;
1220 if (box
.y1
> pArcsTmp
->y
)
1221 box
.y1
= pArcsTmp
->y
;
1222 if (box
.y2
< (pArcsTmp
->y
+ pArcsTmp
->height
))
1223 box
.y2
= pArcsTmp
->y
+ pArcsTmp
->height
;
1226 TRIM_AND_TRANSLATE_BOX(box
, pDrawable
, pGC
);
1227 if (BOX_NOT_EMPTY(box
))
1228 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1230 (*pGC
->ops
->PolyFillArc
) (pDrawable
, pGC
, nArcs
, pArcs
);
1231 damageRegionProcessPending(pDrawable
);
1232 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1236 * general Poly/Image text function. Extract glyph information,
1237 * compute bounding box and remove cursor if it is overlapped.
1241 damageDamageChars(DrawablePtr pDrawable
,
1246 CharInfoPtr
* charinfo
, Bool imageblt
, int subWindowMode
)
1248 ExtentInfoRec extents
;
1251 QueryGlyphExtents(font
, charinfo
, n
, &extents
);
1253 if (extents
.overallWidth
> extents
.overallRight
)
1254 extents
.overallRight
= extents
.overallWidth
;
1255 if (extents
.overallWidth
< extents
.overallLeft
)
1256 extents
.overallLeft
= extents
.overallWidth
;
1257 if (extents
.overallLeft
> 0)
1258 extents
.overallLeft
= 0;
1259 if (extents
.fontAscent
> extents
.overallAscent
)
1260 extents
.overallAscent
= extents
.fontAscent
;
1261 if (extents
.fontDescent
> extents
.overallDescent
)
1262 extents
.overallDescent
= extents
.fontDescent
;
1264 box
.x1
= x
+ extents
.overallLeft
;
1265 box
.y1
= y
- extents
.overallAscent
;
1266 box
.x2
= x
+ extents
.overallRight
;
1267 box
.y2
= y
+ extents
.overallDescent
;
1268 damageDamageBox(pDrawable
, &box
, subWindowMode
);
1272 * values for textType:
1277 #define TT_IMAGE16 3
1280 damageText(DrawablePtr pDrawable
,
1284 unsigned long count
,
1285 char *chars
, FontEncoding fontEncoding
, Bool textType
)
1287 CharInfoPtr
*charinfo
;
1292 imageblt
= (textType
== TT_IMAGE8
) || (textType
== TT_IMAGE16
);
1294 if (!checkGCDamage(pDrawable
, pGC
))
1297 charinfo
= malloc(count
* sizeof(CharInfoPtr
));
1301 GetGlyphs(pGC
->font
, count
, (unsigned char *) chars
,
1302 fontEncoding
, &i
, charinfo
);
1303 n
= (unsigned int) i
;
1306 damageDamageChars(pDrawable
, pGC
->font
, x
+ pDrawable
->x
,
1307 y
+ pDrawable
->y
, n
, charinfo
, imageblt
,
1308 pGC
->subWindowMode
);
1314 damagePolyText8(DrawablePtr pDrawable
,
1315 GCPtr pGC
, int x
, int y
, int count
, char *chars
)
1317 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1318 damageText(pDrawable
, pGC
, x
, y
, (unsigned long) count
, chars
, Linear8Bit
,
1320 x
= (*pGC
->ops
->PolyText8
) (pDrawable
, pGC
, x
, y
, count
, chars
);
1321 damageRegionProcessPending(pDrawable
);
1322 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1327 damagePolyText16(DrawablePtr pDrawable
,
1328 GCPtr pGC
, int x
, int y
, int count
, unsigned short *chars
)
1330 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1331 damageText(pDrawable
, pGC
, x
, y
, (unsigned long) count
, (char *) chars
,
1332 FONTLASTROW(pGC
->font
) == 0 ? Linear16Bit
: TwoD16Bit
,
1334 x
= (*pGC
->ops
->PolyText16
) (pDrawable
, pGC
, x
, y
, count
, chars
);
1335 damageRegionProcessPending(pDrawable
);
1336 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1341 damageImageText8(DrawablePtr pDrawable
,
1342 GCPtr pGC
, int x
, int y
, int count
, char *chars
)
1344 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1345 damageText(pDrawable
, pGC
, x
, y
, (unsigned long) count
, chars
, Linear8Bit
,
1347 (*pGC
->ops
->ImageText8
) (pDrawable
, pGC
, x
, y
, count
, chars
);
1348 damageRegionProcessPending(pDrawable
);
1349 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1353 damageImageText16(DrawablePtr pDrawable
,
1354 GCPtr pGC
, int x
, int y
, int count
, unsigned short *chars
)
1356 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1357 damageText(pDrawable
, pGC
, x
, y
, (unsigned long) count
, (char *) chars
,
1358 FONTLASTROW(pGC
->font
) == 0 ? Linear16Bit
: TwoD16Bit
,
1360 (*pGC
->ops
->ImageText16
) (pDrawable
, pGC
, x
, y
, count
, chars
);
1361 damageRegionProcessPending(pDrawable
);
1362 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1366 damageImageGlyphBlt(DrawablePtr pDrawable
,
1370 unsigned int nglyph
, CharInfoPtr
* ppci
, pointer pglyphBase
)
1372 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1373 damageDamageChars(pDrawable
, pGC
->font
, x
+ pDrawable
->x
, y
+ pDrawable
->y
,
1374 nglyph
, ppci
, TRUE
, pGC
->subWindowMode
);
1375 (*pGC
->ops
->ImageGlyphBlt
) (pDrawable
, pGC
, x
, y
, nglyph
, ppci
, pglyphBase
);
1376 damageRegionProcessPending(pDrawable
);
1377 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1381 damagePolyGlyphBlt(DrawablePtr pDrawable
,
1385 unsigned int nglyph
, CharInfoPtr
* ppci
, pointer pglyphBase
)
1387 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1388 damageDamageChars(pDrawable
, pGC
->font
, x
+ pDrawable
->x
, y
+ pDrawable
->y
,
1389 nglyph
, ppci
, FALSE
, pGC
->subWindowMode
);
1390 (*pGC
->ops
->PolyGlyphBlt
) (pDrawable
, pGC
, x
, y
, nglyph
, ppci
, pglyphBase
);
1391 damageRegionProcessPending(pDrawable
);
1392 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1396 damagePushPixels(GCPtr pGC
,
1398 DrawablePtr pDrawable
, int dx
, int dy
, int xOrg
, int yOrg
)
1400 DAMAGE_GC_OP_PROLOGUE(pGC
, pDrawable
);
1401 if (checkGCDamage(pDrawable
, pGC
)) {
1407 if (!pGC
->miTranslate
) {
1408 box
.x1
+= pDrawable
->x
;
1409 box
.y1
+= pDrawable
->y
;
1412 box
.x2
= box
.x1
+ dx
;
1413 box
.y2
= box
.y1
+ dy
;
1416 if (BOX_NOT_EMPTY(box
))
1417 damageDamageBox(pDrawable
, &box
, pGC
->subWindowMode
);
1419 (*pGC
->ops
->PushPixels
) (pGC
, pBitMap
, pDrawable
, dx
, dy
, xOrg
, yOrg
);
1420 damageRegionProcessPending(pDrawable
);
1421 DAMAGE_GC_OP_EPILOGUE(pGC
, pDrawable
);
1425 damageRemoveDamage(DamagePtr
* pPrev
, DamagePtr pDamage
)
1428 if (*pPrev
== pDamage
) {
1429 *pPrev
= pDamage
->pNext
;
1432 pPrev
= &(*pPrev
)->pNext
;
1434 #if DAMAGE_VALIDATE_ENABLE
1435 ErrorF("Damage not on list\n");
1441 damageInsertDamage(DamagePtr
* pPrev
, DamagePtr pDamage
)
1443 #if DAMAGE_VALIDATE_ENABLE
1446 for (pOld
= *pPrev
; pOld
; pOld
= pOld
->pNext
)
1447 if (pOld
== pDamage
) {
1448 ErrorF("Damage already on list\n");
1452 pDamage
->pNext
= *pPrev
;
1457 damageDestroyPixmap(PixmapPtr pPixmap
)
1459 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
1461 damageScrPriv(pScreen
);
1463 if (pPixmap
->refcnt
== 1) {
1464 DamagePtr
*pPrev
= getPixmapDamageRef(pPixmap
);
1467 while ((pDamage
= *pPrev
)) {
1468 damageRemoveDamage(pPrev
, pDamage
);
1469 if (!pDamage
->isWindow
)
1470 DamageDestroy(pDamage
);
1473 unwrap(pScrPriv
, pScreen
, DestroyPixmap
);
1474 (*pScreen
->DestroyPixmap
) (pPixmap
);
1475 wrap(pScrPriv
, pScreen
, DestroyPixmap
, damageDestroyPixmap
);
1480 damageCopyWindow(WindowPtr pWindow
, DDXPointRec ptOldOrg
, RegionPtr prgnSrc
)
1482 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1484 damageScrPriv(pScreen
);
1486 if (getWindowDamage(pWindow
)) {
1487 int dx
= pWindow
->drawable
.x
- ptOldOrg
.x
;
1488 int dy
= pWindow
->drawable
.y
- ptOldOrg
.y
;
1491 * The region comes in source relative, but the damage occurs
1492 * at the destination location. Translate back and forth.
1494 RegionTranslate(prgnSrc
, dx
, dy
);
1495 damageRegionAppend(&pWindow
->drawable
, prgnSrc
, FALSE
, -1);
1496 RegionTranslate(prgnSrc
, -dx
, -dy
);
1498 unwrap(pScrPriv
, pScreen
, CopyWindow
);
1499 (*pScreen
->CopyWindow
) (pWindow
, ptOldOrg
, prgnSrc
);
1500 damageRegionProcessPending(&pWindow
->drawable
);
1501 wrap(pScrPriv
, pScreen
, CopyWindow
, damageCopyWindow
);
1504 static GCOps damageGCOps
= {
1505 damageFillSpans
, damageSetSpans
,
1506 damagePutImage
, damageCopyArea
,
1507 damageCopyPlane
, damagePolyPoint
,
1508 damagePolylines
, damagePolySegment
,
1509 damagePolyRectangle
, damagePolyArc
,
1510 damageFillPolygon
, damagePolyFillRect
,
1511 damagePolyFillArc
, damagePolyText8
,
1512 damagePolyText16
, damageImageText8
,
1513 damageImageText16
, damageImageGlyphBlt
,
1514 damagePolyGlyphBlt
, damagePushPixels
,
1518 damageSetWindowPixmap(WindowPtr pWindow
, PixmapPtr pPixmap
)
1521 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1523 damageScrPriv(pScreen
);
1525 if ((pDamage
= damageGetWinPriv(pWindow
))) {
1526 PixmapPtr pOldPixmap
= (*pScreen
->GetWindowPixmap
) (pWindow
);
1527 DamagePtr
*pPrev
= getPixmapDamageRef(pOldPixmap
);
1530 damageRemoveDamage(pPrev
, pDamage
);
1531 pDamage
= pDamage
->pNextWin
;
1534 unwrap(pScrPriv
, pScreen
, SetWindowPixmap
);
1535 (*pScreen
->SetWindowPixmap
) (pWindow
, pPixmap
);
1536 wrap(pScrPriv
, pScreen
, SetWindowPixmap
, damageSetWindowPixmap
);
1537 if ((pDamage
= damageGetWinPriv(pWindow
))) {
1538 DamagePtr
*pPrev
= getPixmapDamageRef(pPixmap
);
1541 damageInsertDamage(pPrev
, pDamage
);
1542 pDamage
= pDamage
->pNextWin
;
1548 damageDestroyWindow(WindowPtr pWindow
)
1551 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1554 damageScrPriv(pScreen
);
1556 while ((pDamage
= damageGetWinPriv(pWindow
))) {
1557 DamageDestroy(pDamage
);
1559 unwrap(pScrPriv
, pScreen
, DestroyWindow
);
1560 ret
= (*pScreen
->DestroyWindow
) (pWindow
);
1561 wrap(pScrPriv
, pScreen
, DestroyWindow
, damageDestroyWindow
);
1566 damageCloseScreen(ScreenPtr pScreen
)
1568 damageScrPriv(pScreen
);
1570 unwrap(pScrPriv
, pScreen
, DestroyPixmap
);
1571 unwrap(pScrPriv
, pScreen
, CreateGC
);
1572 unwrap(pScrPriv
, pScreen
, CopyWindow
);
1573 unwrap(pScrPriv
, pScreen
, CloseScreen
);
1575 return (*pScreen
->CloseScreen
) (pScreen
);
1579 * Default implementations of the damage management functions.
1582 miDamageCreate(DamagePtr pDamage
)
1587 * We only wrap into the GC when there's a registered listener. For windows,
1588 * damage includes damage to children. So if there's a GC validated against
1589 * a subwindow and we then register a damage on the parent, we need to bump
1590 * the serial numbers of the children to re-trigger validation.
1592 * Since we can't know if a GC has been validated against one of the affected
1593 * children, just bump them all to be safe.
1596 damageRegisterVisit(WindowPtr pWin
, void *data
)
1598 pWin
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
1599 return WT_WALKCHILDREN
;
1603 miDamageRegister(DrawablePtr pDrawable
, DamagePtr pDamage
)
1605 if (pDrawable
->type
== DRAWABLE_WINDOW
)
1606 TraverseTree((WindowPtr
)pDrawable
, damageRegisterVisit
, NULL
);
1608 pDrawable
->serialNumber
= NEXT_SERIAL_NUMBER
;
1612 miDamageUnregister(DrawablePtr pDrawable
, DamagePtr pDamage
)
1614 if (pDrawable
->type
== DRAWABLE_WINDOW
)
1615 TraverseTree((WindowPtr
)pDrawable
, damageRegisterVisit
, NULL
);
1617 pDrawable
->serialNumber
= NEXT_SERIAL_NUMBER
;
1621 miDamageDestroy(DamagePtr pDamage
)
1626 * Public functions for consumption outside this file.
1630 DamageSetup(ScreenPtr pScreen
)
1632 DamageScrPrivPtr pScrPriv
;
1633 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
1635 const DamageScreenFuncsRec miFuncs
= {
1636 miDamageCreate
, miDamageRegister
, miDamageUnregister
, miDamageDestroy
1639 if (!dixRegisterPrivateKey(&damageScrPrivateKeyRec
, PRIVATE_SCREEN
, 0))
1642 if (dixLookupPrivate(&pScreen
->devPrivates
, damageScrPrivateKey
))
1645 if (!dixRegisterPrivateKey
1646 (&damageGCPrivateKeyRec
, PRIVATE_GC
, sizeof(DamageGCPrivRec
)))
1649 if (!dixRegisterPrivateKey(&damagePixPrivateKeyRec
, PRIVATE_PIXMAP
, 0))
1652 if (!dixRegisterPrivateKey(&damageWinPrivateKeyRec
, PRIVATE_WINDOW
, 0))
1655 pScrPriv
= malloc(sizeof(DamageScrPrivRec
));
1659 pScrPriv
->internalLevel
= 0;
1660 pScrPriv
->pScreenDamage
= 0;
1662 wrap(pScrPriv
, pScreen
, DestroyPixmap
, damageDestroyPixmap
);
1663 wrap(pScrPriv
, pScreen
, CreateGC
, damageCreateGC
);
1664 wrap(pScrPriv
, pScreen
, DestroyWindow
, damageDestroyWindow
);
1665 wrap(pScrPriv
, pScreen
, SetWindowPixmap
, damageSetWindowPixmap
);
1666 wrap(pScrPriv
, pScreen
, CopyWindow
, damageCopyWindow
);
1667 wrap(pScrPriv
, pScreen
, CloseScreen
, damageCloseScreen
);
1669 wrap(pScrPriv
, ps
, Glyphs
, damageGlyphs
);
1670 wrap(pScrPriv
, ps
, Composite
, damageComposite
);
1671 wrap(pScrPriv
, ps
, AddTraps
, damageAddTraps
);
1674 pScrPriv
->funcs
= miFuncs
;
1676 dixSetPrivate(&pScreen
->devPrivates
, damageScrPrivateKey
, pScrPriv
);
1681 DamageCreate(DamageReportFunc damageReport
,
1682 DamageDestroyFunc damageDestroy
,
1683 DamageReportLevel damageLevel
,
1684 Bool isInternal
, ScreenPtr pScreen
, void *closure
)
1686 damageScrPriv(pScreen
);
1689 pDamage
= dixAllocateObjectWithPrivates(DamageRec
, PRIVATE_DAMAGE
);
1693 pDamage
->pNextWin
= 0;
1694 RegionNull(&pDamage
->damage
);
1695 RegionNull(&pDamage
->pendingDamage
);
1697 pDamage
->damageLevel
= damageLevel
;
1698 pDamage
->isInternal
= isInternal
;
1699 pDamage
->closure
= closure
;
1700 pDamage
->isWindow
= FALSE
;
1701 pDamage
->pDrawable
= 0;
1702 pDamage
->reportAfter
= FALSE
;
1704 pDamage
->damageReport
= damageReport
;
1705 pDamage
->damageDestroy
= damageDestroy
;
1706 pDamage
->pScreen
= pScreen
;
1708 (*pScrPriv
->funcs
.Create
) (pDamage
);
1714 DamageRegister(DrawablePtr pDrawable
, DamagePtr pDamage
)
1716 ScreenPtr pScreen
= pDrawable
->pScreen
;
1718 damageScrPriv(pScreen
);
1720 #if DAMAGE_VALIDATE_ENABLE
1721 if (pDrawable
->pScreen
!= pDamage
->pScreen
) {
1722 ErrorF("DamageRegister called with mismatched screens\n");
1727 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
1728 WindowPtr pWindow
= (WindowPtr
) pDrawable
;
1730 winDamageRef(pWindow
);
1732 #if DAMAGE_VALIDATE_ENABLE
1735 for (pOld
= *pPrev
; pOld
; pOld
= pOld
->pNextWin
)
1736 if (pOld
== pDamage
) {
1737 ErrorF("Damage already on window list\n");
1741 pDamage
->pNextWin
= *pPrev
;
1743 pDamage
->isWindow
= TRUE
;
1746 pDamage
->isWindow
= FALSE
;
1747 pDamage
->pDrawable
= pDrawable
;
1748 damageInsertDamage(getDrawableDamageRef(pDrawable
), pDamage
);
1749 (*pScrPriv
->funcs
.Register
) (pDrawable
, pDamage
);
1753 DamageDrawInternal(ScreenPtr pScreen
, Bool enable
)
1755 damageScrPriv(pScreen
);
1757 pScrPriv
->internalLevel
+= enable
? 1 : -1;
1761 DamageUnregister(DamagePtr pDamage
)
1763 DrawablePtr pDrawable
= pDamage
->pDrawable
;
1764 ScreenPtr pScreen
= pDrawable
->pScreen
;
1766 damageScrPriv(pScreen
);
1768 (*pScrPriv
->funcs
.Unregister
) (pDrawable
, pDamage
);
1770 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
1771 WindowPtr pWindow
= (WindowPtr
) pDrawable
;
1773 winDamageRef(pWindow
);
1774 #if DAMAGE_VALIDATE_ENABLE
1779 if (*pPrev
== pDamage
) {
1780 *pPrev
= pDamage
->pNextWin
;
1781 #if DAMAGE_VALIDATE_ENABLE
1786 pPrev
= &(*pPrev
)->pNextWin
;
1788 #if DAMAGE_VALIDATE_ENABLE
1790 ErrorF("Damage not on window list\n");
1795 pDamage
->pDrawable
= 0;
1796 damageRemoveDamage(getDrawableDamageRef(pDrawable
), pDamage
);
1800 DamageDestroy(DamagePtr pDamage
)
1802 ScreenPtr pScreen
= pDamage
->pScreen
;
1804 damageScrPriv(pScreen
);
1806 if (pDamage
->pDrawable
)
1807 DamageUnregister(pDamage
);
1809 if (pDamage
->damageDestroy
)
1810 (*pDamage
->damageDestroy
) (pDamage
, pDamage
->closure
);
1811 (*pScrPriv
->funcs
.Destroy
) (pDamage
);
1812 RegionUninit(&pDamage
->damage
);
1813 RegionUninit(&pDamage
->pendingDamage
);
1814 dixFreeObjectWithPrivates(pDamage
, PRIVATE_DAMAGE
);
1818 DamageSubtract(DamagePtr pDamage
, const RegionPtr pRegion
)
1821 RegionRec pixmapClip
;
1822 DrawablePtr pDrawable
= pDamage
->pDrawable
;
1824 RegionSubtract(&pDamage
->damage
, &pDamage
->damage
, pRegion
);
1826 if (pDrawable
->type
== DRAWABLE_WINDOW
)
1827 pClip
= &((WindowPtr
) pDrawable
)->borderClip
;
1831 box
.x1
= pDrawable
->x
;
1832 box
.y1
= pDrawable
->y
;
1833 box
.x2
= pDrawable
->x
+ pDrawable
->width
;
1834 box
.y2
= pDrawable
->y
+ pDrawable
->height
;
1835 RegionInit(&pixmapClip
, &box
, 1);
1836 pClip
= &pixmapClip
;
1838 RegionTranslate(&pDamage
->damage
, pDrawable
->x
, pDrawable
->y
);
1839 RegionIntersect(&pDamage
->damage
, &pDamage
->damage
, pClip
);
1840 RegionTranslate(&pDamage
->damage
, -pDrawable
->x
, -pDrawable
->y
);
1841 if (pDrawable
->type
!= DRAWABLE_WINDOW
)
1842 RegionUninit(&pixmapClip
);
1844 return RegionNotEmpty(&pDamage
->damage
);
1848 DamageEmpty(DamagePtr pDamage
)
1850 RegionEmpty(&pDamage
->damage
);
1854 DamageRegion(DamagePtr pDamage
)
1856 return &pDamage
->damage
;
1860 DamagePendingRegion(DamagePtr pDamage
)
1862 return &pDamage
->pendingDamage
;
1866 DamageRegionAppend(DrawablePtr pDrawable
, RegionPtr pRegion
)
1868 damageRegionAppend(pDrawable
, pRegion
, FALSE
, -1);
1872 DamageRegionProcessPending(DrawablePtr pDrawable
)
1874 damageRegionProcessPending(pDrawable
);
1877 /* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */
1879 DamageDamageRegion(DrawablePtr pDrawable
, RegionPtr pRegion
)
1881 damageRegionAppend(pDrawable
, pRegion
, FALSE
, -1);
1883 /* Go back and report this damage for DamagePtrs with reportAfter set, since
1884 * this call isn't part of an in-progress drawing op in the call chain and
1885 * the DDX probably just wants to know about it right away.
1887 damageRegionProcessPending(pDrawable
);
1891 DamageSetReportAfterOp(DamagePtr pDamage
, Bool reportAfter
)
1893 pDamage
->reportAfter
= reportAfter
;
1896 DamageScreenFuncsPtr
1897 DamageGetScreenFuncs(ScreenPtr pScreen
)
1899 damageScrPriv(pScreen
);
1900 return &pScrPriv
->funcs
;
1904 DamageReportDamage(DamagePtr pDamage
, RegionPtr pDamageRegion
)
1907 RegionRec tmpRegion
;
1910 switch (pDamage
->damageLevel
) {
1911 case DamageReportRawRegion
:
1912 RegionUnion(&pDamage
->damage
, &pDamage
->damage
, pDamageRegion
);
1913 (*pDamage
->damageReport
) (pDamage
, pDamageRegion
, pDamage
->closure
);
1915 case DamageReportDeltaRegion
:
1916 RegionNull(&tmpRegion
);
1917 RegionSubtract(&tmpRegion
, pDamageRegion
, &pDamage
->damage
);
1918 if (RegionNotEmpty(&tmpRegion
)) {
1919 RegionUnion(&pDamage
->damage
, &pDamage
->damage
, pDamageRegion
);
1920 (*pDamage
->damageReport
) (pDamage
, &tmpRegion
, pDamage
->closure
);
1922 RegionUninit(&tmpRegion
);
1924 case DamageReportBoundingBox
:
1925 tmpBox
= *RegionExtents(&pDamage
->damage
);
1926 RegionUnion(&pDamage
->damage
, &pDamage
->damage
, pDamageRegion
);
1927 if (!BOX_SAME(&tmpBox
, RegionExtents(&pDamage
->damage
))) {
1928 (*pDamage
->damageReport
) (pDamage
, &pDamage
->damage
,
1932 case DamageReportNonEmpty
:
1933 was_empty
= !RegionNotEmpty(&pDamage
->damage
);
1934 RegionUnion(&pDamage
->damage
, &pDamage
->damage
, pDamageRegion
);
1935 if (was_empty
&& RegionNotEmpty(&pDamage
->damage
)) {
1936 (*pDamage
->damageReport
) (pDamage
, &pDamage
->damage
,
1940 case DamageReportNone
:
1941 RegionUnion(&pDamage
->damage
, &pDamage
->damage
, pDamageRegion
);