1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by the Regents of the University of California
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted, provided
32 that the above copyright notice appear in all copies and that both that
33 copyright notice and this permission notice appear in supporting
34 documentation, and that the name The Open Group not be used in advertising or publicity
35 pertaining to distribution of the software without specific, written prior
38 The University of California makes no representations about the suitability
39 of this software for any purpose. It is provided "as is" without express or
42 ******************************************************************/
46 #ifdef HAVE_DIX_CONFIG_H
47 #include <dix-config.h>
52 #include <X11/Xproto.h>
54 #include "regionstr.h"
55 #include "scrnintstr.h"
57 #include "windowstr.h"
58 #include "pixmapstr.h"
59 #include <X11/fonts/fontstruct.h>
60 #include "dixfontstr.h"
61 #include "dixstruct.h" /* For requestingClient */
63 #include "mibstorest.h"
66 * When the server fails to allocate a backing store pixmap, if you want
67 * it to dynamically retry to allocate backing store on every subsequent
68 * graphics op, you can enable BSEAGER; otherwise, backing store will be
69 * disabled on the window until it is unmapped and then remapped.
76 * The functions in this file implement a machine-independent backing-store
77 * scheme. To use it, the output library must do the following:
78 * - Provide a SaveAreas function that takes a destination pixmap, a
79 * region of the areas to save (in the pixmap's coordinate system)
80 * and the screen origin of the region. It should copy the areas from
81 * the screen into the pixmap.
82 * - Provide a RestoreAreas function that takes a source pixmap, a region
83 * of the areas to restore (in the screen's coordinate system) and the
84 * origin of the pixmap on the screen. It should copy the areas from
85 * the pixmap into the screen.
86 * - Provide a SetClipmaskRgn function that takes a gc and a region
87 * and merges the region into any CT_PIXMAP client clip that
88 * is specified in the GC. This routine is only needed if
89 * miValidateBackingStore will see CT_PIXMAP clip lists; not
90 * true for any of the sample servers (which convert the PIXMAP
91 * clip lists into CT_REGION clip lists; an expensive but simple
93 * - The function placed in a window's ClearToBackground vector must call
94 * pScreen->ClearBackingStore with the window, followed by
95 * the window-relative x and y coordinates, followed by the width and
96 * height of the area to be cleared, followed by the generateExposures
97 * flag. This has been taken care of in miClearToBackground.
98 * - Whatever determines GraphicsExpose events for the CopyArea and
99 * CopyPlane requests should call pWin->backStorage->ExposeCopy
100 * with the source and destination drawables, the GC used, a source-
101 * window-relative region of exposed areas, the source and destination
102 * coordinates and the bitplane copied, if CopyPlane, or 0, if
106 * This is a cross between saving everything and just saving the
107 * obscued areas (as in Pike's layers.) This method has the advantage
108 * of only doing each output operation once per pixel, visible or
109 * invisible, and avoids having to do all the crufty storage
110 * management of keeping several separate rectangles. Since the
111 * ddx layer ouput primitives are required to draw through clipping
112 * rectangles anyway, sending multiple drawing requests for each of
113 * several rectangles isn't necessary. (Of course, it could be argued
114 * that the ddx routines should just take one rectangle each and
115 * get called multiple times, but that would make taking advantage of
116 * smart hardware harder, and probably be slower as well.)
119 #define SETUP_BACKING_TERSE(pGC) \
120 miBSGCPtr pGCPrivate = (miBSGCPtr)(pGC)->devPrivates[miBSGCIndex].ptr; \
121 GCFuncs *oldFuncs = pGC->funcs;
123 #define SETUP_BACKING(pDrawable,pGC) \
124 miBSWindowPtr pBackingStore = \
125 (miBSWindowPtr)((WindowPtr)(pDrawable))->backStorage; \
126 DrawablePtr pBackingDrawable = (DrawablePtr) \
127 pBackingStore->pBackingPixmap; \
128 SETUP_BACKING_TERSE(pGC) \
129 GCPtr pBackingGC = pGCPrivate->pBackingGC;
131 #define PROLOGUE(pGC) { \
132 pGC->ops = pGCPrivate->wrapOps;\
133 pGC->funcs = pGCPrivate->wrapFuncs; \
136 #define EPILOGUE(pGC) { \
137 pGCPrivate->wrapOps = (pGC)->ops; \
138 (pGC)->ops = &miBSGCOps; \
139 (pGC)->funcs = oldFuncs; \
142 static void miCreateBSPixmap(WindowPtr pWin
, BoxPtr pExtents
);
143 static void miDestroyBSPixmap(WindowPtr pWin
);
144 static void miTileVirtualBS(WindowPtr pWin
);
145 static void miBSAllocate(WindowPtr pWin
), miBSFree(WindowPtr pWin
);
146 static Bool
miBSCreateGCPrivate(GCPtr pGC
);
147 static void miBSClearBackingRegion(WindowPtr pWin
, RegionPtr pRgn
);
150 #define MoreCopy2 *dstCopy++ = *srcCopy++; *dstCopy++ = *srcCopy++;
151 #define MoreCopy4 MoreCopy2 MoreCopy2
153 #define copyData(src,dst,n,morecopy) \
155 short *srcCopy = (short *)(src); \
156 short *dstCopy = (short *)(dst); \
158 int bsx = pBackingStore->x; \
159 int bsy = pBackingStore->y; \
160 for (i = n; --i >= 0; ) \
162 *dstCopy++ = *srcCopy++ - bsx; \
163 *dstCopy++ = *srcCopy++ - bsy; \
168 #define copyPoints(src,dst,n,mode) \
169 if (mode == CoordModeOrigin) \
171 copyData(src,dst,n,MoreCopy0); \
175 memmove((char *)(dst), (char *)(src), (n) << 2); \
176 *((short *)(dst)) -= pBackingStore->x; \
177 *((short *)(dst) + 1) -= pBackingStore->y; \
181 * wrappers for screen funcs
184 static int miBSScreenIndex
;
185 static unsigned long miBSGeneration
= 0;
187 static Bool
miBSCloseScreen(int i
, ScreenPtr pScreen
);
188 static void miBSGetImage(DrawablePtr pDrawable
, int sx
, int sy
,
189 int w
, int h
, unsigned int format
,
190 unsigned long planemask
, char *pdstLine
);
191 static void miBSGetSpans(DrawablePtr pDrawable
, int wMax
,
192 DDXPointPtr ppt
, int *pwidth
, int nspans
,
194 static Bool
miBSChangeWindowAttributes(WindowPtr pWin
,
196 static Bool
miBSCreateGC(GCPtr pGC
);
197 static Bool
miBSDestroyWindow(WindowPtr pWin
);
200 * backing store screen functions
203 static void miBSSaveDoomedAreas(WindowPtr pWin
, RegionPtr pObscured
,
205 static RegionPtr
miBSRestoreAreas(WindowPtr pWin
, RegionPtr prgnExposed
);
206 static void miBSExposeCopy(WindowPtr pSrc
, DrawablePtr pDst
,
207 GCPtr pGC
, RegionPtr prgnExposed
,
208 int srcx
, int srcy
, int dstx
, int dsty
,
209 unsigned long plane
);
210 static RegionPtr
miBSTranslateBackingStore(WindowPtr pWin
, int windx
,
211 int windy
, RegionPtr oldClip
,
213 static RegionPtr
miBSClearBackingStore(WindowPtr pWin
, int x
, int y
,
214 int w
, int h
, Bool generateExposures
);
215 static void miBSDrawGuarantee(WindowPtr pWin
, GCPtr pGC
,
219 * wrapper vectors for GC funcs and ops
222 static int miBSGCIndex
;
224 static void miBSValidateGC(GCPtr pGC
, unsigned long stateChanges
,
225 DrawablePtr pDrawable
);
226 static void miBSCopyGC(GCPtr pGCSrc
, unsigned long mask
, GCPtr pGCDst
);
227 static void miBSDestroyGC(GCPtr pGC
);
228 static void miBSChangeGC(GCPtr pGC
, unsigned long mask
);
229 static void miBSChangeClip(GCPtr pGC
, int type
, pointer pvalue
, int nrects
);
230 static void miBSDestroyClip(GCPtr pGC
);
231 static void miBSCopyClip(GCPtr pgcDst
, GCPtr pgcSrc
);
233 static GCFuncs miBSGCFuncs
= {
243 static void miBSFillSpans(DrawablePtr pDrawable
, GCPtr pGC
, int nInit
,
244 DDXPointPtr pptInit
, int *pwidthInit
,
246 static void miBSSetSpans(DrawablePtr pDrawable
, GCPtr pGC
, char *psrc
,
247 DDXPointPtr ppt
, int *pwidth
, int nspans
,
249 static void miBSPutImage(DrawablePtr pDrawable
, GCPtr pGC
, int depth
,
250 int x
, int y
, int w
, int h
, int leftPad
,
251 int format
, char *pBits
);
252 static RegionPtr
miBSCopyArea(DrawablePtr pSrc
, DrawablePtr pDst
,
253 GCPtr pGC
, int srcx
, int srcy
, int w
, int h
,
255 static RegionPtr
miBSCopyPlane(DrawablePtr pSrc
, DrawablePtr pDst
,
256 GCPtr pGC
, int srcx
, int srcy
, int w
, int h
,
257 int dstx
, int dsty
, unsigned long plane
);
258 static void miBSPolyPoint(DrawablePtr pDrawable
, GCPtr pGC
, int mode
,
259 int npt
, xPoint
*pptInit
);
260 static void miBSPolylines(DrawablePtr pDrawable
, GCPtr pGC
, int mode
,
261 int npt
, DDXPointPtr pptInit
);
262 static void miBSPolySegment(DrawablePtr pDrawable
, GCPtr pGC
, int nseg
,
264 static void miBSPolyRectangle(DrawablePtr pDrawable
, GCPtr pGC
,
265 int nrects
, xRectangle
*pRects
);
266 static void miBSPolyArc(DrawablePtr pDrawable
, GCPtr pGC
, int narcs
,
268 static void miBSFillPolygon(DrawablePtr pDrawable
, GCPtr pGC
,
269 int shape
, int mode
, int count
,
271 static void miBSPolyFillRect(DrawablePtr pDrawable
, GCPtr pGC
,
272 int nrectFill
, xRectangle
*prectInit
);
273 static void miBSPolyFillArc(DrawablePtr pDrawable
, GCPtr pGC
,
274 int narcs
, xArc
*parcs
);
275 static int miBSPolyText8(DrawablePtr pDrawable
, GCPtr pGC
,
276 int x
, int y
, int count
, char *chars
);
277 static int miBSPolyText16(DrawablePtr pDrawable
, GCPtr pGC
,
278 int x
, int y
, int count
,
279 unsigned short *chars
);
280 static void miBSImageText8(DrawablePtr pDrawable
, GCPtr pGC
,
281 int x
, int y
, int count
, char *chars
);
282 static void miBSImageText16(DrawablePtr pDrawable
, GCPtr pGC
,
283 int x
, int y
, int count
,
284 unsigned short *chars
);
285 static void miBSImageGlyphBlt(DrawablePtr pDrawable
, GCPtr pGC
,
286 int x
, int y
, unsigned int nglyph
,
287 CharInfoPtr
*ppci
, pointer pglyphBase
);
288 static void miBSPolyGlyphBlt(DrawablePtr pDrawable
, GCPtr pGC
,
289 int x
, int y
, unsigned int nglyph
,
290 CharInfoPtr
*ppci
, pointer pglyphBase
);
291 static void miBSPushPixels(GCPtr pGC
, PixmapPtr pBitMap
,
292 DrawablePtr pDst
, int w
, int h
,
295 static GCOps miBSGCOps
= {
296 miBSFillSpans
, miBSSetSpans
, miBSPutImage
,
297 miBSCopyArea
, miBSCopyPlane
, miBSPolyPoint
,
298 miBSPolylines
, miBSPolySegment
, miBSPolyRectangle
,
299 miBSPolyArc
, miBSFillPolygon
, miBSPolyFillRect
,
300 miBSPolyFillArc
, miBSPolyText8
, miBSPolyText16
,
301 miBSImageText8
, miBSImageText16
, miBSImageGlyphBlt
,
302 miBSPolyGlyphBlt
, miBSPushPixels
305 #define FUNC_PROLOGUE(pGC, pPriv) \
306 ((pGC)->funcs = pPriv->wrapFuncs),\
307 ((pGC)->ops = pPriv->wrapOps)
309 #define FUNC_EPILOGUE(pGC, pPriv) \
310 ((pGC)->funcs = &miBSGCFuncs),\
311 ((pGC)->ops = &miBSGCOps)
314 * every GC in the server is initially wrapped with these
315 * "cheap" functions. This allocates no memory and is used
316 * to discover GCs used with windows which have backing
320 static void miBSCheapValidateGC(GCPtr pGC
, unsigned long stateChanges
,
321 DrawablePtr pDrawable
);
322 static void miBSCheapCopyGC(GCPtr pGCSrc
, unsigned long mask
, GCPtr pGCDst
);
323 static void miBSCheapDestroyGC(GCPtr pGC
);
324 static void miBSCheapChangeGC(GCPtr pGC
, unsigned long mask
);
325 static void miBSCheapChangeClip(GCPtr pGC
, int type
, pointer pvalue
,
327 static void miBSCheapDestroyClip(GCPtr pGC
);
328 static void miBSCheapCopyClip(GCPtr pgcDst
, GCPtr pgcSrc
);
330 static GCFuncs miBSCheapGCFuncs
= {
336 miBSCheapDestroyClip
,
340 #define CHEAP_FUNC_PROLOGUE(pGC) \
341 ((pGC)->funcs = (GCFuncs *) (pGC)->devPrivates[miBSGCIndex].ptr)
343 #define CHEAP_FUNC_EPILOGUE(pGC) \
344 ((pGC)->funcs = &miBSCheapGCFuncs)
347 * called from device screen initialization proc. Gets a GCPrivateIndex
348 * and wraps appropriate per-screen functions. pScreen->BackingStoreFuncs
349 * must be previously initialized.
353 miInitializeBackingStore (pScreen
)
356 miBSScreenPtr pScreenPriv
;
358 if (miBSGeneration
!= serverGeneration
)
360 miBSScreenIndex
= AllocateScreenPrivateIndex ();
361 if (miBSScreenIndex
< 0)
363 miBSGCIndex
= AllocateGCPrivateIndex ();
364 miBSGeneration
= serverGeneration
;
366 if (!AllocateGCPrivate(pScreen
, miBSGCIndex
, 0))
368 pScreenPriv
= (miBSScreenPtr
) xalloc (sizeof (miBSScreenRec
));
372 pScreenPriv
->CloseScreen
= pScreen
->CloseScreen
;
373 pScreenPriv
->GetImage
= pScreen
->GetImage
;
374 pScreenPriv
->GetSpans
= pScreen
->GetSpans
;
375 pScreenPriv
->ChangeWindowAttributes
= pScreen
->ChangeWindowAttributes
;
376 pScreenPriv
->CreateGC
= pScreen
->CreateGC
;
377 pScreenPriv
->DestroyWindow
= pScreen
->DestroyWindow
;
379 pScreen
->CloseScreen
= miBSCloseScreen
;
380 pScreen
->GetImage
= miBSGetImage
;
381 pScreen
->GetSpans
= miBSGetSpans
;
382 pScreen
->ChangeWindowAttributes
= miBSChangeWindowAttributes
;
383 pScreen
->CreateGC
= miBSCreateGC
;
384 pScreen
->DestroyWindow
= miBSDestroyWindow
;
386 pScreen
->SaveDoomedAreas
= miBSSaveDoomedAreas
;
387 pScreen
->RestoreAreas
= miBSRestoreAreas
;
388 pScreen
->ExposeCopy
= miBSExposeCopy
;
389 pScreen
->TranslateBackingStore
= miBSTranslateBackingStore
;
390 pScreen
->ClearBackingStore
= miBSClearBackingStore
;
391 pScreen
->DrawGuarantee
= miBSDrawGuarantee
;
393 pScreen
->devPrivates
[miBSScreenIndex
].ptr
= (pointer
) pScreenPriv
;
397 * Screen function wrappers
400 #define SCREEN_PROLOGUE(pScreen, field)\
401 ((pScreen)->field = \
403 (pScreen)->devPrivates[miBSScreenIndex].ptr)->field)
405 #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
406 ((pScreen)->field = wrapper)
409 * CloseScreen wrapper -- unwrap everything, free the private data
410 * and call the wrapped function
414 miBSCloseScreen (i
, pScreen
)
418 miBSScreenPtr pScreenPriv
;
420 pScreenPriv
= (miBSScreenPtr
) pScreen
->devPrivates
[miBSScreenIndex
].ptr
;
422 pScreen
->CloseScreen
= pScreenPriv
->CloseScreen
;
423 pScreen
->GetImage
= pScreenPriv
->GetImage
;
424 pScreen
->GetSpans
= pScreenPriv
->GetSpans
;
425 pScreen
->ChangeWindowAttributes
= pScreenPriv
->ChangeWindowAttributes
;
426 pScreen
->CreateGC
= pScreenPriv
->CreateGC
;
428 xfree ((pointer
) pScreenPriv
);
430 return (*pScreen
->CloseScreen
) (i
, pScreen
);
433 static void miBSFillVirtualBits(DrawablePtr pDrawable
, GCPtr pGC
,
434 RegionPtr pRgn
, int x
, int y
, int state
,
435 PixUnion pixunion
, unsigned long planemask
);
438 miBSGetImage (pDrawable
, sx
, sy
, w
, h
, format
, planemask
, pdstLine
)
439 DrawablePtr pDrawable
;
442 unsigned long planemask
;
445 ScreenPtr pScreen
= pDrawable
->pScreen
;
449 SCREEN_PROLOGUE (pScreen
, GetImage
);
451 if (pDrawable
->type
!= DRAWABLE_PIXMAP
&&
452 ((WindowPtr
) pDrawable
)->visibility
!= VisibilityUnobscured
)
455 miBSWindowPtr pWindowPriv
;
457 WindowPtr pWin
, pSrcWin
;
465 pWin
= (WindowPtr
) pDrawable
;
467 depth
= pDrawable
->depth
;
468 bounds
.x1
= sx
+ pDrawable
->x
;
469 bounds
.y1
= sy
+ pDrawable
->y
;
470 bounds
.x2
= bounds
.x1
+ w
;
471 bounds
.y2
= bounds
.y1
+ h
;
472 REGION_INIT(pScreen
, &Remaining
, &bounds
, 0);
475 bounds
.x1
= sx
+ pDrawable
->x
- pWin
->drawable
.x
;
476 bounds
.y1
= sy
+ pDrawable
->y
- pWin
->drawable
.y
;
477 bounds
.x2
= bounds
.x1
+ w
;
478 bounds
.y2
= bounds
.y1
+ h
;
479 if (pWin
->viewable
&& pWin
->backStorage
&&
480 pWin
->drawable
.depth
== depth
&&
481 (RECT_IN_REGION(pScreen
, &(pWindowPriv
=
482 (miBSWindowPtr
) pWin
->backStorage
)->SavedRegion
,
483 &bounds
) != rgnOUT
||
484 RECT_IN_REGION(pScreen
, &Remaining
,
485 REGION_EXTENTS(pScreen
, &pWin
->borderSize
)) != rgnOUT
))
489 XID subWindowMode
= IncludeInferiors
;
492 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, w
, h
, depth
);
495 pGC
= GetScratchGC (depth
, pScreen
);
498 (*pScreen
->DestroyPixmap
) (pPixmap
);
501 ChangeGC (pGC
, GCSubwindowMode
, &subWindowMode
);
502 ValidateGC ((DrawablePtr
)pPixmap
, pGC
);
503 REGION_NULL(pScreen
, &Border
);
504 REGION_NULL(pScreen
, &Inside
);
505 pSrcWin
= (WindowPtr
) pDrawable
;
510 x
+= pSrcWin
->origin
.x
;
511 y
+= pSrcWin
->origin
.y
;
512 pSrcWin
= pSrcWin
->parent
;
514 (*pGC
->ops
->CopyArea
) ((DrawablePtr
)pSrcWin
,
515 (DrawablePtr
)pPixmap
, pGC
,
518 REGION_SUBTRACT(pScreen
, &Remaining
, &Remaining
,
519 &((WindowPtr
) pDrawable
)->borderClip
);
522 REGION_INTERSECT(pScreen
, &Inside
, &Remaining
, &pWin
->winSize
);
523 REGION_TRANSLATE(pScreen
, &Inside
,
526 REGION_INTERSECT(pScreen
, &Inside
, &Inside
,
527 &pWindowPriv
->SavedRegion
);
529 /* offset of sub-window in GetImage pixmap */
530 xoff
= pWin
->drawable
.x
- pDrawable
->x
- sx
;
531 yoff
= pWin
->drawable
.y
- pDrawable
->y
- sy
;
533 if (REGION_NUM_RECTS(&Inside
) > 0)
535 switch (pWindowPriv
->status
)
538 pBox
= REGION_RECTS(&Inside
);
539 for (n
= REGION_NUM_RECTS(&Inside
); --n
>= 0;)
541 (*pGC
->ops
->CopyArea
) (
542 (DrawablePtr
)pWindowPriv
->pBackingPixmap
,
543 (DrawablePtr
)pPixmap
, pGC
,
544 pBox
->x1
- pWindowPriv
->x
,
545 pBox
->y1
- pWindowPriv
->y
,
555 if (pWindowPriv
->backgroundState
== BackgroundPixmap
||
556 pWindowPriv
->backgroundState
== BackgroundPixel
)
557 miBSFillVirtualBits ((DrawablePtr
) pPixmap
, pGC
, &Inside
,
559 (int) pWindowPriv
->backgroundState
,
560 pWindowPriv
->background
, ~0L);
564 REGION_SUBTRACT(pScreen
, &Border
, &pWin
->borderSize
,
566 REGION_INTERSECT(pScreen
, &Border
, &Border
, &Remaining
);
567 if (REGION_NUM_RECTS(&Border
) > 0)
569 REGION_TRANSLATE(pScreen
, &Border
, -pWin
->drawable
.x
,
571 miBSFillVirtualBits ((DrawablePtr
) pPixmap
, pGC
, &Border
,
573 pWin
->borderIsPixel
? (int)BackgroundPixel
: (int)BackgroundPixmap
,
578 if (pWin
->viewable
&& pWin
->firstChild
)
579 pWin
= pWin
->firstChild
;
582 while (!pWin
->nextSib
&& pWin
!= (WindowPtr
) pDrawable
)
584 if (pWin
== (WindowPtr
) pDrawable
)
586 pWin
= pWin
->nextSib
;
590 REGION_UNINIT(pScreen
, &Remaining
);
594 REGION_UNINIT(pScreen
, &Border
);
595 REGION_UNINIT(pScreen
, &Inside
);
596 (*pScreen
->GetImage
) ((DrawablePtr
) pPixmap
,
597 0, 0, w
, h
, format
, planemask
, pdstLine
);
598 (*pScreen
->DestroyPixmap
) (pPixmap
);
609 (*pScreen
->GetImage
) (pDrawable
, sx
, sy
, w
, h
,
610 format
, planemask
, pdstLine
);
613 SCREEN_EPILOGUE (pScreen
, GetImage
, miBSGetImage
);
617 miBSGetSpans (pDrawable
, wMax
, ppt
, pwidth
, nspans
, pdstStart
)
618 DrawablePtr pDrawable
;
625 ScreenPtr pScreen
= pDrawable
->pScreen
;
631 SCREEN_PROLOGUE (pScreen
, GetSpans
);
633 if (pDrawable
->type
!= DRAWABLE_PIXMAP
&& ((WindowPtr
) pDrawable
)->backStorage
)
636 miBSWindowPtr pWindowPriv
;
639 pWin
= (WindowPtr
) pDrawable
;
640 pWindowPriv
= (miBSWindowPtr
) pWin
->backStorage
;
641 pPixmap
= pWindowPriv
->pBackingPixmap
;
645 bounds
.x2
= bounds
.x1
+ *pwidth
;
647 for (i
= 0; i
< nspans
; i
++)
649 if (ppt
[i
].x
< bounds
.x1
)
650 bounds
.x1
= ppt
[i
].x
;
651 if (ppt
[i
].x
+ pwidth
[i
] > bounds
.x2
)
652 bounds
.x2
= ppt
[i
].x
+ pwidth
[i
];
653 if (ppt
[i
].y
< bounds
.y1
)
654 bounds
.y1
= ppt
[i
].y
;
655 else if (ppt
[i
].y
> bounds
.y2
)
656 bounds
.y2
= ppt
[i
].y
;
659 switch (RECT_IN_REGION(pScreen
, &pWindowPriv
->SavedRegion
, &bounds
))
664 miCreateBSPixmap (pWin
, NullBox
);
665 if (!(pPixmap
= pWindowPriv
->pBackingPixmap
))
668 pWindowPriv
->status
= StatusNoPixmap
;
669 pGC
= GetScratchGC(pPixmap
->drawable
.depth
,
670 pPixmap
->drawable
.pScreen
);
673 ValidateGC ((DrawablePtr
) pPixmap
, pGC
);
674 (*pGC
->ops
->CopyArea
)
675 (pDrawable
, (DrawablePtr
) pPixmap
, pGC
,
676 bounds
.x1
, bounds
.y1
,
677 bounds
.x2
- bounds
.x1
, bounds
.y2
- bounds
.y1
,
678 bounds
.x1
+ pPixmap
->drawable
.x
- pWin
->drawable
.x
-
680 bounds
.y1
+ pPixmap
->drawable
.y
- pWin
->drawable
.y
-
684 pWindowPriv
->status
= StatusContents
;
689 miCreateBSPixmap (pWin
, NullBox
);
690 if (!(pPixmap
= pWindowPriv
->pBackingPixmap
))
693 dx
= pPixmap
->drawable
.x
- pWin
->drawable
.x
- pWindowPriv
->x
;
694 dy
= pPixmap
->drawable
.y
- pWin
->drawable
.y
- pWindowPriv
->y
;
695 for (i
= 0; i
< nspans
; i
++)
700 (*pScreen
->GetSpans
) ((DrawablePtr
) pPixmap
, wMax
, ppt
, pwidth
,
704 (*pScreen
->GetSpans
) (pDrawable
, wMax
, ppt
, pwidth
, nspans
,
711 (*pScreen
->GetSpans
) (pDrawable
, wMax
, ppt
, pwidth
, nspans
, pdstStart
);
714 SCREEN_EPILOGUE (pScreen
, GetSpans
, miBSGetSpans
);
718 miBSChangeWindowAttributes (pWin
, mask
)
725 pScreen
= pWin
->drawable
.pScreen
;
727 SCREEN_PROLOGUE (pScreen
, ChangeWindowAttributes
);
729 ret
= (*pScreen
->ChangeWindowAttributes
) (pWin
, mask
);
731 if (ret
&& (mask
& CWBackingStore
))
733 if (pWin
->backingStore
!= NotUseful
|| pWin
->DIXsaveUnder
)
739 SCREEN_EPILOGUE (pScreen
, ChangeWindowAttributes
, miBSChangeWindowAttributes
);
745 * GC Create wrapper. Set up the cheap GC func wrappers to track
746 * GC validation on BackingStore windows
753 ScreenPtr pScreen
= pGC
->pScreen
;
756 SCREEN_PROLOGUE (pScreen
, CreateGC
);
758 if ( (ret
= (*pScreen
->CreateGC
) (pGC
)) )
760 pGC
->devPrivates
[miBSGCIndex
].ptr
= (pointer
) pGC
->funcs
;
761 pGC
->funcs
= &miBSCheapGCFuncs
;
764 SCREEN_EPILOGUE (pScreen
, CreateGC
, miBSCreateGC
);
770 miBSDestroyWindow (pWin
)
773 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
776 SCREEN_PROLOGUE (pScreen
, DestroyWindow
);
778 ret
= (*pScreen
->DestroyWindow
) (pWin
);
782 SCREEN_EPILOGUE (pScreen
, DestroyWindow
, miBSDestroyWindow
);
788 * cheap GC func wrappers. Simply track validation on windows
789 * with backing store to enable the real func/op wrappers
793 miBSCheapValidateGC (pGC
, stateChanges
, pDrawable
)
795 unsigned long stateChanges
;
796 DrawablePtr pDrawable
;
798 CHEAP_FUNC_PROLOGUE (pGC
);
800 if (pDrawable
->type
!= DRAWABLE_PIXMAP
&&
801 ((WindowPtr
) pDrawable
)->backStorage
!= NULL
&&
802 miBSCreateGCPrivate (pGC
))
804 (*pGC
->funcs
->ValidateGC
) (pGC
, stateChanges
, pDrawable
);
808 (*pGC
->funcs
->ValidateGC
) (pGC
, stateChanges
, pDrawable
);
810 /* rewrap funcs as Validate may have changed them */
811 pGC
->devPrivates
[miBSGCIndex
].ptr
= (pointer
) pGC
->funcs
;
813 CHEAP_FUNC_EPILOGUE (pGC
);
818 miBSCheapChangeGC (pGC
, mask
)
822 CHEAP_FUNC_PROLOGUE (pGC
);
824 (*pGC
->funcs
->ChangeGC
) (pGC
, mask
);
826 CHEAP_FUNC_EPILOGUE (pGC
);
830 miBSCheapCopyGC (pGCSrc
, mask
, pGCDst
)
831 GCPtr pGCSrc
, pGCDst
;
834 CHEAP_FUNC_PROLOGUE (pGCDst
);
836 (*pGCDst
->funcs
->CopyGC
) (pGCSrc
, mask
, pGCDst
);
838 CHEAP_FUNC_EPILOGUE (pGCDst
);
842 miBSCheapDestroyGC (pGC
)
845 CHEAP_FUNC_PROLOGUE (pGC
);
847 (*pGC
->funcs
->DestroyGC
) (pGC
);
849 /* leave it unwrapped */
853 miBSCheapChangeClip (pGC
, type
, pvalue
, nrects
)
859 CHEAP_FUNC_PROLOGUE (pGC
);
861 (*pGC
->funcs
->ChangeClip
) (pGC
, type
, pvalue
, nrects
);
863 CHEAP_FUNC_EPILOGUE (pGC
);
867 miBSCheapCopyClip(pgcDst
, pgcSrc
)
868 GCPtr pgcDst
, pgcSrc
;
870 CHEAP_FUNC_PROLOGUE (pgcDst
);
872 (* pgcDst
->funcs
->CopyClip
)(pgcDst
, pgcSrc
);
874 CHEAP_FUNC_EPILOGUE (pgcDst
);
878 miBSCheapDestroyClip(pGC
)
881 CHEAP_FUNC_PROLOGUE (pGC
);
883 (* pGC
->funcs
->DestroyClip
)(pGC
);
885 CHEAP_FUNC_EPILOGUE (pGC
);
889 * create the full func/op wrappers for a GC
893 miBSCreateGCPrivate (pGC
)
898 pPriv
= (miBSGCRec
*) xalloc (sizeof (miBSGCRec
));
901 pPriv
->pBackingGC
= NULL
;
902 pPriv
->guarantee
= GuaranteeNothing
;
903 pPriv
->serialNumber
= 0;
904 pPriv
->stateChanges
= (1 << (GCLastBit
+ 1)) - 1;
905 pPriv
->wrapOps
= pGC
->ops
;
906 pPriv
->wrapFuncs
= pGC
->funcs
;
907 pGC
->funcs
= &miBSGCFuncs
;
908 pGC
->ops
= &miBSGCOps
;
909 pGC
->devPrivates
[miBSGCIndex
].ptr
= (pointer
) pPriv
;
914 miBSDestroyGCPrivate (GCPtr pGC
)
918 pPriv
= (miBSGCRec
*) pGC
->devPrivates
[miBSGCIndex
].ptr
;
921 pGC
->devPrivates
[miBSGCIndex
].ptr
= (pointer
) pPriv
->wrapFuncs
;
922 pGC
->funcs
= &miBSCheapGCFuncs
;
923 pGC
->ops
= pPriv
->wrapOps
;
924 if (pPriv
->pBackingGC
)
925 FreeGC (pPriv
->pBackingGC
, (GContext
) 0);
926 xfree ((pointer
) pPriv
);
931 * GC ops -- wrap each GC operation with our own function
935 *-----------------------------------------------------------------------
937 * Perform a FillSpans, routing output to backing-store as needed.
944 *-----------------------------------------------------------------------
947 miBSFillSpans(pDrawable
, pGC
, nInit
, pptInit
, pwidthInit
, fSorted
)
948 DrawablePtr pDrawable
;
950 int nInit
; /* number of spans to fill */
951 DDXPointPtr pptInit
; /* pointer to list of start points */
952 int *pwidthInit
; /* pointer to list of n widths */
955 DDXPointPtr pptCopy
, pptReset
;
957 SETUP_BACKING (pDrawable
, pGC
);
961 pptCopy
= (DDXPointPtr
)ALLOCATE_LOCAL(nInit
*sizeof(DDXPointRec
));
962 pwidthCopy
=(int *)ALLOCATE_LOCAL(nInit
*sizeof(int));
963 if (pptCopy
&& pwidthCopy
)
965 copyData(pptInit
, pptCopy
, nInit
, MoreCopy0
);
966 memmove((char *)pwidthCopy
,(char *)pwidthInit
,nInit
*sizeof(int));
968 (* pGC
->ops
->FillSpans
)(pDrawable
, pGC
, nInit
, pptInit
,
969 pwidthInit
, fSorted
);
970 if (pGC
->miTranslate
)
976 dx
= pDrawable
->x
- pBackingDrawable
->x
;
977 dy
= pDrawable
->y
- pBackingDrawable
->y
;
986 (* pBackingGC
->ops
->FillSpans
)(pBackingDrawable
,
987 pBackingGC
, nInit
, pptCopy
, pwidthCopy
,
990 if (pwidthCopy
) DEALLOCATE_LOCAL(pwidthCopy
);
991 if (pptCopy
) DEALLOCATE_LOCAL(pptCopy
);
997 *-----------------------------------------------------------------------
999 * Perform a SetSpans, routing output to backing-store as needed.
1006 *-----------------------------------------------------------------------
1009 miBSSetSpans(pDrawable
, pGC
, psrc
, ppt
, pwidth
, nspans
, fSorted
)
1010 DrawablePtr pDrawable
;
1018 DDXPointPtr pptCopy
, pptReset
;
1020 SETUP_BACKING (pDrawable
, pGC
);
1024 pptCopy
= (DDXPointPtr
)ALLOCATE_LOCAL(nspans
*sizeof(DDXPointRec
));
1025 pwidthCopy
=(int *)ALLOCATE_LOCAL(nspans
*sizeof(int));
1026 if (pptCopy
&& pwidthCopy
)
1028 copyData(ppt
, pptCopy
, nspans
, MoreCopy0
);
1029 memmove((char *)pwidthCopy
,(char *)pwidth
,nspans
*sizeof(int));
1031 (* pGC
->ops
->SetSpans
)(pDrawable
, pGC
, psrc
, ppt
, pwidth
,
1033 if (pGC
->miTranslate
)
1039 dx
= pDrawable
->x
- pBackingDrawable
->x
;
1040 dy
= pDrawable
->y
- pBackingDrawable
->y
;
1049 (* pBackingGC
->ops
->SetSpans
)(pBackingDrawable
, pBackingGC
,
1050 psrc
, pptCopy
, pwidthCopy
, nspans
, fSorted
);
1052 if (pwidthCopy
) DEALLOCATE_LOCAL(pwidthCopy
);
1053 if (pptCopy
) DEALLOCATE_LOCAL(pptCopy
);
1059 *-----------------------------------------------------------------------
1061 * Perform a PutImage, routing output to backing-store as needed.
1068 *-----------------------------------------------------------------------
1071 miBSPutImage(pDrawable
, pGC
, depth
, x
, y
, w
, h
, leftPad
, format
, pBits
)
1072 DrawablePtr pDrawable
;
1083 SETUP_BACKING (pDrawable
, pGC
);
1087 (*pGC
->ops
->PutImage
)(pDrawable
, pGC
,
1088 depth
, x
, y
, w
, h
, leftPad
, format
, pBits
);
1089 (*pBackingGC
->ops
->PutImage
)(pBackingDrawable
, pBackingGC
,
1090 depth
, x
- pBackingStore
->x
, y
- pBackingStore
->y
,
1091 w
, h
, leftPad
, format
, pBits
);
1096 typedef RegionPtr (* CopyAreaProcPtr
)(DrawablePtr
, DrawablePtr
, GCPtr
,
1097 int, int, int, int, int, int);
1098 typedef RegionPtr (* CopyPlaneProcPtr
)(DrawablePtr
, DrawablePtr
, GCPtr
,
1099 int, int, int, int, int, int,
1100 unsigned long bitPlane
);
1102 *-----------------------------------------------------------------------
1104 * Perform a CopyArea or CopyPlane within a window that has backing
1108 * TRUE if the copy was performed or FALSE if a regular one should
1112 * Things are copied (no s***!)
1115 * The idea here is to form two regions that cover the source box.
1116 * One contains the exposed rectangles while the other contains
1117 * the obscured ones. An array of <box, drawable> pairs is then
1118 * formed where the <box> indicates the area to be copied and the
1119 * <drawable> indicates from where it is to be copied (exposed regions
1120 * come from the screen while obscured ones come from the backing
1121 * pixmap). The array 'sequence' is then filled with the indices of
1122 * the pairs in the order in which they should be copied to prevent
1123 * things from getting screwed up. A call is also made through the
1124 * backingGC to take care of any copying into the backing pixmap.
1126 *-----------------------------------------------------------------------
1130 WindowPtr pWin
, /* Window being scrolled */
1131 GCPtr pGC
, /* GC we're called through */
1132 int srcx
, /* X of source rectangle */
1133 int srcy
, /* Y of source rectangle */
1134 int w
, /* Width of source rectangle */
1135 int h
, /* Height of source rectangle */
1136 int dstx
, /* X of destination rectangle */
1137 int dsty
, /* Y of destination rectangle */
1138 unsigned long plane
, /* Plane to copy (0 for CopyArea) */
1139 CopyPlaneProcPtr copyProc
, /* Procedure to call to perform the copy */
1140 RegionPtr
*ppRgn
) /* resultant Graphics Expose region */
1142 RegionPtr pRgnExp
; /* Exposed region */
1143 RegionPtr pRgnObs
; /* Obscured region */
1144 BoxRec box
; /* Source box (screen coord) */
1146 BoxPtr pBox
; /* Source box */
1149 } source
; /* Place from which to copy */
1150 } *boxes
; /* Array of box/drawable pairs covering
1152 int *sequence
; /* Sequence of boxes to move */
1156 Bool graphicsExposures
;
1157 CopyPlaneProcPtr pixCopyProc
;
1158 int numRectsExp
, numRectsObs
;
1159 BoxPtr pBoxExp
, pBoxObs
;
1161 SETUP_BACKING (pWin
, pGC
);
1165 * Create a region of exposed boxes in pRgnExp.
1167 box
.x1
= srcx
+ pWin
->drawable
.x
;
1168 box
.x2
= box
.x1
+ w
;
1169 box
.y1
= srcy
+ pWin
->drawable
.y
;
1170 box
.y2
= box
.y1
+ h
;
1172 pRgnExp
= REGION_CREATE(pGC
->pScreen
, &box
, 1);
1173 REGION_INTERSECT(pGC
->pScreen
, pRgnExp
, pRgnExp
, &pWin
->clipList
);
1174 pRgnObs
= REGION_CREATE(pGC
->pScreen
, NULL
, 1);
1175 REGION_INVERSE( pGC
->pScreen
, pRgnObs
, pRgnExp
, &box
);
1178 * Translate regions into window coordinates for proper calls
1179 * to the copyProc, then make sure none of the obscured region sticks
1180 * into invalid areas of the backing pixmap.
1182 REGION_TRANSLATE(pGC
->pScreen
, pRgnExp
,
1185 REGION_TRANSLATE(pGC
->pScreen
, pRgnObs
,
1188 REGION_INTERSECT(pGC
->pScreen
, pRgnObs
, pRgnObs
, &pBackingStore
->SavedRegion
);
1191 * If the obscured region is empty, there's no point being fancy.
1193 if (!REGION_NOTEMPTY(pGC
->pScreen
, pRgnObs
))
1195 REGION_DESTROY(pGC
->pScreen
, pRgnExp
);
1196 REGION_DESTROY(pGC
->pScreen
, pRgnObs
);
1201 numRectsExp
= REGION_NUM_RECTS(pRgnExp
);
1202 pBoxExp
= REGION_RECTS(pRgnExp
);
1203 pBoxObs
= REGION_RECTS(pRgnObs
);
1204 numRectsObs
= REGION_NUM_RECTS(pRgnObs
);
1205 nrects
= numRectsExp
+ numRectsObs
;
1207 boxes
= (struct BoxDraw
*)ALLOCATE_LOCAL(nrects
* sizeof(struct BoxDraw
));
1208 sequence
= (int *) ALLOCATE_LOCAL(nrects
* sizeof(int));
1211 if (!boxes
|| !sequence
)
1213 if (sequence
) DEALLOCATE_LOCAL(sequence
);
1214 if (boxes
) DEALLOCATE_LOCAL(boxes
);
1215 REGION_DESTROY(pGC
->pScreen
, pRgnExp
);
1216 REGION_DESTROY(pGC
->pScreen
, pRgnObs
);
1222 * Order the boxes in the two regions so we know from which drawable
1223 * to copy which box, storing the result in the boxes array
1225 for (i
= 0, j
= 0, k
= 0;
1226 (i
< numRectsExp
) && (j
< numRectsObs
);
1229 if (pBoxExp
[i
].y1
< pBoxObs
[j
].y1
)
1231 boxes
[k
].pBox
= &pBoxExp
[i
];
1232 boxes
[k
].source
= win
;
1235 else if ((pBoxObs
[j
].y1
< pBoxExp
[i
].y1
) ||
1236 (pBoxObs
[j
].x1
< pBoxExp
[i
].x1
))
1238 boxes
[k
].pBox
= &pBoxObs
[j
];
1239 boxes
[k
].source
= pix
;
1244 boxes
[k
].pBox
= &pBoxExp
[i
];
1245 boxes
[k
].source
= win
;
1251 * Catch any leftover boxes from either region (note that only
1252 * one can have leftover boxes...)
1254 if (i
!= numRectsExp
)
1258 boxes
[k
].pBox
= &pBoxExp
[i
];
1259 boxes
[k
].source
= win
;
1262 } while (i
< numRectsExp
);
1269 boxes
[k
].pBox
= &pBoxObs
[j
];
1270 boxes
[k
].source
= pix
;
1273 } while (j
< numRectsObs
);
1279 * Scroll up or vertically stationary, so vertical order is ok.
1284 * Scroll left or horizontally stationary, so horizontal order
1287 for (i
= 0; i
< nrects
; i
++)
1295 * Scroll right. Need to reverse the rectangles within each
1298 for (i
= 0, j
= 1, k
= 0;
1302 y
= boxes
[i
].pBox
->y1
;
1303 while ((j
< nrects
) && (boxes
[j
].pBox
->y1
== y
))
1307 for (j
--; j
>= k
; j
--, i
++)
1317 * Scroll down. Must reverse vertical banding, at least.
1322 * Scroll left. Horizontal order is ok.
1324 for (i
= nrects
- 1, j
= i
- 1, k
= i
, l
= 0;
1329 * Find extent of current horizontal band, then reverse
1330 * the order of the whole band.
1332 y
= boxes
[i
].pBox
->y1
;
1333 while ((j
>= 0) && (boxes
[j
].pBox
->y1
== y
))
1337 for (j
++; j
<= k
; j
++, i
--, l
++)
1346 * Scroll right or horizontal stationary.
1347 * Reverse horizontal order as well (if stationary, horizontal
1348 * order can be swapped without penalty and this is faster
1351 for (i
= 0, j
= nrects
- 1; i
< nrects
; i
++, j
--)
1359 * XXX: To avoid getting multiple NoExpose events from this operation,
1360 * we turn OFF graphicsExposures in the gc and deal with any uncopied
1361 * areas later, if there's something not in backing-store.
1364 graphicsExposures
= pGC
->graphicsExposures
;
1365 pGC
->graphicsExposures
= FALSE
;
1371 * Figure out which copy procedure to use from the backing GC. Note we
1372 * must do this because some implementations (sun's, e.g.) have
1373 * pBackingGC a fake GC with the real one below it, thus the devPriv for
1374 * pBackingGC won't be what the output library expects.
1378 pixCopyProc
= pBackingGC
->ops
->CopyPlane
;
1382 pixCopyProc
= (CopyPlaneProcPtr
)pBackingGC
->ops
->CopyArea
;
1385 for (i
= 0; i
< nrects
; i
++)
1387 pBox
= boxes
[sequence
[i
]].pBox
;
1390 * If we're copying from the pixmap, we need to place its contents
1391 * onto the screen before scrolling the pixmap itself. If we're copying
1392 * from the window, we need to copy its contents into the pixmap before
1393 * we scroll the window itself.
1395 if (boxes
[sequence
[i
]].source
== pix
)
1397 (void) (* copyProc
) (pBackingDrawable
, &(pWin
->drawable
), pGC
,
1398 pBox
->x1
- pBackingStore
->x
,
1399 pBox
->y1
- pBackingStore
->y
,
1400 pBox
->x2
- pBox
->x1
, pBox
->y2
- pBox
->y1
,
1401 pBox
->x1
+ dx
, pBox
->y1
+ dy
, plane
);
1402 (void) (* pixCopyProc
) (pBackingDrawable
, pBackingDrawable
, pBackingGC
,
1403 pBox
->x1
- pBackingStore
->x
,
1404 pBox
->y1
- pBackingStore
->y
,
1405 pBox
->x2
- pBox
->x1
, pBox
->y2
- pBox
->y1
,
1406 pBox
->x1
+ dx
- pBackingStore
->x
,
1407 pBox
->y1
+ dy
- pBackingStore
->y
, plane
);
1411 (void) (* pixCopyProc
) (&(pWin
->drawable
), pBackingDrawable
, pBackingGC
,
1413 pBox
->x2
- pBox
->x1
, pBox
->y2
- pBox
->y1
,
1414 pBox
->x1
+ dx
- pBackingStore
->x
,
1415 pBox
->y1
+ dy
- pBackingStore
->y
, plane
);
1416 (void) (* copyProc
) (&(pWin
->drawable
), &(pWin
->drawable
), pGC
,
1418 pBox
->x2
- pBox
->x1
, pBox
->y2
- pBox
->y1
,
1419 pBox
->x1
+ dx
, pBox
->y1
+ dy
, plane
);
1422 DEALLOCATE_LOCAL(sequence
);
1423 DEALLOCATE_LOCAL(boxes
);
1425 pGC
->graphicsExposures
= graphicsExposures
;
1427 * Form union of rgnExp and rgnObs and see if covers entire area
1428 * to be copied. Store the resultant region for miBSCopyArea
1429 * to return to dispatch which will send the appropriate expose
1432 REGION_UNION(pGC
->pScreen
, pRgnExp
, pRgnExp
, pRgnObs
);
1437 if (RECT_IN_REGION(pGC
->pScreen
, pRgnExp
, &box
) == rgnIN
)
1439 REGION_EMPTY(pGC
->pScreen
, pRgnExp
);
1443 REGION_INVERSE( pGC
->pScreen
, pRgnExp
, pRgnExp
, &box
);
1444 REGION_TRANSLATE( pGC
->pScreen
, pRgnExp
,
1445 dx
+ pWin
->drawable
.x
,
1446 dy
+ pWin
->drawable
.y
);
1447 REGION_INTERSECT( pGC
->pScreen
, pRgnObs
, pRgnExp
, &pWin
->clipList
);
1448 (*pWin
->drawable
.pScreen
->PaintWindowBackground
) (pWin
,
1449 pRgnObs
, PW_BACKGROUND
);
1450 REGION_TRANSLATE( pGC
->pScreen
, pRgnExp
,
1453 miBSClearBackingRegion (pWin
, pRgnExp
);
1455 if (graphicsExposures
)
1458 REGION_DESTROY(pGC
->pScreen
, pRgnExp
);
1459 REGION_DESTROY(pGC
->pScreen
, pRgnObs
);
1465 *-----------------------------------------------------------------------
1467 * Perform a CopyArea from the source to the destination, extracting
1468 * from the source's backing-store and storing into the destination's
1469 * backing-store without messing anything up. If the source and
1470 * destination are different, there's not too much to worry about:
1471 * we can just issue several calls to the regular CopyArea function.
1478 *-----------------------------------------------------------------------
1481 miBSCopyArea (pSrc
, pDst
, pGC
, srcx
, srcy
, w
, h
, dstx
, dsty
)
1494 int bsrcx
, bsrcy
, bw
, bh
, bdstx
, bdsty
;
1495 RegionPtr pixExposed
= 0, winExposed
= 0;
1497 SETUP_BACKING(pDst
, pGC
);
1501 if ((pSrc
!= pDst
) ||
1502 (!miBSDoCopy((WindowPtr
)pSrc
, pGC
, srcx
, srcy
, w
, h
, dstx
, dsty
,
1503 (unsigned long) 0, (CopyPlaneProcPtr
)pGC
->ops
->CopyArea
,
1507 * always copy to the backing store first, miBSDoCopy
1508 * returns FALSE if the *source* region is disjoint
1509 * from the backing store saved region. So, copying
1510 * *to* the backing store is always safe
1512 if (pGC
->clientClipType
!= CT_PIXMAP
)
1515 * adjust srcx, srcy, w, h, dstx, dsty to be clipped to
1516 * the backing store. An unnecessary optimisation,
1517 * but a useful one when GetSpans is slow.
1519 pExtents
= REGION_EXTENTS(pDst
->pScreen
,
1520 (RegionPtr
)pBackingGC
->clientClip
);
1527 dx
= pExtents
->x1
- bdstx
;
1534 dy
= pExtents
->y1
- bdsty
;
1541 dx
= (bdstx
+ bw
) - pExtents
->x2
;
1544 dy
= (bdsty
+ bh
) - pExtents
->y2
;
1547 if (bw
> 0 && bh
> 0)
1548 pixExposed
= (* pBackingGC
->ops
->CopyArea
) (pSrc
,
1549 pBackingDrawable
, pBackingGC
,
1550 bsrcx
, bsrcy
, bw
, bh
, bdstx
- pBackingStore
->x
,
1551 bdsty
- pBackingStore
->y
);
1554 pixExposed
= (* pBackingGC
->ops
->CopyArea
) (pSrc
,
1555 pBackingDrawable
, pBackingGC
,
1557 dstx
- pBackingStore
->x
, dsty
- pBackingStore
->y
);
1559 winExposed
= (* pGC
->ops
->CopyArea
) (pSrc
, pDst
, pGC
, srcx
, srcy
, w
, h
, dstx
, dsty
);
1563 * compute the composite graphics exposure region
1568 REGION_UNION(pDst
->pScreen
, winExposed
, winExposed
, pixExposed
);
1569 REGION_DESTROY(pDst
->pScreen
, pixExposed
);
1572 winExposed
= pixExposed
;
1580 *-----------------------------------------------------------------------
1588 *-----------------------------------------------------------------------
1591 miBSCopyPlane (pSrc
, pDst
, pGC
, srcx
, srcy
, w
, h
, dstx
, dsty
, plane
)
1601 unsigned long plane
;
1605 int bsrcx
, bsrcy
, bw
, bh
, bdstx
, bdsty
;
1606 RegionPtr winExposed
= 0, pixExposed
= 0;
1607 SETUP_BACKING(pDst
, pGC
);
1611 if ((pSrc
!= pDst
) ||
1612 (!miBSDoCopy((WindowPtr
)pSrc
, pGC
, srcx
, srcy
, w
, h
, dstx
, dsty
,
1613 plane
, pGC
->ops
->CopyPlane
, &winExposed
)))
1616 * always copy to the backing store first, miBSDoCopy
1617 * returns FALSE if the *source* region is disjoint
1618 * from the backing store saved region. So, copying
1619 * *to* the backing store is always safe
1621 if (pGC
->clientClipType
!= CT_PIXMAP
)
1624 * adjust srcx, srcy, w, h, dstx, dsty to be clipped to
1625 * the backing store. An unnecessary optimisation,
1626 * but a useful one when GetSpans is slow.
1628 pExtents
= REGION_EXTENTS(pDst
->pScreen
,
1629 (RegionPtr
)pBackingGC
->clientClip
);
1636 dx
= pExtents
->x1
- bdstx
;
1643 dy
= pExtents
->y1
- bdsty
;
1650 dx
= (bdstx
+ bw
) - pExtents
->x2
;
1653 dy
= (bdsty
+ bh
) - pExtents
->y2
;
1656 if (bw
> 0 && bh
> 0)
1657 pixExposed
= (* pBackingGC
->ops
->CopyPlane
) (pSrc
,
1659 pBackingGC
, bsrcx
, bsrcy
, bw
, bh
,
1660 bdstx
- pBackingStore
->x
,
1661 bdsty
- pBackingStore
->y
, plane
);
1664 pixExposed
= (* pBackingGC
->ops
->CopyPlane
) (pSrc
,
1666 pBackingGC
, srcx
, srcy
, w
, h
,
1667 dstx
- pBackingStore
->x
,
1668 dsty
- pBackingStore
->y
, plane
);
1670 winExposed
= (* pGC
->ops
->CopyPlane
) (pSrc
, pDst
, pGC
, srcx
, srcy
, w
, h
,
1676 * compute the composite graphics exposure region
1682 REGION_UNION(pDst
->pScreen
, winExposed
, winExposed
, pixExposed
);
1683 REGION_DESTROY(pDst
->pScreen
, pixExposed
);
1686 winExposed
= pixExposed
;
1694 *-----------------------------------------------------------------------
1696 * Perform a PolyPoint, routing output to backing-store as needed.
1703 *-----------------------------------------------------------------------
1706 miBSPolyPoint (pDrawable
, pGC
, mode
, npt
, pptInit
)
1707 DrawablePtr pDrawable
;
1709 int mode
; /* Origin or Previous */
1714 SETUP_BACKING (pDrawable
, pGC
);
1718 pptCopy
= (xPoint
*)ALLOCATE_LOCAL(npt
*sizeof(xPoint
));
1721 copyPoints(pptInit
, pptCopy
, npt
, mode
);
1723 (* pGC
->ops
->PolyPoint
) (pDrawable
, pGC
, mode
, npt
, pptInit
);
1725 (* pBackingGC
->ops
->PolyPoint
) (pBackingDrawable
,
1726 pBackingGC
, mode
, npt
, pptCopy
);
1728 DEALLOCATE_LOCAL(pptCopy
);
1735 *-----------------------------------------------------------------------
1737 * Perform a Polylines, routing output to backing-store as needed.
1743 *-----------------------------------------------------------------------
1746 miBSPolylines (pDrawable
, pGC
, mode
, npt
, pptInit
)
1747 DrawablePtr pDrawable
;
1751 DDXPointPtr pptInit
;
1753 DDXPointPtr pptCopy
;
1754 SETUP_BACKING (pDrawable
, pGC
);
1758 pptCopy
= (DDXPointPtr
)ALLOCATE_LOCAL(npt
*sizeof(DDXPointRec
));
1761 copyPoints(pptInit
, pptCopy
, npt
, mode
);
1763 (* pGC
->ops
->Polylines
)(pDrawable
, pGC
, mode
, npt
, pptInit
);
1764 (* pBackingGC
->ops
->Polylines
)(pBackingDrawable
,
1765 pBackingGC
, mode
, npt
, pptCopy
);
1766 DEALLOCATE_LOCAL(pptCopy
);
1773 *-----------------------------------------------------------------------
1774 * miBSPolySegment --
1775 * Perform a PolySegment, routing output to backing-store as needed.
1782 *-----------------------------------------------------------------------
1785 miBSPolySegment(pDrawable
, pGC
, nseg
, pSegs
)
1786 DrawablePtr pDrawable
;
1791 xSegment
*pSegsCopy
;
1793 SETUP_BACKING (pDrawable
, pGC
);
1797 pSegsCopy
= (xSegment
*)ALLOCATE_LOCAL(nseg
*sizeof(xSegment
));
1800 copyData(pSegs
, pSegsCopy
, nseg
<< 1, MoreCopy0
);
1802 (* pGC
->ops
->PolySegment
)(pDrawable
, pGC
, nseg
, pSegs
);
1803 (* pBackingGC
->ops
->PolySegment
)(pBackingDrawable
,
1804 pBackingGC
, nseg
, pSegsCopy
);
1806 DEALLOCATE_LOCAL(pSegsCopy
);
1813 *-----------------------------------------------------------------------
1814 * miBSPolyRectangle --
1815 * Perform a PolyRectangle, routing output to backing-store as needed.
1822 *-----------------------------------------------------------------------
1825 miBSPolyRectangle(pDrawable
, pGC
, nrects
, pRects
)
1826 DrawablePtr pDrawable
;
1831 xRectangle
*pRectsCopy
;
1832 SETUP_BACKING (pDrawable
, pGC
);
1836 pRectsCopy
=(xRectangle
*)ALLOCATE_LOCAL(nrects
*sizeof(xRectangle
));
1839 copyData(pRects
, pRectsCopy
, nrects
, MoreCopy2
);
1841 (* pGC
->ops
->PolyRectangle
)(pDrawable
, pGC
, nrects
, pRects
);
1842 (* pBackingGC
->ops
->PolyRectangle
)(pBackingDrawable
,
1843 pBackingGC
, nrects
, pRectsCopy
);
1845 DEALLOCATE_LOCAL(pRectsCopy
);
1852 *-----------------------------------------------------------------------
1854 * Perform a PolyArc, routing output to backing-store as needed.
1860 *-----------------------------------------------------------------------
1863 miBSPolyArc(pDrawable
, pGC
, narcs
, parcs
)
1864 DrawablePtr pDrawable
;
1870 SETUP_BACKING (pDrawable
, pGC
);
1874 pArcsCopy
= (xArc
*)ALLOCATE_LOCAL(narcs
*sizeof(xArc
));
1877 copyData(parcs
, pArcsCopy
, narcs
, MoreCopy4
);
1879 (* pGC
->ops
->PolyArc
)(pDrawable
, pGC
, narcs
, parcs
);
1880 (* pBackingGC
->ops
->PolyArc
)(pBackingDrawable
, pBackingGC
,
1883 DEALLOCATE_LOCAL(pArcsCopy
);
1890 *-----------------------------------------------------------------------
1891 * miBSFillPolygon --
1892 * Perform a FillPolygon, routing output to backing-store as needed.
1899 *-----------------------------------------------------------------------
1902 miBSFillPolygon(pDrawable
, pGC
, shape
, mode
, count
, pPts
)
1903 DrawablePtr pDrawable
;
1909 DDXPointPtr pPtsCopy
;
1910 SETUP_BACKING (pDrawable
, pGC
);
1914 pPtsCopy
= (DDXPointPtr
)ALLOCATE_LOCAL(count
*sizeof(DDXPointRec
));
1917 copyPoints(pPts
, pPtsCopy
, count
, mode
);
1918 (* pGC
->ops
->FillPolygon
)(pDrawable
, pGC
, shape
, mode
, count
, pPts
);
1919 (* pBackingGC
->ops
->FillPolygon
)(pBackingDrawable
,
1920 pBackingGC
, shape
, mode
,
1923 DEALLOCATE_LOCAL(pPtsCopy
);
1930 *-----------------------------------------------------------------------
1931 * miBSPolyFillRect --
1932 * Perform a PolyFillRect, routing output to backing-store as needed.
1939 *-----------------------------------------------------------------------
1942 miBSPolyFillRect(pDrawable
, pGC
, nrectFill
, prectInit
)
1943 DrawablePtr pDrawable
;
1945 int nrectFill
; /* number of rectangles to fill */
1946 xRectangle
*prectInit
; /* Pointer to first rectangle to fill */
1948 xRectangle
*pRectCopy
;
1949 SETUP_BACKING (pDrawable
, pGC
);
1954 (xRectangle
*)ALLOCATE_LOCAL(nrectFill
*sizeof(xRectangle
));
1957 copyData(prectInit
, pRectCopy
, nrectFill
, MoreCopy2
);
1959 (* pGC
->ops
->PolyFillRect
)(pDrawable
, pGC
, nrectFill
, prectInit
);
1960 (* pBackingGC
->ops
->PolyFillRect
)(pBackingDrawable
,
1961 pBackingGC
, nrectFill
, pRectCopy
);
1963 DEALLOCATE_LOCAL(pRectCopy
);
1970 *-----------------------------------------------------------------------
1971 * miBSPolyFillArc --
1972 * Perform a PolyFillArc, routing output to backing-store as needed.
1979 *-----------------------------------------------------------------------
1982 miBSPolyFillArc(pDrawable
, pGC
, narcs
, parcs
)
1983 DrawablePtr pDrawable
;
1989 SETUP_BACKING (pDrawable
, pGC
);
1993 pArcsCopy
= (xArc
*)ALLOCATE_LOCAL(narcs
*sizeof(xArc
));
1996 copyData(parcs
, pArcsCopy
, narcs
, MoreCopy4
);
1997 (* pGC
->ops
->PolyFillArc
)(pDrawable
, pGC
, narcs
, parcs
);
1998 (* pBackingGC
->ops
->PolyFillArc
)(pBackingDrawable
,
1999 pBackingGC
, narcs
, pArcsCopy
);
2000 DEALLOCATE_LOCAL(pArcsCopy
);
2008 *-----------------------------------------------------------------------
2010 * Perform a PolyText8, routing output to backing-store as needed.
2016 *-----------------------------------------------------------------------
2019 miBSPolyText8(pDrawable
, pGC
, x
, y
, count
, chars
)
2020 DrawablePtr pDrawable
;
2027 SETUP_BACKING (pDrawable
, pGC
);
2031 result
= (* pGC
->ops
->PolyText8
)(pDrawable
, pGC
, x
, y
, count
, chars
);
2032 (* pBackingGC
->ops
->PolyText8
)(pBackingDrawable
, pBackingGC
,
2033 x
- pBackingStore
->x
, y
- pBackingStore
->y
,
2041 *-----------------------------------------------------------------------
2043 * Perform a PolyText16, routing output to backing-store as needed.
2049 *-----------------------------------------------------------------------
2052 miBSPolyText16(pDrawable
, pGC
, x
, y
, count
, chars
)
2053 DrawablePtr pDrawable
;
2057 unsigned short *chars
;
2060 SETUP_BACKING (pDrawable
, pGC
);
2064 result
= (* pGC
->ops
->PolyText16
)(pDrawable
, pGC
, x
, y
, count
, chars
);
2065 (* pBackingGC
->ops
->PolyText16
)(pBackingDrawable
, pBackingGC
,
2066 x
- pBackingStore
->x
, y
- pBackingStore
->y
,
2075 *-----------------------------------------------------------------------
2077 * Perform a ImageText8, routing output to backing-store as needed.
2083 *-----------------------------------------------------------------------
2086 miBSImageText8(pDrawable
, pGC
, x
, y
, count
, chars
)
2087 DrawablePtr pDrawable
;
2093 SETUP_BACKING (pDrawable
, pGC
);
2096 (* pGC
->ops
->ImageText8
)(pDrawable
, pGC
, x
, y
, count
, chars
);
2097 (* pBackingGC
->ops
->ImageText8
)(pBackingDrawable
, pBackingGC
,
2098 x
- pBackingStore
->x
, y
- pBackingStore
->y
,
2105 *-----------------------------------------------------------------------
2106 * miBSImageText16 --
2107 * Perform a ImageText16, routing output to backing-store as needed.
2113 *-----------------------------------------------------------------------
2116 miBSImageText16(pDrawable
, pGC
, x
, y
, count
, chars
)
2117 DrawablePtr pDrawable
;
2121 unsigned short *chars
;
2123 SETUP_BACKING (pDrawable
, pGC
);
2126 (* pGC
->ops
->ImageText16
)(pDrawable
, pGC
, x
, y
, count
, chars
);
2127 (* pBackingGC
->ops
->ImageText16
)(pBackingDrawable
, pBackingGC
,
2128 x
- pBackingStore
->x
, y
- pBackingStore
->y
,
2135 *-----------------------------------------------------------------------
2136 * miBSImageGlyphBlt --
2137 * Perform a ImageGlyphBlt, routing output to backing-store as needed.
2143 *-----------------------------------------------------------------------
2146 miBSImageGlyphBlt(pDrawable
, pGC
, x
, y
, nglyph
, ppci
, pglyphBase
)
2147 DrawablePtr pDrawable
;
2150 unsigned int nglyph
;
2151 CharInfoPtr
*ppci
; /* array of character info */
2152 pointer pglyphBase
; /* start of array of glyphs */
2154 SETUP_BACKING (pDrawable
, pGC
);
2157 (* pGC
->ops
->ImageGlyphBlt
)(pDrawable
, pGC
, x
, y
, nglyph
, ppci
,
2159 (* pBackingGC
->ops
->ImageGlyphBlt
)(pBackingDrawable
, pBackingGC
,
2160 x
- pBackingStore
->x
, y
- pBackingStore
->y
,
2161 nglyph
, ppci
, pglyphBase
);
2167 *-----------------------------------------------------------------------
2168 * miBSPolyGlyphBlt --
2169 * Perform a PolyGlyphBlt, routing output to backing-store as needed.
2175 *-----------------------------------------------------------------------
2178 miBSPolyGlyphBlt(pDrawable
, pGC
, x
, y
, nglyph
, ppci
, pglyphBase
)
2179 DrawablePtr pDrawable
;
2182 unsigned int nglyph
;
2183 CharInfoPtr
*ppci
; /* array of character info */
2184 pointer pglyphBase
; /* start of array of glyphs */
2186 SETUP_BACKING (pDrawable
, pGC
);
2189 (* pGC
->ops
->PolyGlyphBlt
)(pDrawable
, pGC
, x
, y
, nglyph
,
2191 (* pBackingGC
->ops
->PolyGlyphBlt
)(pBackingDrawable
, pBackingGC
,
2192 x
- pBackingStore
->x
, y
- pBackingStore
->y
,
2193 nglyph
, ppci
, pglyphBase
);
2198 *-----------------------------------------------------------------------
2200 * Perform a PushPixels, routing output to backing-store as needed.
2206 *-----------------------------------------------------------------------
2209 miBSPushPixels(pGC
, pBitMap
, pDst
, w
, h
, x
, y
)
2215 SETUP_BACKING (pDst
, pGC
);
2218 (* pGC
->ops
->PushPixels
)(pGC
, pBitMap
, pDst
, w
, h
, x
, y
);
2219 if (pGC
->miTranslate
) {
2223 (* pBackingGC
->ops
->PushPixels
)(pBackingGC
, pBitMap
,
2224 pBackingDrawable
, w
, h
,
2225 x
- pBackingStore
->x
, y
- pBackingStore
->y
);
2231 *-----------------------------------------------------------------------
2232 * miBSClearBackingStore --
2233 * Clear the given area of the backing pixmap with the background of
2234 * the window, whatever it is. If generateExposures is TRUE, generate
2235 * exposure events for the area. Note that if the area has any
2236 * part outside the saved portions of the window, we do not allow the
2237 * count in the expose events to be 0, since there will be more
2238 * expose events to come.
2244 * Areas of pixmap are cleared and Expose events are generated.
2246 *-----------------------------------------------------------------------
2249 miBSClearBackingStore(pWin
, x
, y
, w
, h
, generateExposures
)
2255 Bool generateExposures
;
2259 miBSWindowPtr pBackingStore
;
2264 pointer gcvalues
[4];
2265 unsigned long gcmask
;
2269 PixUnion background
;
2270 char backgroundState
;
2273 pBackingStore
= (miBSWindowPtr
)pWin
->backStorage
;
2274 pScreen
= pWin
->drawable
.pScreen
;
2276 if ((pBackingStore
->status
== StatusNoPixmap
) ||
2277 (pBackingStore
->status
== StatusBadAlloc
))
2281 w
= (int) pWin
->drawable
.width
- x
;
2283 h
= (int) pWin
->drawable
.height
- y
;
2289 pRgn
= REGION_CREATE(pWin
->drawable
.pScreen
, &box
, 1);
2292 REGION_INTERSECT( pScreen
, pRgn
, pRgn
, &pBackingStore
->SavedRegion
);
2294 if (REGION_NOTEMPTY( pScreen
, pRgn
))
2297 * if clearing entire window, simply make new virtual
2298 * tile. For the root window, we also destroy the pixmap
2299 * to save a pile of memory
2301 if (x
== 0 && y
== 0 &&
2302 w
== pWin
->drawable
.width
&&
2303 h
== pWin
->drawable
.height
)
2306 miDestroyBSPixmap (pWin
);
2307 if (pBackingStore
->status
!= StatusContents
)
2308 miTileVirtualBS (pWin
);
2311 ts_x_origin
= ts_y_origin
= 0;
2313 backgroundState
= pWin
->backgroundState
;
2314 background
= pWin
->background
;
2315 if (backgroundState
== ParentRelative
) {
2319 while (pParent
->backgroundState
== ParentRelative
) {
2320 ts_x_origin
-= pParent
->origin
.x
;
2321 ts_y_origin
-= pParent
->origin
.y
;
2322 pParent
= pParent
->parent
;
2324 backgroundState
= pParent
->backgroundState
;
2325 background
= pParent
->background
;
2328 if ((backgroundState
!= None
) &&
2329 ((pBackingStore
->status
== StatusContents
) ||
2330 !SameBackground (pBackingStore
->backgroundState
,
2331 pBackingStore
->background
,
2335 if (!pBackingStore
->pBackingPixmap
)
2336 miCreateBSPixmap(pWin
, NullBox
);
2338 pGC
= GetScratchGC(pWin
->drawable
.depth
, pScreen
);
2339 if (pGC
&& pBackingStore
->pBackingPixmap
)
2342 * First take care of any ParentRelative stuff by altering the
2343 * tile/stipple origin to match the coordinates of the upper-left
2344 * corner of the first ancestor without a ParentRelative background.
2345 * This coordinate is, of course, negative.
2348 if (backgroundState
== BackgroundPixel
)
2350 gcvalues
[0] = (pointer
) background
.pixel
;
2351 gcvalues
[1] = (pointer
)FillSolid
;
2352 gcmask
= GCForeground
|GCFillStyle
;
2356 gcvalues
[0] = (pointer
)FillTiled
;
2357 gcvalues
[1] = (pointer
) background
.pixmap
;
2358 gcmask
= GCFillStyle
|GCTile
;
2360 gcvalues
[2] = (pointer
)(long)(ts_x_origin
- pBackingStore
->x
);
2361 gcvalues
[3] = (pointer
)(long)(ts_y_origin
- pBackingStore
->y
);
2362 gcmask
|= GCTileStipXOrigin
|GCTileStipYOrigin
;
2363 DoChangeGC(pGC
, gcmask
, (XID
*)gcvalues
, TRUE
);
2364 ValidateGC((DrawablePtr
)pBackingStore
->pBackingPixmap
, pGC
);
2367 * Figure out the array of rectangles to fill and fill them with
2368 * PolyFillRect in the proper mode, as set in the GC above.
2370 numRects
= REGION_NUM_RECTS(pRgn
);
2371 rects
= (xRectangle
*)ALLOCATE_LOCAL(numRects
*sizeof(xRectangle
));
2375 for (i
= 0, pBox
= REGION_RECTS(pRgn
);
2379 rects
[i
].x
= pBox
->x1
- pBackingStore
->x
;
2380 rects
[i
].y
= pBox
->y1
- pBackingStore
->y
;
2381 rects
[i
].width
= pBox
->x2
- pBox
->x1
;
2382 rects
[i
].height
= pBox
->y2
- pBox
->y1
;
2384 (* pGC
->ops
->PolyFillRect
) (
2385 (DrawablePtr
)pBackingStore
->pBackingPixmap
,
2386 pGC
, numRects
, rects
);
2387 DEALLOCATE_LOCAL(rects
);
2393 if (!generateExposures
)
2395 REGION_DESTROY(pScreen
, pRgn
);
2401 * result must be screen relative, but is currently
2402 * drawable relative.
2404 REGION_TRANSLATE(pScreen
, pRgn
, pWin
->drawable
.x
,
2410 REGION_DESTROY( pScreen
, pRgn
);
2417 miBSClearBackingRegion (pWin
, pRgn
)
2424 i
= REGION_NUM_RECTS(pRgn
);
2425 pBox
= REGION_RECTS(pRgn
);
2428 (void) miBSClearBackingStore(pWin
, pBox
->x1
, pBox
->y1
,
2429 pBox
->x2
- pBox
->x1
,
2430 pBox
->y2
- pBox
->y1
,
2437 * fill a region of the destination with virtual bits
2439 * pRgn is to be translated by (x,y)
2443 miBSFillVirtualBits (pDrawable
, pGC
, pRgn
, x
, y
, state
, pixunion
, planeMask
)
2444 DrawablePtr pDrawable
;
2450 unsigned long planeMask
;
2462 numRects
= REGION_NUM_RECTS(pRgn
);
2463 pRect
= (xRectangle
*)ALLOCATE_LOCAL(numRects
* sizeof(xRectangle
));
2467 if (pDrawable
->type
!= DRAWABLE_PIXMAP
)
2469 pWin
= (WindowPtr
) pDrawable
;
2470 if (!pWin
->backStorage
)
2475 gcval
[i
++] = (pointer
)planeMask
;
2476 gcmask
|= GCPlaneMask
;
2477 if (state
== BackgroundPixel
)
2479 if (pGC
->fgPixel
!= pixunion
.pixel
)
2481 gcval
[i
++] = (pointer
)pixunion
.pixel
;
2482 gcmask
|= GCForeground
;
2484 if (pGC
->fillStyle
!= FillSolid
)
2486 gcval
[i
++] = (pointer
)FillSolid
;
2487 gcmask
|= GCFillStyle
;
2492 if (pGC
->fillStyle
!= FillTiled
)
2494 gcval
[i
++] = (pointer
)FillTiled
;
2495 gcmask
|= GCFillStyle
;
2497 if (pGC
->tileIsPixel
|| pGC
->tile
.pixmap
!= pixunion
.pixmap
)
2499 gcval
[i
++] = (pointer
)pixunion
.pixmap
;
2502 if (pGC
->patOrg
.x
!= x
)
2504 gcval
[i
++] = (pointer
)(long)x
;
2505 gcmask
|= GCTileStipXOrigin
;
2507 if (pGC
->patOrg
.y
!= y
)
2509 gcval
[i
++] = (pointer
)(long)y
;
2510 gcmask
|= GCTileStipYOrigin
;
2514 DoChangeGC (pGC
, gcmask
, (XID
*)gcval
, 1);
2517 (*pWin
->drawable
.pScreen
->DrawGuarantee
) (pWin
, pGC
, GuaranteeVisBack
);
2519 if (pDrawable
->serialNumber
!= pGC
->serialNumber
)
2520 ValidateGC (pDrawable
, pGC
);
2522 pBox
= REGION_RECTS(pRgn
);
2523 for (i
= numRects
; --i
>= 0; pBox
++, pRect
++)
2525 pRect
->x
= pBox
->x1
+ x
;
2526 pRect
->y
= pBox
->y1
+ y
;
2527 pRect
->width
= pBox
->x2
- pBox
->x1
;
2528 pRect
->height
= pBox
->y2
- pBox
->y1
;
2531 (*pGC
->ops
->PolyFillRect
) (pDrawable
, pGC
, numRects
, pRect
);
2533 (*pWin
->drawable
.pScreen
->DrawGuarantee
) (pWin
, pGC
, GuaranteeNothing
);
2534 DEALLOCATE_LOCAL (pRect
);
2538 *-----------------------------------------------------------------------
2540 * Create and install backing store info for a window
2542 *-----------------------------------------------------------------------
2549 miBSWindowPtr pBackingStore
;
2552 if (pWin
->drawable
.pScreen
->backingStoreSupport
== NotUseful
)
2554 pScreen
= pWin
->drawable
.pScreen
;
2555 if (!(pBackingStore
= (miBSWindowPtr
)pWin
->backStorage
))
2558 pBackingStore
= (miBSWindowPtr
)xalloc(sizeof(miBSWindowRec
));
2562 pBackingStore
->pBackingPixmap
= NullPixmap
;
2563 pBackingStore
->x
= 0;
2564 pBackingStore
->y
= 0;
2565 REGION_NULL( pScreen
, &pBackingStore
->SavedRegion
);
2566 pBackingStore
->viewable
= (char)pWin
->viewable
;
2567 pBackingStore
->status
= StatusNoPixmap
;
2568 pBackingStore
->backgroundState
= None
;
2569 pWin
->backStorage
= (pointer
) pBackingStore
;
2573 * Now want to initialize the backing pixmap and SavedRegion if
2574 * necessary. The initialization consists of finding all the
2575 * currently-obscured regions, by taking the inverse of the window's
2576 * clip list, storing the result in SavedRegion, and exposing those
2577 * areas of the window.
2580 if (pBackingStore
->status
== StatusNoPixmap
&&
2581 ((pWin
->backingStore
== WhenMapped
&& pWin
->viewable
) ||
2582 (pWin
->backingStore
== Always
)))
2585 RegionPtr pSavedRegion
;
2587 pSavedRegion
= &pBackingStore
->SavedRegion
;
2589 box
.x1
= pWin
->drawable
.x
;
2590 box
.x2
= box
.x1
+ (int) pWin
->drawable
.width
;
2591 box
.y1
= pWin
->drawable
.y
;
2592 box
.y2
= pWin
->drawable
.y
+ (int) pWin
->drawable
.height
;
2594 REGION_INVERSE( pScreen
, pSavedRegion
, &pWin
->clipList
, &box
);
2595 REGION_TRANSLATE( pScreen
, pSavedRegion
,
2599 if (wBoundingShape (pWin
))
2600 REGION_INTERSECT(pScreen
, pSavedRegion
, pSavedRegion
,
2601 wBoundingShape (pWin
));
2602 if (wClipShape (pWin
))
2603 REGION_INTERSECT(pScreen
, pSavedRegion
, pSavedRegion
,
2606 /* if window is already on-screen, assume it has been drawn to */
2608 pBackingStore
->status
= StatusVDirty
;
2609 miTileVirtualBS (pWin
);
2612 * deliver all the newly available regions
2613 * as exposure events to the window
2616 miSendExposures(pWin
, pSavedRegion
, 0, 0);
2618 else if (!pWin
->viewable
)
2621 * Turn off backing store when we're not supposed to
2622 * be saving anything
2624 if (pBackingStore
->status
!= StatusNoPixmap
)
2626 REGION_EMPTY( pScreen
, &pBackingStore
->SavedRegion
);
2627 miDestroyBSPixmap (pWin
);
2633 *-----------------------------------------------------------------------
2635 * Destroy and free all the stuff associated with the backing-store
2636 * for the given window.
2642 * The backing pixmap and all the regions and GC's are destroyed.
2644 *-----------------------------------------------------------------------
2650 miBSWindowPtr pBackingStore
;
2653 pScreen
= pWin
->drawable
.pScreen
;
2655 pBackingStore
= (miBSWindowPtr
)pWin
->backStorage
;
2658 miDestroyBSPixmap (pWin
);
2660 REGION_UNINIT( pScreen
, &pBackingStore
->SavedRegion
);
2662 xfree(pBackingStore
);
2663 pWin
->backStorage
= NULL
;
2668 *-----------------------------------------------------------------------
2669 * miResizeBackingStore --
2670 * Alter the size of the backing pixmap as necessary when the
2671 * SavedRegion changes size. The contents of the old pixmap are
2672 * copied/shifted into the new/same pixmap.
2675 * The new Pixmap is created as necessary.
2678 * The old pixmap is destroyed.
2680 *-----------------------------------------------------------------------
2683 miResizeBackingStore(
2685 int dx
, /* bits are moving this far */
2686 int dy
, /* bits are moving this far */
2687 Bool saveBits
) /* bits are useful */
2689 miBSWindowPtr pBackingStore
;
2690 PixmapPtr pBackingPixmap
;
2694 PixmapPtr pNewPixmap
;
2698 pBackingStore
= (miBSWindowPtr
)(pWin
->backStorage
);
2699 pBackingPixmap
= pBackingStore
->pBackingPixmap
;
2700 if (!pBackingPixmap
)
2702 pScreen
= pWin
->drawable
.pScreen
;
2703 extents
= REGION_EXTENTS(pScreen
, &pBackingStore
->SavedRegion
);
2704 pNewPixmap
= pBackingPixmap
;
2706 nw
= extents
->x2
- extents
->x1
;
2707 nh
= extents
->y2
- extents
->y1
;
2709 /* the policy here could be more sophisticated */
2710 if (nw
!= pBackingPixmap
->drawable
.width
||
2711 nh
!= pBackingPixmap
->drawable
.height
)
2713 if (!saveBits
|| !nw
|| !nh
)
2715 pNewPixmap
= NullPixmap
;
2716 pBackingStore
->status
= StatusNoPixmap
;
2720 pNewPixmap
= (PixmapPtr
)(*pScreen
->CreatePixmap
)
2723 pWin
->drawable
.depth
);
2727 pBackingStore
->status
= StatusNoPixmap
;
2729 pBackingStore
->status
= StatusBadAlloc
;
2736 pBackingStore
->x
= 0;
2737 pBackingStore
->y
= 0;
2741 nx
= pBackingStore
->x
- extents
->x1
+ dx
;
2742 ny
= pBackingStore
->y
- extents
->y1
+ dy
;
2743 pBackingStore
->x
= extents
->x1
;
2744 pBackingStore
->y
= extents
->y1
;
2746 if (saveBits
&& (pNewPixmap
!= pBackingPixmap
|| nx
!= 0 || ny
!= 0))
2748 pGC
= GetScratchGC(pNewPixmap
->drawable
.depth
, pScreen
);
2751 ValidateGC((DrawablePtr
)pNewPixmap
, pGC
);
2752 /* if we implement a policy where the pixmap can be larger than
2753 * the region extents, we might want to optimize this copyarea
2754 * by only copying the old extents, rather than the entire
2757 (*pGC
->ops
->CopyArea
)((DrawablePtr
)pBackingPixmap
,
2758 (DrawablePtr
)pNewPixmap
, pGC
,
2760 pBackingPixmap
->drawable
.width
,
2761 pBackingPixmap
->drawable
.height
,
2767 /* SavedRegion is used in the backingGC clip; force an update */
2768 pWin
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
2769 if (pNewPixmap
!= pBackingPixmap
)
2771 (* pScreen
->DestroyPixmap
)(pBackingPixmap
);
2772 pBackingStore
->pBackingPixmap
= pNewPixmap
;
2777 *-----------------------------------------------------------------------
2778 * miBSSaveDoomedAreas --
2779 * Saved the areas of the given window that are about to be
2780 * obscured. If the window has moved, pObscured is expected to
2781 * be at the new screen location and (dx,dy) is expected to be the offset
2782 * to the window's previous location.
2788 * The region is copied from the screen into pBackingPixmap and
2789 * SavedRegion is updated.
2791 *-----------------------------------------------------------------------
2794 miBSSaveDoomedAreas(pWin
, pObscured
, dx
, dy
)
2796 RegionPtr pObscured
;
2799 miBSWindowPtr pBackingStore
;
2803 pBackingStore
= (miBSWindowPtr
)pWin
->backStorage
;
2804 pScreen
= pWin
->drawable
.pScreen
;
2807 * If the window isn't realized, it's being unmapped, thus we don't
2808 * want to save anything if backingStore isn't Always.
2810 if (!pWin
->realized
)
2812 pBackingStore
->viewable
= (char)pWin
->viewable
;
2813 if (pWin
->backingStore
!= Always
)
2815 REGION_EMPTY( pScreen
, &pBackingStore
->SavedRegion
);
2816 miDestroyBSPixmap (pWin
);
2819 if (pBackingStore
->status
== StatusBadAlloc
)
2820 pBackingStore
->status
= StatusNoPixmap
;
2823 /* Don't even pretend to save anything for a virtual background None */
2824 if ((pBackingStore
->status
== StatusVirtual
) &&
2825 (pBackingStore
->backgroundState
== None
))
2828 if (REGION_NOTEMPTY(pScreen
, pObscured
))
2831 x
= pWin
->drawable
.x
;
2832 y
= pWin
->drawable
.y
;
2833 REGION_TRANSLATE(pScreen
, pObscured
, -x
, -y
);
2834 oldExtents
= *REGION_EXTENTS(pScreen
, &pBackingStore
->SavedRegion
);
2835 REGION_UNION( pScreen
, &pBackingStore
->SavedRegion
,
2836 &pBackingStore
->SavedRegion
,
2839 * only save the bits if we've actually
2840 * started using backing store
2842 if (pBackingStore
->status
!= StatusVirtual
)
2844 if (!pBackingStore
->pBackingPixmap
)
2845 miCreateBSPixmap (pWin
, &oldExtents
);
2847 miResizeBackingStore(pWin
, 0, 0, TRUE
);
2849 if (pBackingStore
->pBackingPixmap
) {
2850 if (pBackingStore
->x
| pBackingStore
->y
)
2852 REGION_TRANSLATE( pScreen
, pObscured
,
2855 x
+= pBackingStore
->x
;
2856 y
+= pBackingStore
->y
;
2858 (* pScreen
->BackingStoreFuncs
.SaveAreas
)
2859 (pBackingStore
->pBackingPixmap
, pObscured
,
2860 x
- dx
, y
- dy
, pWin
);
2863 REGION_TRANSLATE(pScreen
, pObscured
, x
, y
);
2867 if (REGION_BROKEN (pScreen
, pObscured
))
2869 REGION_EMPTY( pScreen
, &pBackingStore
->SavedRegion
);
2870 miDestroyBSPixmap (pWin
);
2877 *-----------------------------------------------------------------------
2878 * miBSRestoreAreas --
2879 * Restore areas from backing-store that are no longer obscured.
2880 * expects prgnExposed to contain a screen-relative area.
2883 * The region to generate exposure events on (which may be
2884 * different from the region to paint).
2887 * Areas are copied from pBackingPixmap to the screen. prgnExposed
2888 * is altered to contain the region that could not be restored from
2892 * This is called before sending any exposure events to the client,
2893 * and so might be called if the window has grown. Changing the backing
2894 * pixmap doesn't require revalidating the backingGC because the
2895 * client's next output request will result in a call to ValidateGC,
2896 * since the window clip region has changed, which will in turn call
2897 * miValidateBackingStore.
2898 *-----------------------------------------------------------------------
2901 miBSRestoreAreas(pWin
, prgnExposed
)
2903 RegionPtr prgnExposed
;
2905 PixmapPtr pBackingPixmap
;
2906 miBSWindowPtr pBackingStore
;
2907 RegionPtr prgnSaved
;
2908 RegionPtr prgnRestored
;
2910 RegionPtr exposures
= prgnExposed
;
2912 pScreen
= pWin
->drawable
.pScreen
;
2913 pBackingStore
= (miBSWindowPtr
)pWin
->backStorage
;
2914 pBackingPixmap
= pBackingStore
->pBackingPixmap
;
2916 prgnSaved
= &pBackingStore
->SavedRegion
;
2918 if (pBackingStore
->status
== StatusContents
)
2920 REGION_TRANSLATE(pScreen
, prgnSaved
, pWin
->drawable
.x
,
2923 prgnRestored
= REGION_CREATE( pScreen
, (BoxPtr
)NULL
, 1);
2924 REGION_INTERSECT( pScreen
, prgnRestored
, prgnExposed
, prgnSaved
);
2927 * Since prgnExposed is no longer obscured, we no longer
2928 * will have a valid copy of it in backing-store, but there is a valid
2929 * copy of it on screen, so subtract the area we just restored from
2930 * from the area to be exposed.
2933 if (REGION_NOTEMPTY( pScreen
, prgnRestored
))
2935 REGION_SUBTRACT( pScreen
, prgnSaved
, prgnSaved
, prgnExposed
);
2936 REGION_SUBTRACT( pScreen
, prgnExposed
, prgnExposed
, prgnRestored
);
2939 * Do the actual restoration
2941 (* pScreen
->BackingStoreFuncs
.RestoreAreas
) (pBackingPixmap
,
2943 pWin
->drawable
.x
+ pBackingStore
->x
,
2944 pWin
->drawable
.y
+ pBackingStore
->y
,
2947 * if the saved region is completely empty, dispose of the
2948 * backing pixmap, otherwise, retranslate the saved
2949 * region to window relative
2952 if (REGION_NOTEMPTY(pScreen
, prgnSaved
))
2954 REGION_TRANSLATE(pScreen
, prgnSaved
,
2957 miResizeBackingStore(pWin
, 0, 0, TRUE
);
2960 miDestroyBSPixmap (pWin
);
2963 REGION_TRANSLATE(pScreen
, prgnSaved
,
2964 -pWin
->drawable
.x
, -pWin
->drawable
.y
);
2965 REGION_DESTROY( pScreen
, prgnRestored
);
2968 else if ((pBackingStore
->status
== StatusVirtual
) ||
2969 (pBackingStore
->status
== StatusVDirty
))
2971 REGION_TRANSLATE(pScreen
, prgnSaved
,
2972 pWin
->drawable
.x
, pWin
->drawable
.y
);
2973 exposures
= REGION_CREATE( pScreen
, NullBox
, 1);
2974 if (SameBackground (pBackingStore
->backgroundState
,
2975 pBackingStore
->background
,
2976 pWin
->backgroundState
,
2979 REGION_SUBTRACT( pScreen
, exposures
, prgnExposed
, prgnSaved
);
2983 miTileVirtualBS(pWin
);
2985 /* we need to expose all we have (virtually) retiled */
2986 REGION_UNION( pScreen
, exposures
, prgnExposed
, prgnSaved
);
2988 REGION_SUBTRACT( pScreen
, prgnSaved
, prgnSaved
, prgnExposed
);
2989 REGION_TRANSLATE(pScreen
, prgnSaved
,
2990 -pWin
->drawable
.x
, -pWin
->drawable
.y
);
2992 else if (pWin
->viewable
&& !pBackingStore
->viewable
&&
2993 pWin
->backingStore
!= Always
)
2996 * The window was just mapped and nothing has been saved in
2997 * backing-store from the last time it was mapped. We want to capture
2998 * any output to regions that are already obscured but there are no
2999 * bits to snag off the screen, so we initialize things just as we did
3000 * in miBSAllocate, above.
3004 prgnSaved
= &pBackingStore
->SavedRegion
;
3006 box
.x1
= pWin
->drawable
.x
;
3007 box
.x2
= box
.x1
+ (int) pWin
->drawable
.width
;
3008 box
.y1
= pWin
->drawable
.y
;
3009 box
.y2
= box
.y1
+ (int) pWin
->drawable
.height
;
3011 REGION_INVERSE( pScreen
, prgnSaved
, &pWin
->clipList
, &box
);
3012 REGION_TRANSLATE( pScreen
, prgnSaved
,
3016 if (wBoundingShape (pWin
))
3017 REGION_INTERSECT(pScreen
, prgnSaved
, prgnSaved
,
3018 wBoundingShape (pWin
));
3019 if (wClipShape (pWin
))
3020 REGION_INTERSECT(pScreen
, prgnSaved
, prgnSaved
,
3023 miTileVirtualBS(pWin
);
3025 exposures
= REGION_CREATE( pScreen
, &box
, 1);
3027 pBackingStore
->viewable
= (char)pWin
->viewable
;
3033 *-----------------------------------------------------------------------
3034 * miBSTranslateBackingStore --
3035 * Shift the backing-store in the given direction. Called when bit
3036 * gravity is shifting things around.
3039 * An occluded region of the window which should be sent exposure events.
3040 * This region should be in absolute coordinates (i.e. include
3041 * new window position).
3044 * If the window changed size as well as position, the backing pixmap
3045 * is resized. The contents of the backing pixmap are shifted
3048 * Bob and I have rewritten this routine quite a few times, each
3049 * time it gets a few more cases correct, and introducing some
3050 * interesting bugs. Naturally, I think the code is correct this
3053 * Let me try to explain what this routine is for:
3055 * It's called from SlideAndSizeWindow whenever a window
3056 * with backing store is resized. There are two separate
3059 * a) The window has ForgetGravity
3061 * In this case, windx, windy will be 0 and oldClip will
3062 * be NULL. This indicates that all of the window contents
3063 * currently saved offscreen should be discarded, and the
3064 * entire window exposed. TranslateBackingStore, then, should
3065 * prepare a completely new backing store region based on the
3066 * new window clipList and return that region for exposure.
3068 * b) The window has some other gravity
3070 * In this case, windx, windy will be set to the distance
3071 * that the bits should move within the window. oldClip
3072 * will be set to the old visible portion of the window.
3073 * TranslateBackingStore, then, should adjust the backing
3074 * store to accommodate the portion of the existing backing
3075 * store bits which coorespond to backing store bits which
3076 * will still be occluded in the new configuration. oldx,oldy
3077 * are set to the old position of the window on the screen.
3079 * Furthermore, in this case any contents of the screen which
3080 * are about to become occluded should be fetched from the screen
3081 * and placed in backing store. This is to avoid the eventual
3082 * occlusion by the win gravity shifting the child window bits around
3083 * on top of this window, and potentially losing information
3085 * It's also called from SetShape, but I think (he says not
3086 * really knowing for sure) that this code will even work
3088 *-----------------------------------------------------------------------
3092 miBSTranslateBackingStore(pWin
, windx
, windy
, oldClip
, oldx
, oldy
)
3094 int windx
; /* bit translation distance in window */
3096 RegionPtr oldClip
; /* Region being copied */
3097 int oldx
; /* old window position */
3100 miBSWindowPtr pBackingStore
;
3101 RegionPtr pSavedRegion
;
3102 RegionPtr newSaved
, doomed
;
3105 int scrdx
; /* bit translation distance on screen */
3107 int dx
; /* distance window moved on screen */
3110 pScreen
= pWin
->drawable
.pScreen
;
3111 pBackingStore
= (miBSWindowPtr
)(pWin
->backStorage
);
3112 if ((pBackingStore
->status
== StatusNoPixmap
) ||
3113 (pBackingStore
->status
== StatusBadAlloc
))
3117 * Compute the new saved region
3120 newSaved
= REGION_CREATE( pScreen
, NullBox
, 1);
3121 extents
.x1
= pWin
->drawable
.x
;
3122 extents
.x2
= pWin
->drawable
.x
+ (int) pWin
->drawable
.width
;
3123 extents
.y1
= pWin
->drawable
.y
;
3124 extents
.y2
= pWin
->drawable
.y
+ (int) pWin
->drawable
.height
;
3125 REGION_INVERSE( pScreen
, newSaved
, &pWin
->clipList
, &extents
);
3127 REGION_TRANSLATE( pScreen
, newSaved
,
3128 -pWin
->drawable
.x
, -pWin
->drawable
.y
);
3130 if (wBoundingShape (pWin
) || wClipShape (pWin
)) {
3131 if (wBoundingShape (pWin
))
3132 REGION_INTERSECT( pScreen
, newSaved
, newSaved
,
3133 wBoundingShape (pWin
));
3134 if (wClipShape (pWin
))
3135 REGION_INTERSECT( pScreen
, newSaved
, newSaved
, wClipShape (pWin
));
3139 pSavedRegion
= &pBackingStore
->SavedRegion
;
3141 /* now find any visible areas we can save from the screen */
3142 /* and then translate newSaved to old local coordinates */
3145 /* bit gravity makes things virtually too hard, punt */
3146 if (((windx
!= 0) || (windy
!= 0)) &&
3147 (pBackingStore
->status
!= StatusContents
))
3148 miCreateBSPixmap(pWin
, NullBox
);
3151 * The window is moving this far on the screen
3153 dx
= pWin
->drawable
.x
- oldx
;
3154 dy
= pWin
->drawable
.y
- oldy
;
3156 * The bits will be moving on the screen by the
3157 * amount the window is moving + the amount the
3158 * bits are moving within the window
3164 * intersect at old bit position to discover the
3165 * bits on the screen which can be put into the
3168 REGION_TRANSLATE( pScreen
, oldClip
, windx
- oldx
, windy
- oldy
);
3169 doomed
= REGION_CREATE( pScreen
, NullBox
, 1);
3170 REGION_INTERSECT( pScreen
, doomed
, oldClip
, newSaved
);
3171 REGION_TRANSLATE( pScreen
, oldClip
, oldx
- windx
, oldy
- windy
);
3174 * Translate the old saved region to the position in the
3175 * window where it will appear to be
3177 REGION_TRANSLATE( pScreen
, pSavedRegion
, windx
, windy
);
3180 * Add the old saved region to the new saved region, so
3181 * that calls to RestoreAreas will be able to fetch those
3184 REGION_UNION( pScreen
, newSaved
, newSaved
, pSavedRegion
);
3187 * Swap the new saved region into the window
3192 tmp
= *pSavedRegion
;
3193 *pSavedRegion
= *newSaved
;
3196 miResizeBackingStore (pWin
, windx
, windy
, TRUE
);
3199 * Compute the newly enabled region
3200 * of backing store. This region will be
3201 * set to background in the backing pixmap and
3202 * sent as exposure events to the client.
3204 REGION_SUBTRACT( pScreen
, newSaved
, pSavedRegion
, newSaved
);
3207 * Fetch bits which will be obscured from
3210 if (REGION_NOTEMPTY( pScreen
, doomed
))
3213 * Don't clear regions which have bits on the
3216 REGION_SUBTRACT( pScreen
, newSaved
, newSaved
, doomed
);
3219 * Make the region to SaveDoomedAreas absolute, instead
3220 * of window relative.
3222 REGION_TRANSLATE( pScreen
, doomed
,
3223 pWin
->drawable
.x
, pWin
->drawable
.y
);
3224 (* pScreen
->SaveDoomedAreas
) (pWin
, doomed
, scrdx
, scrdy
);
3227 REGION_DESTROY(pScreen
, doomed
);
3230 * and clear whatever there is that's new
3232 if (REGION_NOTEMPTY( pScreen
, newSaved
))
3234 miBSClearBackingRegion (pWin
, newSaved
);
3236 * Make the exposed region absolute
3238 REGION_TRANSLATE(pScreen
, newSaved
,
3244 REGION_DESTROY(pScreen
, newSaved
);
3245 newSaved
= NullRegion
;
3251 * ForgetGravity: just reset backing store and
3252 * expose the whole mess
3254 REGION_COPY( pScreen
, pSavedRegion
, newSaved
);
3255 REGION_TRANSLATE( pScreen
, newSaved
,
3256 pWin
->drawable
.x
, pWin
->drawable
.y
);
3258 miResizeBackingStore (pWin
, 0, 0, FALSE
);
3259 (void) miBSClearBackingStore (pWin
, 0, 0, 0, 0, FALSE
);
3266 * Inform the backing store layer that you are about to validate
3267 * a gc with a window, and that subsequent output to the window
3268 * is (or is not) guaranteed to be already clipped to the visible
3269 * regions of the window.
3273 miBSDrawGuarantee (pWin
, pGC
, guarantee
)
3280 if (pWin
->backStorage
)
3282 pPriv
= (miBSGCPtr
)pGC
->devPrivates
[miBSGCIndex
].ptr
;
3284 (void) miBSCreateGCPrivate (pGC
);
3285 pPriv
= (miBSGCPtr
)pGC
->devPrivates
[miBSGCIndex
].ptr
;
3291 * when the GC is Cheap pPriv will point
3292 * at some device's gc func structure. guarantee
3293 * will point at the ChangeGC entry of that struct
3294 * and will never match a valid guarantee value.
3296 switch (pPriv
->guarantee
)
3298 case GuaranteeNothing
:
3299 case GuaranteeVisBack
:
3300 pPriv
->guarantee
= guarantee
;
3307 #define noBackingCopy (GCGraphicsExposures|GCClipXOrigin|GCClipYOrigin| \
3308 GCClipMask|GCSubwindowMode| \
3309 GCTileStipXOrigin|GCTileStipYOrigin)
3312 *-----------------------------------------------------------------------
3314 * Wrapper around output-library's ValidateGC routine
3322 * The idea here is to perform several functions:
3323 * - All the output calls must be intercepted and routed to
3324 * backing-store as necessary.
3325 * - pGC in the window's devBackingStore must be set up with the
3326 * clip list appropriate for writing to pBackingPixmap (i.e.
3327 * the inverse of the window's clipList intersected with the
3328 * clientClip of the GC). Since the destination for this GC is
3329 * a pixmap, it is sufficient to set the clip list as its
3331 *-----------------------------------------------------------------------
3335 miBSValidateGC (pGC
, stateChanges
, pDrawable
)
3337 unsigned long stateChanges
;
3338 DrawablePtr pDrawable
;
3341 miBSWindowPtr pWindowPriv
= NULL
;
3345 RegionPtr backingCompositeClip
= NULL
;
3347 if (pDrawable
->type
!= DRAWABLE_PIXMAP
)
3349 pWin
= (WindowPtr
) pDrawable
;
3350 pWindowPriv
= (miBSWindowPtr
) pWin
->backStorage
;
3351 lift_functions
= (pWindowPriv
== (miBSWindowPtr
) NULL
);
3355 pWin
= (WindowPtr
) NULL
;
3356 lift_functions
= TRUE
;
3359 pPriv
= (miBSGCPtr
)pGC
->devPrivates
[miBSGCIndex
].ptr
;
3361 FUNC_PROLOGUE (pGC
, pPriv
);
3363 (*pGC
->funcs
->ValidateGC
) (pGC
, stateChanges
, pDrawable
);
3366 * rewrap funcs and ops as Validate may have changed them
3369 pPriv
->wrapFuncs
= pGC
->funcs
;
3370 pPriv
->wrapOps
= pGC
->ops
;
3372 if (!lift_functions
&& ((pPriv
->guarantee
== GuaranteeVisBack
) ||
3373 (pWindowPriv
->status
== StatusNoPixmap
) ||
3374 (pWindowPriv
->status
== StatusBadAlloc
)))
3375 lift_functions
= TRUE
;
3378 * check to see if a new backingCompositeClip region must
3382 if (!lift_functions
&&
3383 ((pDrawable
->serialNumber
!= pPriv
->serialNumber
) ||
3384 (stateChanges
&(GCClipXOrigin
|GCClipYOrigin
|GCClipMask
|GCSubwindowMode
))))
3386 if (REGION_NOTEMPTY(pGC
->pScreen
, &pWindowPriv
->SavedRegion
))
3388 backingCompositeClip
= REGION_CREATE(pGC
->pScreen
, NULL
, 1);
3389 if ((pGC
->clientClipType
== CT_NONE
) ||
3390 (pGC
->clientClipType
== CT_PIXMAP
))
3392 REGION_COPY(pGC
->pScreen
, backingCompositeClip
,
3393 &pWindowPriv
->SavedRegion
);
3398 * Make a new copy of the client clip, translated to
3399 * its proper origin.
3402 REGION_COPY(pGC
->pScreen
, backingCompositeClip
,
3404 REGION_TRANSLATE(pGC
->pScreen
, backingCompositeClip
,
3407 REGION_INTERSECT(pGC
->pScreen
, backingCompositeClip
,
3408 backingCompositeClip
,
3409 &pWindowPriv
->SavedRegion
);
3411 if (pGC
->subWindowMode
== IncludeInferiors
)
3413 RegionPtr translatedClip
;
3416 * any output in IncludeInferiors mode will not
3417 * be redirected to Inferiors backing store. This
3418 * can be fixed only at great cost to the shadow routines.
3420 translatedClip
= NotClippedByChildren (pWin
);
3421 REGION_TRANSLATE(pGC
->pScreen
, translatedClip
,
3424 REGION_SUBTRACT(pGC
->pScreen
, backingCompositeClip
,
3425 backingCompositeClip
, translatedClip
);
3426 REGION_DESTROY(pGC
->pScreen
, translatedClip
);
3428 if (!REGION_NOTEMPTY(pGC
->pScreen
, backingCompositeClip
))
3429 lift_functions
= TRUE
;
3433 lift_functions
= TRUE
;
3436 /* Reset the status when drawing to an unoccluded window so that
3437 * future SaveAreas will actually copy bits from the screen. Note that
3438 * output to root window in IncludeInferiors mode will not cause this
3439 * to change. This causes all transient graphics by the window
3440 * manager to the root window to not enable backing store.
3442 if (lift_functions
&& (pWindowPriv
->status
== StatusVirtual
) &&
3443 (pWin
->parent
|| pGC
->subWindowMode
!= IncludeInferiors
))
3444 pWindowPriv
->status
= StatusVDirty
;
3448 * if no backing store has been allocated, and it's needed,
3452 if (!lift_functions
&& !pWindowPriv
->pBackingPixmap
)
3454 miCreateBSPixmap (pWin
, NullBox
);
3455 if (!pWindowPriv
->pBackingPixmap
)
3456 lift_functions
= TRUE
;
3460 * create the backing GC if needed, lift functions
3461 * if the creation fails
3464 if (!lift_functions
&& !pPriv
->pBackingGC
)
3467 XID noexpose
= xFalse
;
3469 /* We never want ops with the backingGC to generate GraphicsExpose */
3470 pBackingGC
= CreateGC ((DrawablePtr
)pWindowPriv
->pBackingPixmap
,
3471 GCGraphicsExposures
, &noexpose
, &status
);
3472 if (status
!= Success
)
3473 lift_functions
= TRUE
;
3475 pPriv
->pBackingGC
= pBackingGC
;
3478 pBackingGC
= pPriv
->pBackingGC
;
3480 pPriv
->stateChanges
|= stateChanges
;
3484 if (backingCompositeClip
)
3485 REGION_DESTROY( pGC
->pScreen
, backingCompositeClip
);
3487 /* unwrap the GC again */
3488 miBSDestroyGCPrivate (pGC
);
3494 * the rest of this function gets the pBackingGC
3495 * into shape for possible draws
3498 pPriv
->stateChanges
&= ~noBackingCopy
;
3499 if (pPriv
->stateChanges
)
3500 CopyGC(pGC
, pBackingGC
, pPriv
->stateChanges
);
3501 if ((pGC
->patOrg
.x
- pWindowPriv
->x
) != pBackingGC
->patOrg
.x
||
3502 (pGC
->patOrg
.y
- pWindowPriv
->y
) != pBackingGC
->patOrg
.y
)
3505 vals
[0] = pGC
->patOrg
.x
- pWindowPriv
->x
;
3506 vals
[1] = pGC
->patOrg
.y
- pWindowPriv
->y
;
3507 DoChangeGC(pBackingGC
, GCTileStipXOrigin
|GCTileStipYOrigin
, vals
, 0);
3509 pPriv
->stateChanges
= 0;
3511 if (backingCompositeClip
)
3515 if (pGC
->clientClipType
== CT_PIXMAP
)
3517 (*pBackingGC
->funcs
->CopyClip
)(pBackingGC
, pGC
);
3518 REGION_TRANSLATE(pGC
->pScreen
, backingCompositeClip
,
3519 -pGC
->clipOrg
.x
, -pGC
->clipOrg
.y
);
3520 vals
[0] = pGC
->clipOrg
.x
- pWindowPriv
->x
;
3521 vals
[1] = pGC
->clipOrg
.y
- pWindowPriv
->y
;
3522 DoChangeGC(pBackingGC
, GCClipXOrigin
|GCClipYOrigin
, vals
, 0);
3523 (* pGC
->pScreen
->BackingStoreFuncs
.SetClipmaskRgn
)
3524 (pBackingGC
, backingCompositeClip
);
3525 REGION_DESTROY( pGC
->pScreen
, backingCompositeClip
);
3529 vals
[0] = -pWindowPriv
->x
;
3530 vals
[1] = -pWindowPriv
->y
;
3531 DoChangeGC(pBackingGC
, GCClipXOrigin
|GCClipYOrigin
, vals
, 0);
3532 (*pBackingGC
->funcs
->ChangeClip
) (pBackingGC
, CT_REGION
, backingCompositeClip
, 0);
3534 pPriv
->serialNumber
= pDrawable
->serialNumber
;
3537 if (pWindowPriv
->pBackingPixmap
->drawable
.serialNumber
3538 != pBackingGC
->serialNumber
)
3540 ValidateGC((DrawablePtr
)pWindowPriv
->pBackingPixmap
, pBackingGC
);
3543 if (pBackingGC
->clientClip
== 0)
3544 ErrorF ("backing store clip list nil");
3546 FUNC_EPILOGUE (pGC
, pPriv
);
3550 miBSChangeGC (pGC
, mask
)
3554 miBSGCPtr pPriv
= (miBSGCPtr
) (pGC
)->devPrivates
[miBSGCIndex
].ptr
;
3556 FUNC_PROLOGUE (pGC
, pPriv
);
3558 (*pGC
->funcs
->ChangeGC
) (pGC
, mask
);
3560 FUNC_EPILOGUE (pGC
, pPriv
);
3564 miBSCopyGC (pGCSrc
, mask
, pGCDst
)
3565 GCPtr pGCSrc
, pGCDst
;
3568 miBSGCPtr pPriv
= (miBSGCPtr
) (pGCDst
)->devPrivates
[miBSGCIndex
].ptr
;
3570 FUNC_PROLOGUE (pGCDst
, pPriv
);
3572 (*pGCDst
->funcs
->CopyGC
) (pGCSrc
, mask
, pGCDst
);
3574 FUNC_EPILOGUE (pGCDst
, pPriv
);
3581 miBSGCPtr pPriv
= (miBSGCPtr
) (pGC
)->devPrivates
[miBSGCIndex
].ptr
;
3583 FUNC_PROLOGUE (pGC
, pPriv
);
3585 if (pPriv
->pBackingGC
)
3586 FreeGC(pPriv
->pBackingGC
, (GContext
)0);
3588 (*pGC
->funcs
->DestroyGC
) (pGC
);
3590 FUNC_EPILOGUE (pGC
, pPriv
);
3596 miBSChangeClip(pGC
, type
, pvalue
, nrects
)
3602 miBSGCPtr pPriv
= (miBSGCPtr
) (pGC
)->devPrivates
[miBSGCIndex
].ptr
;
3604 FUNC_PROLOGUE (pGC
, pPriv
);
3606 (* pGC
->funcs
->ChangeClip
)(pGC
, type
, pvalue
, nrects
);
3608 FUNC_EPILOGUE (pGC
, pPriv
);
3612 miBSCopyClip(pgcDst
, pgcSrc
)
3613 GCPtr pgcDst
, pgcSrc
;
3615 miBSGCPtr pPriv
= (miBSGCPtr
) (pgcDst
)->devPrivates
[miBSGCIndex
].ptr
;
3617 FUNC_PROLOGUE (pgcDst
, pPriv
);
3619 (* pgcDst
->funcs
->CopyClip
)(pgcDst
, pgcSrc
);
3621 FUNC_EPILOGUE (pgcDst
, pPriv
);
3625 miBSDestroyClip(pGC
)
3628 miBSGCPtr pPriv
= (miBSGCPtr
) (pGC
)->devPrivates
[miBSGCIndex
].ptr
;
3630 FUNC_PROLOGUE (pGC
, pPriv
);
3632 (* pGC
->funcs
->DestroyClip
)(pGC
);
3634 FUNC_EPILOGUE (pGC
, pPriv
);
3638 miDestroyBSPixmap (pWin
)
3641 miBSWindowPtr pBackingStore
;
3644 pScreen
= pWin
->drawable
.pScreen
;
3645 pBackingStore
= (miBSWindowPtr
) pWin
->backStorage
;
3646 if (pBackingStore
->pBackingPixmap
)
3647 (* pScreen
->DestroyPixmap
)(pBackingStore
->pBackingPixmap
);
3648 pBackingStore
->pBackingPixmap
= NullPixmap
;
3649 pBackingStore
->x
= 0;
3650 pBackingStore
->y
= 0;
3651 if (pBackingStore
->backgroundState
== BackgroundPixmap
)
3652 (* pScreen
->DestroyPixmap
)(pBackingStore
->background
.pixmap
);
3653 pBackingStore
->backgroundState
= None
;
3654 pBackingStore
->status
= StatusNoPixmap
;
3655 pWin
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
3659 miTileVirtualBS (pWin
)
3662 miBSWindowPtr pBackingStore
;
3664 pBackingStore
= (miBSWindowPtr
) pWin
->backStorage
;
3665 if (pBackingStore
->backgroundState
== BackgroundPixmap
)
3666 (* pWin
->drawable
.pScreen
->DestroyPixmap
)
3667 (pBackingStore
->background
.pixmap
);
3668 pBackingStore
->backgroundState
= pWin
->backgroundState
;
3669 pBackingStore
->background
= pWin
->background
;
3670 if (pBackingStore
->backgroundState
== BackgroundPixmap
)
3671 pBackingStore
->background
.pixmap
->refcnt
++;
3673 if (pBackingStore
->status
!= StatusVDirty
)
3674 pBackingStore
->status
= StatusVirtual
;
3677 * punt parent relative tiles and do it now
3679 if (pBackingStore
->backgroundState
== ParentRelative
)
3680 miCreateBSPixmap (pWin
, NullBox
);
3684 static int BSAllocationsFailed
= 0;
3685 #define FAILEDSIZE 32
3686 static struct { int w
, h
; } failedRecord
[FAILEDSIZE
];
3687 static int failedIndex
;
3691 miCreateBSPixmap (pWin
, pExtents
)
3695 miBSWindowPtr pBackingStore
;
3697 PixUnion background
;
3698 char backgroundState
= 0;
3702 pScreen
= pWin
->drawable
.pScreen
;
3703 pBackingStore
= (miBSWindowPtr
) pWin
->backStorage
;
3704 if (pBackingStore
->status
== StatusBadAlloc
)
3706 backSet
= ((pBackingStore
->status
== StatusVirtual
) ||
3707 (pBackingStore
->status
== StatusVDirty
));
3709 extents
= REGION_EXTENTS( pScreen
, &pBackingStore
->SavedRegion
);
3711 if (!pBackingStore
->pBackingPixmap
&&
3712 extents
->x2
!= extents
->x1
&&
3713 extents
->y2
!= extents
->y1
)
3715 /* the policy here could be more sophisticated */
3716 pBackingStore
->x
= extents
->x1
;
3717 pBackingStore
->y
= extents
->y1
;
3718 pBackingStore
->pBackingPixmap
=
3719 (PixmapPtr
)(* pScreen
->CreatePixmap
)
3721 extents
->x2
- extents
->x1
,
3722 extents
->y2
- extents
->y1
,
3723 pWin
->drawable
.depth
);
3725 if (!pBackingStore
->pBackingPixmap
)
3728 BSAllocationsFailed
++;
3730 * record failed allocations
3732 failedRecord
[failedIndex
].w
= pWin
->drawable
.width
;
3733 failedRecord
[failedIndex
].h
= pWin
->drawable
.height
;
3735 if (failedIndex
== FAILEDSIZE
)
3739 pBackingStore
->status
= StatusNoPixmap
;
3741 pBackingStore
->status
= StatusBadAlloc
;
3746 pBackingStore
->status
= StatusContents
;
3750 backgroundState
= pWin
->backgroundState
;
3751 background
= pWin
->background
;
3753 pWin
->backgroundState
= pBackingStore
->backgroundState
;
3754 pWin
->background
= pBackingStore
->background
;
3755 if (pWin
->backgroundState
== BackgroundPixmap
)
3756 pWin
->background
.pixmap
->refcnt
++;
3762 if (pExtents
->y1
!= pExtents
->y2
)
3766 exposed
= miBSClearBackingStore(pWin
,
3767 pExtents
->x1
, pExtents
->y1
,
3768 pExtents
->x2
- pExtents
->x1
,
3769 pExtents
->y2
- pExtents
->y1
,
3773 miSendExposures(pWin
, exposed
, pWin
->drawable
.x
, pWin
->drawable
.y
);
3774 REGION_DESTROY( pScreen
, exposed
);
3780 if (pWin
->backgroundState
== BackgroundPixmap
)
3781 (* pScreen
->DestroyPixmap
) (pWin
->background
.pixmap
);
3782 pWin
->backgroundState
= backgroundState
;
3783 pWin
->background
= background
;
3784 if (pBackingStore
->backgroundState
== BackgroundPixmap
)
3785 (* pScreen
->DestroyPixmap
) (pBackingStore
->background
.pixmap
);
3786 pBackingStore
->backgroundState
= None
;
3791 *-----------------------------------------------------------------------
3793 * Handle the restoration of areas exposed by graphics operations.
3799 * prgnExposed has the areas exposed from backing-store removed
3802 *-----------------------------------------------------------------------
3805 miBSExposeCopy (pSrc
, pDst
, pGC
, prgnExposed
, srcx
, srcy
, dstx
, dsty
, plane
)
3809 RegionPtr prgnExposed
;
3812 unsigned long plane
;
3815 miBSWindowPtr pBackingStore
;
3816 CopyPlaneProcPtr copyProc
;
3823 if (!REGION_NOTEMPTY(pGC
->pScreen
, prgnExposed
))
3825 pBackingStore
= (miBSWindowPtr
)pSrc
->backStorage
;
3827 if ((pBackingStore
->status
== StatusNoPixmap
) ||
3828 (pBackingStore
->status
== StatusBadAlloc
))
3831 REGION_NULL( pGC
->pScreen
, &tempRgn
);
3832 REGION_INTERSECT( pGC
->pScreen
, &tempRgn
, prgnExposed
,
3833 &pBackingStore
->SavedRegion
);
3834 REGION_SUBTRACT( pGC
->pScreen
, prgnExposed
, prgnExposed
, &tempRgn
);
3837 copyProc
= pGC
->ops
->CopyPlane
;
3839 copyProc
= (CopyPlaneProcPtr
)pGC
->ops
->CopyArea
;
3845 switch (pBackingStore
->status
) {
3848 pScratchGC
= GetScratchGC (pDst
->depth
, pDst
->pScreen
);
3852 if (pGC
->alu
!= pScratchGC
->alu
)
3853 gcMask
= GCFunction
;
3854 if (pGC
->planemask
!= pScratchGC
->planemask
)
3855 gcMask
|= GCPlaneMask
;
3857 CopyGC (pGC
, pScratchGC
, gcMask
);
3858 miBSFillVirtualBits (pDst
, pScratchGC
, &tempRgn
, dx
, dy
,
3859 (int) pBackingStore
->backgroundState
,
3860 pBackingStore
->background
,
3862 FreeScratchGC (pScratchGC
);
3865 case StatusContents
:
3866 for (i
= REGION_NUM_RECTS(&tempRgn
), pBox
= REGION_RECTS(&tempRgn
);
3870 (* copyProc
) (&(pBackingStore
->pBackingPixmap
->drawable
), pDst
, pGC
,
3871 pBox
->x1
- pBackingStore
->x
,
3872 pBox
->y1
- pBackingStore
->y
,
3873 pBox
->x2
- pBox
->x1
, pBox
->y2
- pBox
->y1
,
3874 pBox
->x1
+ dx
, pBox
->y1
+ dy
, plane
);
3878 REGION_UNINIT( pGC
->pScreen
, &tempRgn
);