1 /* $XConsortium: mibstore.c,v 5.63 94/10/21 20:25:08 dpw Exp $ */
2 /***********************************************************
4 Copyright (c) 1987 X Consortium
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
28 Copyright 1987 by the Regents of the University of California
32 Permission to use, copy, modify, and distribute this software and its
33 documentation for any purpose and without fee is hereby granted, provided
34 that the above copyright notice appear in all copies and that both that
35 copyright notice and this permission notice appear in supporting
36 documentation, and that the name X Consortium not be used in advertising or publicity
37 pertaining to distribution of the software without specific, written prior
40 The University of California makes no representations about the suitability
41 of this software for any purpose. It is provided "as is" without express or
44 ******************************************************************/
51 #include "regionstr.h"
52 #include "scrnintstr.h"
54 #include "extnsionst.h"
55 #include "windowstr.h"
56 #include "pixmapstr.h"
57 #include "fontstruct.h"
58 #include "dixfontstr.h"
59 #include "dixstruct.h" /* For requestingClient */
61 #include "mibstorest.h"
64 * When the server fails to allocate a backing store pixmap, if you want
65 * it to dynamically retry to allocate backing store on every subsequent
66 * graphics op, you can enable BSEAGER; otherwise, backing store will be
67 * disabled on the window until it is unmapped and then remapped.
74 * The functions in this file implement a machine-independent backing-store
75 * scheme. To use it, the output library must do the following:
76 * - Provide a SaveAreas function that takes a destination pixmap, a
77 * region of the areas to save (in the pixmap's coordinate system)
78 * and the screen origin of the region. It should copy the areas from
79 * the screen into the pixmap.
80 * - Provide a RestoreAreas function that takes a source pixmap, a region
81 * of the areas to restore (in the screen's coordinate system) and the
82 * origin of the pixmap on the screen. It should copy the areas from
83 * the pixmap into the screen.
84 * - Provide a SetClipmaskRgn function that takes a gc and a region
85 * and merges the region into any CT_PIXMAP client clip that
86 * is specified in the GC. This routine is only needed if
87 * miValidateBackingStore will see CT_PIXMAP clip lists; not
88 * true for any of the sample servers (which convert the PIXMAP
89 * clip lists into CT_REGION clip lists; an expensive but simple
91 * - The function placed in a window's ClearToBackground vector must call
92 * pScreen->ClearBackingStore with the window, followed by
93 * the window-relative x and y coordinates, followed by the width and
94 * height of the area to be cleared, followed by the generateExposures
95 * flag. This has been taken care of in miClearToBackground.
96 * - Whatever determines GraphicsExpose events for the CopyArea and
97 * CopyPlane requests should call pWin->backStorage->ExposeCopy
98 * with the source and destination drawables, the GC used, a source-
99 * window-relative region of exposed areas, the source and destination
100 * coordinates and the bitplane copied, if CopyPlane, or 0, if
104 * This is a cross between saving everything and just saving the
105 * obscued areas (as in Pike's layers.) This method has the advantage
106 * of only doing each output operation once per pixel, visible or
107 * invisible, and avoids having to do all the crufty storage
108 * management of keeping several separate rectangles. Since the
109 * ddx layer ouput primitives are required to draw through clipping
110 * rectangles anyway, sending multiple drawing requests for each of
111 * several rectangles isn't necessary. (Of course, it could be argued
112 * that the ddx routines should just take one rectangle each and
113 * get called multiple times, but that would make taking advantage of
114 * smart hardware harder, and probably be slower as well.)
117 #define SETUP_BACKING_TERSE(pGC) \
118 miBSGCPtr pGCPrivate = (miBSGCPtr)(pGC)->devPrivates[miBSGCIndex].ptr; \
119 GCFuncs *oldFuncs = pGC->funcs;
121 #define SETUP_BACKING(pDrawable,pGC) \
122 miBSWindowPtr pBackingStore = \
123 (miBSWindowPtr)((WindowPtr)(pDrawable))->backStorage; \
124 DrawablePtr pBackingDrawable = (DrawablePtr) \
125 pBackingStore->pBackingPixmap; \
126 SETUP_BACKING_TERSE(pGC) \
127 GCPtr pBackingGC = pGCPrivate->pBackingGC;
129 #define PROLOGUE(pGC) { \
130 pGC->ops = pGCPrivate->wrapOps;\
131 pGC->funcs = pGCPrivate->wrapFuncs; \
134 #define EPILOGUE(pGC) { \
135 pGCPrivate->wrapOps = (pGC)->ops; \
136 (pGC)->ops = &miBSGCOps; \
137 (pGC)->funcs = oldFuncs; \
140 static void miCreateBSPixmap();
141 static void miDestroyBSPixmap();
142 static void miTileVirtualBS();
143 static void miBSAllocate(), miBSFree();
144 static Bool miBSCreateGCPrivate ();
145 static void miBSClearBackingRegion ();
148 #define MoreCopy2 *dstCopy++ = *srcCopy++; *dstCopy++ = *srcCopy++;
149 #define MoreCopy4 MoreCopy2 MoreCopy2
151 #define copyData(src,dst,n,morecopy) \
153 register short *srcCopy = (short *)(src); \
154 register short *dstCopy = (short *)(dst); \
156 register int bsx = pBackingStore->x; \
157 register int bsy = pBackingStore->y; \
158 for (i = n; --i >= 0; ) \
160 *dstCopy++ = *srcCopy++ - bsx; \
161 *dstCopy++ = *srcCopy++ - bsy; \
166 #define copyPoints(src,dst,n,mode) \
167 if (mode == CoordModeOrigin) \
169 copyData(src,dst,n,MoreCopy0); \
173 memmove((char *)(dst), (char *)(src), (n) << 2); \
174 *((short *)(dst)) -= pBackingStore->x; \
175 *((short *)(dst) + 1) -= pBackingStore->y; \
179 * wrappers for screen funcs
182 static int miBSScreenIndex;
183 static unsigned long miBSGeneration = 0;
185 static Bool miBSCloseScreen();
186 static void miBSGetImage();
187 static void miBSGetSpans();
188 static Bool miBSChangeWindowAttributes();
189 static Bool miBSCreateGC();
190 static Bool miBSDestroyWindow();
193 * backing store screen functions
196 static void miBSSaveDoomedAreas();
197 static RegionPtr miBSRestoreAreas();
198 static void miBSExposeCopy();
199 static RegionPtr miBSTranslateBackingStore(), miBSClearBackingStore();
200 static void miBSDrawGuarantee();
203 * wrapper vectors for GC funcs and ops
206 static int miBSGCIndex;
208 static void miBSValidateGC (), miBSCopyGC (), miBSDestroyGC();
209 static void miBSChangeGC();
210 static void miBSChangeClip(), miBSDestroyClip(), miBSCopyClip();
212 static GCFuncs miBSGCFuncs = {
222 static void miBSFillSpans(), miBSSetSpans(), miBSPutImage();
223 static RegionPtr miBSCopyArea(), miBSCopyPlane();
224 static void miBSPolyPoint(), miBSPolylines(), miBSPolySegment();
225 static void miBSPolyRectangle(),miBSPolyArc(), miBSFillPolygon();
226 static void miBSPolyFillRect(), miBSPolyFillArc();
227 static int miBSPolyText8(), miBSPolyText16();
228 static void miBSImageText8(), miBSImageText16();
229 static void miBSImageGlyphBlt(),miBSPolyGlyphBlt();
230 static void miBSPushPixels();
231 #ifdef NEED_LINEHELPER
232 static void miBSLineHelper();
235 static GCOps miBSGCOps = {
236 miBSFillSpans, miBSSetSpans, miBSPutImage,
237 miBSCopyArea, miBSCopyPlane, miBSPolyPoint,
238 miBSPolylines, miBSPolySegment, miBSPolyRectangle,
239 miBSPolyArc, miBSFillPolygon, miBSPolyFillRect,
240 miBSPolyFillArc, miBSPolyText8, miBSPolyText16,
241 miBSImageText8, miBSImageText16, miBSImageGlyphBlt,
242 miBSPolyGlyphBlt, miBSPushPixels
243 #ifdef NEED_LINEHELPER
248 #define FUNC_PROLOGUE(pGC, pPriv) \
249 ((pGC)->funcs = pPriv->wrapFuncs),\
250 ((pGC)->ops = pPriv->wrapOps)
252 #define FUNC_EPILOGUE(pGC, pPriv) \
253 ((pGC)->funcs = &miBSGCFuncs),\
254 ((pGC)->ops = &miBSGCOps)
257 * every GC in the server is initially wrapped with these
258 * "cheap" functions. This allocates no memory and is used
259 * to discover GCs used with windows which have backing
263 static void miBSCheapValidateGC(), miBSCheapCopyGC(), miBSCheapDestroyGC();
264 static void miBSCheapChangeGC ();
265 static void miBSCheapChangeClip(), miBSCheapDestroyClip();
266 static void miBSCheapCopyClip();
268 static GCFuncs miBSCheapGCFuncs = {
274 miBSCheapDestroyClip,
278 #define CHEAP_FUNC_PROLOGUE(pGC) \
279 ((pGC)->funcs = (GCFuncs *) (pGC)->devPrivates[miBSGCIndex].ptr)
281 #define CHEAP_FUNC_EPILOGUE(pGC) \
282 ((pGC)->funcs = &miBSCheapGCFuncs)
285 * called from device screen initialization proc. Gets a GCPrivateIndex
286 * and wraps appropriate per-screen functions
290 miInitializeBackingStore (pScreen, funcs)
294 miBSScreenPtr pScreenPriv;
296 if (miBSGeneration != serverGeneration)
298 miBSScreenIndex = AllocateScreenPrivateIndex ();
299 if (miBSScreenIndex < 0)
301 miBSGCIndex = AllocateGCPrivateIndex ();
302 miBSGeneration = serverGeneration;
304 if (!AllocateGCPrivate(pScreen, miBSGCIndex, 0))
306 pScreenPriv = (miBSScreenPtr) xalloc (sizeof (miBSScreenRec));
310 pScreenPriv->CloseScreen = pScreen->CloseScreen;
311 pScreenPriv->GetImage = pScreen->GetImage;
312 pScreenPriv->GetSpans = pScreen->GetSpans;
313 pScreenPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
314 pScreenPriv->CreateGC = pScreen->CreateGC;
315 pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
316 pScreenPriv->funcs = funcs;
318 pScreen->CloseScreen = miBSCloseScreen;
319 pScreen->GetImage = miBSGetImage;
320 pScreen->GetSpans = miBSGetSpans;
321 pScreen->ChangeWindowAttributes = miBSChangeWindowAttributes;
322 pScreen->CreateGC = miBSCreateGC;
323 pScreen->DestroyWindow = miBSDestroyWindow;
325 pScreen->SaveDoomedAreas = miBSSaveDoomedAreas;
326 pScreen->RestoreAreas = miBSRestoreAreas;
327 pScreen->ExposeCopy = miBSExposeCopy;
328 pScreen->TranslateBackingStore = miBSTranslateBackingStore;
329 pScreen->ClearBackingStore = miBSClearBackingStore;
330 pScreen->DrawGuarantee = miBSDrawGuarantee;
332 pScreen->devPrivates[miBSScreenIndex].ptr = (pointer) pScreenPriv;
336 * Screen function wrappers
339 #define SCREEN_PROLOGUE(pScreen, field)\
340 ((pScreen)->field = \
342 (pScreen)->devPrivates[miBSScreenIndex].ptr)->field)
344 #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
345 ((pScreen)->field = wrapper)
348 * CloseScreen wrapper -- unwrap everything, free the private data
349 * and call the wrapped function
353 miBSCloseScreen (i, pScreen)
357 miBSScreenPtr pScreenPriv;
359 pScreenPriv = (miBSScreenPtr) pScreen->devPrivates[miBSScreenIndex].ptr;
361 pScreen->CloseScreen = pScreenPriv->CloseScreen;
362 pScreen->GetImage = pScreenPriv->GetImage;
363 pScreen->GetSpans = pScreenPriv->GetSpans;
364 pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes;
365 pScreen->CreateGC = pScreenPriv->CreateGC;
367 xfree ((pointer) pScreenPriv);
369 return (*pScreen->CloseScreen) (i, pScreen);
372 static void miBSFillVirtualBits();
375 miBSGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
376 DrawablePtr pDrawable;
379 unsigned long planemask;
382 ScreenPtr pScreen = pDrawable->pScreen;
386 SCREEN_PROLOGUE (pScreen, GetImage);
388 if (pDrawable->type != DRAWABLE_PIXMAP &&
389 ((WindowPtr) pDrawable)->visibility != VisibilityUnobscured)
392 miBSWindowPtr pWindowPriv;
394 WindowPtr pWin, pSrcWin;
402 pWin = (WindowPtr) pDrawable;
404 depth = pDrawable->depth;
405 bounds.x1 = sx + pDrawable->x;
406 bounds.y1 = sy + pDrawable->y;
407 bounds.x2 = bounds.x1 + w;
408 bounds.y2 = bounds.y1 + h;
409 REGION_INIT(pScreen, &Remaining, &bounds, 0);
412 bounds.x1 = sx + pDrawable->x - pWin->drawable.x;
413 bounds.y1 = sy + pDrawable->y - pWin->drawable.y;
414 bounds.x2 = bounds.x1 + w;
415 bounds.y2 = bounds.y1 + h;
416 if (pWin->viewable && pWin->backStorage &&
417 pWin->drawable.depth == depth &&
418 (RECT_IN_REGION(pScreen, &(pWindowPriv =
419 (miBSWindowPtr) pWin->backStorage)->SavedRegion,
420 &bounds) != rgnOUT ||
421 RECT_IN_REGION(pScreen, &Remaining,
422 REGION_EXTENTS(pScreen, &pWin->borderSize)) != rgnOUT))
426 XID subWindowMode = IncludeInferiors;
429 pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, depth);
432 pGC = GetScratchGC (depth, pScreen);
435 (*pScreen->DestroyPixmap) (pPixmap);
438 ChangeGC (pGC, GCSubwindowMode, &subWindowMode);
439 ValidateGC ((DrawablePtr)pPixmap, pGC);
440 REGION_INIT(pScreen, &Border, NullBox, 0);
441 REGION_INIT(pScreen, &Inside, NullBox, 0);
442 pSrcWin = (WindowPtr) pDrawable;
447 x += pSrcWin->origin.x;
448 y += pSrcWin->origin.y;
449 pSrcWin = pSrcWin->parent;
451 (*pGC->ops->CopyArea) ((DrawablePtr)pSrcWin,
452 (DrawablePtr)pPixmap, pGC,
455 REGION_SUBTRACT(pScreen, &Remaining, &Remaining,
456 &((WindowPtr) pDrawable)->borderClip);
459 REGION_INTERSECT(pScreen, &Inside, &Remaining, &pWin->winSize);
460 REGION_TRANSLATE(pScreen, &Inside,
463 REGION_INTERSECT(pScreen, &Inside, &Inside,
464 &pWindowPriv->SavedRegion);
466 /* offset of sub-window in GetImage pixmap */
467 xoff = pWin->drawable.x - pDrawable->x - sx;
468 yoff = pWin->drawable.y - pDrawable->y - sy;
470 if (REGION_NUM_RECTS(&Inside) > 0)
472 switch (pWindowPriv->status)
475 pBox = REGION_RECTS(&Inside);
476 for (n = REGION_NUM_RECTS(&Inside); --n >= 0;)
478 (*pGC->ops->CopyArea) (
479 (DrawablePtr)pWindowPriv->pBackingPixmap,
480 (DrawablePtr)pPixmap, pGC,
481 pBox->x1 - pWindowPriv->x,
482 pBox->y1 - pWindowPriv->y,
492 if (pWindowPriv->backgroundState == BackgroundPixmap ||
493 pWindowPriv->backgroundState == BackgroundPixel)
494 miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Inside,
496 (int) pWindowPriv->backgroundState,
497 pWindowPriv->background, ~0L);
501 REGION_SUBTRACT(pScreen, &Border, &pWin->borderSize,
503 REGION_INTERSECT(pScreen, &Border, &Border, &Remaining);
504 if (REGION_NUM_RECTS(&Border) > 0)
506 REGION_TRANSLATE(pScreen, &Border, -pWin->drawable.x,
508 miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Border,
510 pWin->borderIsPixel ? (int)BackgroundPixel : (int)BackgroundPixmap,
515 if (pWin->viewable && pWin->firstChild)
516 pWin = pWin->firstChild;
519 while (!pWin->nextSib && pWin != (WindowPtr) pDrawable)
521 if (pWin == (WindowPtr) pDrawable)
523 pWin = pWin->nextSib;
527 REGION_UNINIT(pScreen, &Remaining);
531 REGION_UNINIT(pScreen, &Border);
532 REGION_UNINIT(pScreen, &Inside);
533 (*pScreen->GetImage) ((DrawablePtr) pPixmap,
534 0, 0, w, h, format, planemask, pdstLine);
535 (*pScreen->DestroyPixmap) (pPixmap);
546 (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
547 format, planemask, pdstLine);
550 SCREEN_EPILOGUE (pScreen, GetImage, miBSGetImage);
554 miBSGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
555 DrawablePtr pDrawable;
562 ScreenPtr pScreen = pDrawable->pScreen;
568 SCREEN_PROLOGUE (pScreen, GetSpans);
570 if (pDrawable->type != DRAWABLE_PIXMAP && ((WindowPtr) pDrawable)->backStorage)
573 miBSWindowPtr pWindowPriv;
576 pWin = (WindowPtr) pDrawable;
577 pWindowPriv = (miBSWindowPtr) pWin->backStorage;
578 pPixmap = pWindowPriv->pBackingPixmap;
582 bounds.x2 = bounds.x1 + *pwidth;
584 for (i = 0; i < nspans; i++)
586 if (ppt[i].x < bounds.x1)
587 bounds.x1 = ppt[i].x;
588 if (ppt[i].x + pwidth[i] > bounds.x2)
589 bounds.x2 = ppt[i].x + pwidth[i];
590 if (ppt[i].y < bounds.y1)
591 bounds.y1 = ppt[i].y;
592 else if (ppt[i].y > bounds.y2)
593 bounds.y2 = ppt[i].y;
596 switch (RECT_IN_REGION(pScreen, &pWindowPriv->SavedRegion, &bounds))
601 miCreateBSPixmap (pWin, NullBox);
602 if (!(pPixmap = pWindowPriv->pBackingPixmap))
605 pWindowPriv->status = StatusNoPixmap;
606 pGC = GetScratchGC(pPixmap->drawable.depth,
607 pPixmap->drawable.pScreen);
610 ValidateGC ((DrawablePtr) pPixmap, pGC);
611 (*pGC->ops->CopyArea)
612 (pDrawable, (DrawablePtr) pPixmap, pGC,
613 bounds.x1, bounds.y1,
614 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1,
615 bounds.x1 + pPixmap->drawable.x - pWin->drawable.x -
617 bounds.y1 + pPixmap->drawable.y - pWin->drawable.y -
621 pWindowPriv->status = StatusContents;
626 miCreateBSPixmap (pWin, NullBox);
627 if (!(pPixmap = pWindowPriv->pBackingPixmap))
630 dx = pPixmap->drawable.x - pWin->drawable.x - pWindowPriv->x;
631 dy = pPixmap->drawable.y - pWin->drawable.y - pWindowPriv->y;
632 for (i = 0; i < nspans; i++)
637 (*pScreen->GetSpans) ((DrawablePtr) pPixmap, wMax, ppt, pwidth,
641 (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans,
648 (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
651 SCREEN_EPILOGUE (pScreen, GetSpans, miBSGetSpans);
655 miBSChangeWindowAttributes (pWin, mask)
662 pScreen = pWin->drawable.pScreen;
664 SCREEN_PROLOGUE (pScreen, ChangeWindowAttributes);
666 ret = (*pScreen->ChangeWindowAttributes) (pWin, mask);
668 if (ret && (mask & CWBackingStore))
670 if (pWin->backingStore != NotUseful || pWin->DIXsaveUnder)
676 SCREEN_EPILOGUE (pScreen, ChangeWindowAttributes, miBSChangeWindowAttributes);
682 * GC Create wrapper. Set up the cheap GC func wrappers to track
683 * GC validation on BackingStore windows
690 ScreenPtr pScreen = pGC->pScreen;
693 SCREEN_PROLOGUE (pScreen, CreateGC);
695 if ( (ret = (*pScreen->CreateGC) (pGC)) )
697 pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs;
698 pGC->funcs = &miBSCheapGCFuncs;
701 SCREEN_EPILOGUE (pScreen, CreateGC, miBSCreateGC);
707 miBSDestroyWindow (pWin)
710 ScreenPtr pScreen = pWin->drawable.pScreen;
713 SCREEN_PROLOGUE (pScreen, DestroyWindow);
715 ret = (*pScreen->DestroyWindow) (pWin);
719 SCREEN_EPILOGUE (pScreen, DestroyWindow, miBSDestroyWindow);
725 * cheap GC func wrappers. Simply track validation on windows
726 * with backing store to enable the real func/op wrappers
730 miBSCheapValidateGC (pGC, stateChanges, pDrawable)
732 unsigned long stateChanges;
733 DrawablePtr pDrawable;
735 CHEAP_FUNC_PROLOGUE (pGC);
737 if (pDrawable->type != DRAWABLE_PIXMAP &&
738 ((WindowPtr) pDrawable)->backStorage != NULL &&
739 miBSCreateGCPrivate (pGC))
741 (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
745 (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
747 /* rewrap funcs as Validate may have changed them */
748 pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs;
750 CHEAP_FUNC_EPILOGUE (pGC);
755 miBSCheapChangeGC (pGC, mask)
759 CHEAP_FUNC_PROLOGUE (pGC);
761 (*pGC->funcs->ChangeGC) (pGC, mask);
763 CHEAP_FUNC_EPILOGUE (pGC);
767 miBSCheapCopyGC (pGCSrc, mask, pGCDst)
768 GCPtr pGCSrc, pGCDst;
771 CHEAP_FUNC_PROLOGUE (pGCDst);
773 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
775 CHEAP_FUNC_EPILOGUE (pGCDst);
779 miBSCheapDestroyGC (pGC)
782 CHEAP_FUNC_PROLOGUE (pGC);
784 (*pGC->funcs->DestroyGC) (pGC);
786 /* leave it unwrapped */
790 miBSCheapChangeClip (pGC, type, pvalue, nrects)
796 CHEAP_FUNC_PROLOGUE (pGC);
798 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
800 CHEAP_FUNC_EPILOGUE (pGC);
804 miBSCheapCopyClip(pgcDst, pgcSrc)
805 GCPtr pgcDst, pgcSrc;
807 CHEAP_FUNC_PROLOGUE (pgcDst);
809 (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
811 CHEAP_FUNC_EPILOGUE (pgcDst);
815 miBSCheapDestroyClip(pGC)
818 CHEAP_FUNC_PROLOGUE (pGC);
820 (* pGC->funcs->DestroyClip)(pGC);
822 CHEAP_FUNC_EPILOGUE (pGC);
826 * create the full func/op wrappers for a GC
830 miBSCreateGCPrivate (pGC)
835 pPriv = (miBSGCRec *) xalloc (sizeof (miBSGCRec));
838 pPriv->pBackingGC = NULL;
839 pPriv->guarantee = GuaranteeNothing;
840 pPriv->serialNumber = 0;
841 pPriv->stateChanges = (1 << (GCLastBit + 1)) - 1;
842 pPriv->wrapOps = pGC->ops;
843 pPriv->wrapFuncs = pGC->funcs;
844 pGC->funcs = &miBSGCFuncs;
845 pGC->ops = &miBSGCOps;
846 pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv;
851 miBSDestroyGCPrivate (pGC)
856 pPriv = (miBSGCRec *) pGC->devPrivates[miBSGCIndex].ptr;
859 pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv->wrapFuncs;
860 pGC->funcs = &miBSCheapGCFuncs;
861 pGC->ops = pPriv->wrapOps;
862 if (pPriv->pBackingGC)
863 FreeGC (pPriv->pBackingGC, (GContext) 0);
864 xfree ((pointer) pPriv);
869 * GC ops -- wrap each GC operation with our own function
873 *-----------------------------------------------------------------------
875 * Perform a FillSpans, routing output to backing-store as needed.
882 *-----------------------------------------------------------------------
885 miBSFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
886 DrawablePtr pDrawable;
888 int nInit; /* number of spans to fill */
889 DDXPointPtr pptInit; /* pointer to list of start points */
890 int *pwidthInit; /* pointer to list of n widths */
893 DDXPointPtr pptCopy, pptReset;
895 SETUP_BACKING (pDrawable, pGC);
899 pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nInit*sizeof(DDXPointRec));
900 pwidthCopy=(int *)ALLOCATE_LOCAL(nInit*sizeof(int));
901 if (pptCopy && pwidthCopy)
903 copyData(pptInit, pptCopy, nInit, MoreCopy0);
904 memmove((char *)pwidthCopy,(char *)pwidthInit,nInit*sizeof(int));
906 (* pGC->ops->FillSpans)(pDrawable, pGC, nInit, pptInit,
907 pwidthInit, fSorted);
908 if (pGC->miTranslate)
914 dx = pDrawable->x - pBackingDrawable->x;
915 dy = pDrawable->y - pBackingDrawable->y;
924 (* pBackingGC->ops->FillSpans)(pBackingDrawable,
925 pBackingGC, nInit, pptCopy, pwidthCopy,
928 if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy);
929 if (pptCopy) DEALLOCATE_LOCAL(pptCopy);
935 *-----------------------------------------------------------------------
937 * Perform a SetSpans, routing output to backing-store as needed.
944 *-----------------------------------------------------------------------
947 miBSSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
948 DrawablePtr pDrawable;
951 register DDXPointPtr ppt;
956 DDXPointPtr pptCopy, pptReset;
958 SETUP_BACKING (pDrawable, pGC);
962 pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nspans*sizeof(DDXPointRec));
963 pwidthCopy=(int *)ALLOCATE_LOCAL(nspans*sizeof(int));
964 if (pptCopy && pwidthCopy)
966 copyData(ppt, pptCopy, nspans, MoreCopy0);
967 memmove((char *)pwidthCopy,(char *)pwidth,nspans*sizeof(int));
969 (* pGC->ops->SetSpans)(pDrawable, pGC, psrc, ppt, pwidth,
971 if (pGC->miTranslate)
977 dx = pDrawable->x - pBackingDrawable->x;
978 dy = pDrawable->y - pBackingDrawable->y;
987 (* pBackingGC->ops->SetSpans)(pBackingDrawable, pBackingGC,
988 psrc, pptCopy, pwidthCopy, nspans, fSorted);
990 if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy);
991 if (pptCopy) DEALLOCATE_LOCAL(pptCopy);
997 *-----------------------------------------------------------------------
999 * Perform a PutImage, routing output to backing-store as needed.
1006 *-----------------------------------------------------------------------
1009 miBSPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
1010 DrawablePtr pDrawable;
1021 SETUP_BACKING (pDrawable, pGC);
1025 (*pGC->ops->PutImage)(pDrawable, pGC,
1026 depth, x, y, w, h, leftPad, format, pBits);
1027 (*pBackingGC->ops->PutImage)(pBackingDrawable, pBackingGC,
1028 depth, x - pBackingStore->x, y - pBackingStore->y,
1029 w, h, leftPad, format, pBits);
1035 *-----------------------------------------------------------------------
1037 * Perform a CopyArea or CopyPlane within a window that has backing
1041 * TRUE if the copy was performed or FALSE if a regular one should
1045 * Things are copied (no s***!)
1048 * The idea here is to form two regions that cover the source box.
1049 * One contains the exposed rectangles while the other contains
1050 * the obscured ones. An array of <box, drawable> pairs is then
1051 * formed where the <box> indicates the area to be copied and the
1052 * <drawable> indicates from where it is to be copied (exposed regions
1053 * come from the screen while obscured ones come from the backing
1054 * pixmap). The array 'sequence' is then filled with the indices of
1055 * the pairs in the order in which they should be copied to prevent
1056 * things from getting screwed up. A call is also made through the
1057 * backingGC to take care of any copying into the backing pixmap.
1059 *-----------------------------------------------------------------------
1062 miBSDoCopy(pWin, pGC, srcx, srcy, w, h, dstx, dsty, plane, copyProc, ppRgn)
1063 WindowPtr pWin; /* Window being scrolled */
1064 GCPtr pGC; /* GC we're called through */
1065 int srcx; /* X of source rectangle */
1066 int srcy; /* Y of source rectangle */
1067 int w; /* Width of source rectangle */
1068 int h; /* Height of source rectangle */
1069 int dstx; /* X of destination rectangle */
1070 int dsty; /* Y of destination rectangle */
1071 unsigned long plane; /* Plane to copy (0 for CopyArea) */
1072 RegionPtr (*copyProc)(); /* Procedure to call to perform the copy */
1073 RegionPtr *ppRgn; /* resultant Graphics Expose region */
1075 RegionPtr pRgnExp; /* Exposed region */
1076 RegionPtr pRgnObs; /* Obscured region */
1077 BoxRec box; /* Source box (screen coord) */
1079 BoxPtr pBox; /* Source box */
1082 } source; /* Place from which to copy */
1083 } *boxes; /* Array of box/drawable pairs covering
1085 int *sequence; /* Sequence of boxes to move */
1086 register int i, j, k, l, y;
1087 register BoxPtr pBox;
1089 Bool graphicsExposures;
1090 RegionPtr (*pixCopyProc)();
1091 int numRectsExp, numRectsObs;
1092 BoxPtr pBoxExp, pBoxObs;
1094 SETUP_BACKING (pWin, pGC);
1097 * Create a region of exposed boxes in pRgnExp.
1099 box.x1 = srcx + pWin->drawable.x;
1100 box.x2 = box.x1 + w;
1101 box.y1 = srcy + pWin->drawable.y;
1102 box.y2 = box.y1 + h;
1104 pRgnExp = REGION_CREATE(pGC->pScreen, &box, 1);
1105 REGION_INTERSECT(pGC->pScreen, pRgnExp, pRgnExp, &pWin->clipList);
1106 pRgnObs = REGION_CREATE(pGC->pScreen, NULL, 1);
1107 REGION_INVERSE( pGC->pScreen, pRgnObs, pRgnExp, &box);
1110 * Translate regions into window coordinates for proper calls
1111 * to the copyProc, then make sure none of the obscured region sticks
1112 * into invalid areas of the backing pixmap.
1114 REGION_TRANSLATE(pGC->pScreen, pRgnExp,
1117 REGION_TRANSLATE(pGC->pScreen, pRgnObs,
1120 REGION_INTERSECT(pGC->pScreen, pRgnObs, pRgnObs, &pBackingStore->SavedRegion);
1123 * If the obscured region is empty, there's no point being fancy.
1125 if (!REGION_NOTEMPTY(pGC->pScreen, pRgnObs))
1127 REGION_DESTROY(pGC->pScreen, pRgnExp);
1128 REGION_DESTROY(pGC->pScreen, pRgnObs);
1133 numRectsExp = REGION_NUM_RECTS(pRgnExp);
1134 pBoxExp = REGION_RECTS(pRgnExp);
1135 pBoxObs = REGION_RECTS(pRgnObs);
1136 numRectsObs = REGION_NUM_RECTS(pRgnObs);
1137 nrects = numRectsExp + numRectsObs;
1139 boxes = (struct BoxDraw *)ALLOCATE_LOCAL(nrects * sizeof(struct BoxDraw));
1140 sequence = (int *) ALLOCATE_LOCAL(nrects * sizeof(int));
1143 if (!boxes || !sequence)
1145 if (sequence) DEALLOCATE_LOCAL(sequence);
1146 if (boxes) DEALLOCATE_LOCAL(boxes);
1147 REGION_DESTROY(pGC->pScreen, pRgnExp);
1148 REGION_DESTROY(pGC->pScreen, pRgnObs);
1154 * Order the boxes in the two regions so we know from which drawable
1155 * to copy which box, storing the result in the boxes array
1157 for (i = 0, j = 0, k = 0;
1158 (i < numRectsExp) && (j < numRectsObs);
1161 if (pBoxExp[i].y1 < pBoxObs[j].y1)
1163 boxes[k].pBox = &pBoxExp[i];
1164 boxes[k].source = win;
1167 else if ((pBoxObs[j].y1 < pBoxExp[i].y1) ||
1168 (pBoxObs[j].x1 < pBoxExp[i].x1))
1170 boxes[k].pBox = &pBoxObs[j];
1171 boxes[k].source = pix;
1176 boxes[k].pBox = &pBoxExp[i];
1177 boxes[k].source = win;
1183 * Catch any leftover boxes from either region (note that only
1184 * one can have leftover boxes...)
1186 if (i != numRectsExp)
1190 boxes[k].pBox = &pBoxExp[i];
1191 boxes[k].source = win;
1194 } while (i < numRectsExp);
1201 boxes[k].pBox = &pBoxObs[j];
1202 boxes[k].source = pix;
1205 } while (j < numRectsObs);
1211 * Scroll up or vertically stationary, so vertical order is ok.
1216 * Scroll left or horizontally stationary, so horizontal order
1219 for (i = 0; i < nrects; i++)
1227 * Scroll right. Need to reverse the rectangles within each
1230 for (i = 0, j = 1, k = 0;
1234 y = boxes[i].pBox->y1;
1235 while ((j < nrects) && (boxes[j].pBox->y1 == y))
1239 for (j--; j >= k; j--, i++)
1249 * Scroll down. Must reverse vertical banding, at least.
1254 * Scroll left. Horizontal order is ok.
1256 for (i = nrects - 1, j = i - 1, k = i, l = 0;
1261 * Find extent of current horizontal band, then reverse
1262 * the order of the whole band.
1264 y = boxes[i].pBox->y1;
1265 while ((j >= 0) && (boxes[j].pBox->y1 == y))
1269 for (j++; j <= k; j++, i--, l++)
1278 * Scroll right or horizontal stationary.
1279 * Reverse horizontal order as well (if stationary, horizontal
1280 * order can be swapped without penalty and this is faster
1283 for (i = 0, j = nrects - 1; i < nrects; i++, j--)
1291 * XXX: To avoid getting multiple NoExpose events from this operation,
1292 * we turn OFF graphicsExposures in the gc and deal with any uncopied
1293 * areas later, if there's something not in backing-store.
1296 graphicsExposures = pGC->graphicsExposures;
1297 pGC->graphicsExposures = FALSE;
1303 * Figure out which copy procedure to use from the backing GC. Note we
1304 * must do this because some implementations (sun's, e.g.) have
1305 * pBackingGC a fake GC with the real one below it, thus the devPriv for
1306 * pBackingGC won't be what the output library expects.
1310 pixCopyProc = pBackingGC->ops->CopyPlane;
1314 pixCopyProc = pBackingGC->ops->CopyArea;
1317 for (i = 0; i < nrects; i++)
1319 pBox = boxes[sequence[i]].pBox;
1322 * If we're copying from the pixmap, we need to place its contents
1323 * onto the screen before scrolling the pixmap itself. If we're copying
1324 * from the window, we need to copy its contents into the pixmap before
1325 * we scroll the window itself.
1327 if (boxes[sequence[i]].source == pix)
1329 (void) (* copyProc) (pBackingDrawable, pWin, pGC,
1330 pBox->x1 - pBackingStore->x,
1331 pBox->y1 - pBackingStore->y,
1332 pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
1333 pBox->x1 + dx, pBox->y1 + dy, plane);
1334 (void) (* pixCopyProc) (pBackingDrawable, pBackingDrawable, pBackingGC,
1335 pBox->x1 - pBackingStore->x,
1336 pBox->y1 - pBackingStore->y,
1337 pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
1338 pBox->x1 + dx - pBackingStore->x,
1339 pBox->y1 + dy - pBackingStore->y, plane);
1343 (void) (* pixCopyProc) (pWin, pBackingDrawable, pBackingGC,
1345 pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
1346 pBox->x1 + dx - pBackingStore->x,
1347 pBox->y1 + dy - pBackingStore->y, plane);
1348 (void) (* copyProc) (pWin, pWin, pGC,
1350 pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
1351 pBox->x1 + dx, pBox->y1 + dy, plane);
1354 DEALLOCATE_LOCAL(sequence);
1355 DEALLOCATE_LOCAL(boxes);
1357 pGC->graphicsExposures = graphicsExposures;
1359 * Form union of rgnExp and rgnObs and see if covers entire area
1360 * to be copied. Store the resultant region for miBSCopyArea
1361 * to return to dispatch which will send the appropriate expose
1364 REGION_UNION(pGC->pScreen, pRgnExp, pRgnExp, pRgnObs);
1369 if (RECT_IN_REGION(pGC->pScreen, pRgnExp, &box) == rgnIN)
1371 REGION_EMPTY(pGC->pScreen, pRgnExp);
1375 REGION_INVERSE( pGC->pScreen, pRgnExp, pRgnExp, &box);
1376 REGION_TRANSLATE( pGC->pScreen, pRgnExp,
1377 dx + pWin->drawable.x,
1378 dy + pWin->drawable.y);
1379 REGION_INTERSECT( pGC->pScreen, pRgnObs, pRgnExp, &pWin->clipList);
1380 (*pWin->drawable.pScreen->PaintWindowBackground) (pWin,
1381 pRgnObs, PW_BACKGROUND);
1382 REGION_TRANSLATE( pGC->pScreen, pRgnExp,
1385 miBSClearBackingRegion (pWin, pRgnExp);
1387 if (graphicsExposures)
1390 REGION_DESTROY(pGC->pScreen, pRgnExp);
1391 REGION_DESTROY(pGC->pScreen, pRgnObs);
1397 *-----------------------------------------------------------------------
1399 * Perform a CopyArea from the source to the destination, extracting
1400 * from the source's backing-store and storing into the destination's
1401 * backing-store without messing anything up. If the source and
1402 * destination are different, there's not too much to worry about:
1403 * we can just issue several calls to the regular CopyArea function.
1410 *-----------------------------------------------------------------------
1413 miBSCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
1426 int bsrcx, bsrcy, bw, bh, bdstx, bdsty;
1427 RegionPtr pixExposed = 0, winExposed = 0;
1429 SETUP_BACKING(pDst, pGC);
1433 if ((pSrc != pDst) ||
1434 (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty,
1435 (unsigned long) 0, pGC->ops->CopyArea, &winExposed)))
1438 * always copy to the backing store first, miBSDoCopy
1439 * returns FALSE if the *source* region is disjoint
1440 * from the backing store saved region. So, copying
1441 * *to* the backing store is always safe
1443 if (pGC->clientClipType != CT_PIXMAP)
1446 * adjust srcx, srcy, w, h, dstx, dsty to be clipped to
1447 * the backing store. An unnecessary optimisation,
1448 * but a useful one when GetSpans is slow.
1450 pExtents = REGION_EXTENTS(pDst->pScreen,
1451 (RegionPtr)pBackingGC->clientClip);
1458 dx = pExtents->x1 - bdstx;
1465 dy = pExtents->y1 - bdsty;
1472 dx = (bdstx + bw) - pExtents->x2;
1475 dy = (bdsty + bh) - pExtents->y2;
1478 if (bw > 0 && bh > 0)
1479 pixExposed = (* pBackingGC->ops->CopyArea) (pSrc,
1480 pBackingDrawable, pBackingGC,
1481 bsrcx, bsrcy, bw, bh, bdstx - pBackingStore->x,
1482 bdsty - pBackingStore->y);
1485 pixExposed = (* pBackingGC->ops->CopyArea) (pSrc,
1486 pBackingDrawable, pBackingGC,
1488 dstx - pBackingStore->x, dsty - pBackingStore->y);
1490 winExposed = (* pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
1494 * compute the composite graphics exposure region
1499 REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed);
1500 REGION_DESTROY(pDst->pScreen, pixExposed);
1503 winExposed = pixExposed;
1511 *-----------------------------------------------------------------------
1519 *-----------------------------------------------------------------------
1522 miBSCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
1532 unsigned long plane;
1536 int bsrcx, bsrcy, bw, bh, bdstx, bdsty;
1537 RegionPtr winExposed = 0, pixExposed = 0;
1538 SETUP_BACKING(pDst, pGC);
1542 if ((pSrc != pDst) ||
1543 (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty,
1544 plane, pGC->ops->CopyPlane, &winExposed)))
1547 * always copy to the backing store first, miBSDoCopy
1548 * returns FALSE if the *source* region is disjoint
1549 * from the backing store saved region. So, copying
1550 * *to* the backing store is always safe
1552 if (pGC->clientClipType != CT_PIXMAP)
1555 * adjust srcx, srcy, w, h, dstx, dsty to be clipped to
1556 * the backing store. An unnecessary optimisation,
1557 * but a useful one when GetSpans is slow.
1559 pExtents = REGION_EXTENTS(pDst->pScreen,
1560 (RegionPtr)pBackingGC->clientClip);
1567 dx = pExtents->x1 - bdstx;
1574 dy = pExtents->y1 - bdsty;
1581 dx = (bdstx + bw) - pExtents->x2;
1584 dy = (bdsty + bh) - pExtents->y2;
1587 if (bw > 0 && bh > 0)
1588 pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc,
1590 pBackingGC, bsrcx, bsrcy, bw, bh,
1591 bdstx - pBackingStore->x,
1592 bdsty - pBackingStore->y, plane);
1595 pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc,
1597 pBackingGC, srcx, srcy, w, h,
1598 dstx - pBackingStore->x,
1599 dsty - pBackingStore->y, plane);
1601 winExposed = (* pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
1607 * compute the composite graphics exposure region
1613 REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed);
1614 REGION_DESTROY(pDst->pScreen, pixExposed);
1617 winExposed = pixExposed;
1625 *-----------------------------------------------------------------------
1627 * Perform a PolyPoint, routing output to backing-store as needed.
1634 *-----------------------------------------------------------------------
1637 miBSPolyPoint (pDrawable, pGC, mode, npt, pptInit)
1638 DrawablePtr pDrawable;
1640 int mode; /* Origin or Previous */
1645 SETUP_BACKING (pDrawable, pGC);
1649 pptCopy = (xPoint *)ALLOCATE_LOCAL(npt*sizeof(xPoint));
1652 copyPoints(pptInit, pptCopy, npt, mode);
1654 (* pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
1656 (* pBackingGC->ops->PolyPoint) (pBackingDrawable,
1657 pBackingGC, mode, npt, pptCopy);
1659 DEALLOCATE_LOCAL(pptCopy);
1666 *-----------------------------------------------------------------------
1668 * Perform a Polylines, routing output to backing-store as needed.
1674 *-----------------------------------------------------------------------
1677 miBSPolylines (pDrawable, pGC, mode, npt, pptInit)
1678 DrawablePtr pDrawable;
1682 DDXPointPtr pptInit;
1684 DDXPointPtr pptCopy;
1685 SETUP_BACKING (pDrawable, pGC);
1689 pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(npt*sizeof(DDXPointRec));
1692 copyPoints(pptInit, pptCopy, npt, mode);
1694 (* pGC->ops->Polylines)(pDrawable, pGC, mode, npt, pptInit);
1695 (* pBackingGC->ops->Polylines)(pBackingDrawable,
1696 pBackingGC, mode, npt, pptCopy);
1697 DEALLOCATE_LOCAL(pptCopy);
1704 *-----------------------------------------------------------------------
1705 * miBSPolySegment --
1706 * Perform a PolySegment, routing output to backing-store as needed.
1713 *-----------------------------------------------------------------------
1716 miBSPolySegment(pDrawable, pGC, nseg, pSegs)
1717 DrawablePtr pDrawable;
1722 xSegment *pSegsCopy;
1724 SETUP_BACKING (pDrawable, pGC);
1728 pSegsCopy = (xSegment *)ALLOCATE_LOCAL(nseg*sizeof(xSegment));
1731 copyData(pSegs, pSegsCopy, nseg << 1, MoreCopy0);
1733 (* pGC->ops->PolySegment)(pDrawable, pGC, nseg, pSegs);
1734 (* pBackingGC->ops->PolySegment)(pBackingDrawable,
1735 pBackingGC, nseg, pSegsCopy);
1737 DEALLOCATE_LOCAL(pSegsCopy);
1744 *-----------------------------------------------------------------------
1745 * miBSPolyRectangle --
1746 * Perform a PolyRectangle, routing output to backing-store as needed.
1753 *-----------------------------------------------------------------------
1756 miBSPolyRectangle(pDrawable, pGC, nrects, pRects)
1757 DrawablePtr pDrawable;
1762 xRectangle *pRectsCopy;
1763 SETUP_BACKING (pDrawable, pGC);
1767 pRectsCopy =(xRectangle *)ALLOCATE_LOCAL(nrects*sizeof(xRectangle));
1770 copyData(pRects, pRectsCopy, nrects, MoreCopy2);
1772 (* pGC->ops->PolyRectangle)(pDrawable, pGC, nrects, pRects);
1773 (* pBackingGC->ops->PolyRectangle)(pBackingDrawable,
1774 pBackingGC, nrects, pRectsCopy);
1776 DEALLOCATE_LOCAL(pRectsCopy);
1783 *-----------------------------------------------------------------------
1785 * Perform a PolyArc, routing output to backing-store as needed.
1791 *-----------------------------------------------------------------------
1794 miBSPolyArc(pDrawable, pGC, narcs, parcs)
1795 DrawablePtr pDrawable;
1801 SETUP_BACKING (pDrawable, pGC);
1805 pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc));
1808 copyData(parcs, pArcsCopy, narcs, MoreCopy4);
1810 (* pGC->ops->PolyArc)(pDrawable, pGC, narcs, parcs);
1811 (* pBackingGC->ops->PolyArc)(pBackingDrawable, pBackingGC,
1814 DEALLOCATE_LOCAL(pArcsCopy);
1821 *-----------------------------------------------------------------------
1822 * miBSFillPolygon --
1823 * Perform a FillPolygon, routing output to backing-store as needed.
1830 *-----------------------------------------------------------------------
1833 miBSFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
1834 DrawablePtr pDrawable;
1840 DDXPointPtr pPtsCopy;
1841 SETUP_BACKING (pDrawable, pGC);
1845 pPtsCopy = (DDXPointPtr)ALLOCATE_LOCAL(count*sizeof(DDXPointRec));
1848 copyPoints(pPts, pPtsCopy, count, mode);
1849 (* pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, count, pPts);
1850 (* pBackingGC->ops->FillPolygon)(pBackingDrawable,
1851 pBackingGC, shape, mode,
1854 DEALLOCATE_LOCAL(pPtsCopy);
1861 *-----------------------------------------------------------------------
1862 * miBSPolyFillRect --
1863 * Perform a PolyFillRect, routing output to backing-store as needed.
1870 *-----------------------------------------------------------------------
1873 miBSPolyFillRect(pDrawable, pGC, nrectFill, prectInit)
1874 DrawablePtr pDrawable;
1876 int nrectFill; /* number of rectangles to fill */
1877 xRectangle *prectInit; /* Pointer to first rectangle to fill */
1879 xRectangle *pRectCopy;
1880 SETUP_BACKING (pDrawable, pGC);
1885 (xRectangle *)ALLOCATE_LOCAL(nrectFill*sizeof(xRectangle));
1888 copyData(prectInit, pRectCopy, nrectFill, MoreCopy2);
1890 (* pGC->ops->PolyFillRect)(pDrawable, pGC, nrectFill, prectInit);
1891 (* pBackingGC->ops->PolyFillRect)(pBackingDrawable,
1892 pBackingGC, nrectFill, pRectCopy);
1894 DEALLOCATE_LOCAL(pRectCopy);
1901 *-----------------------------------------------------------------------
1902 * miBSPolyFillArc --
1903 * Perform a PolyFillArc, routing output to backing-store as needed.
1910 *-----------------------------------------------------------------------
1913 miBSPolyFillArc(pDrawable, pGC, narcs, parcs)
1914 DrawablePtr pDrawable;
1920 SETUP_BACKING (pDrawable, pGC);
1924 pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc));
1927 copyData(parcs, pArcsCopy, narcs, MoreCopy4);
1928 (* pGC->ops->PolyFillArc)(pDrawable, pGC, narcs, parcs);
1929 (* pBackingGC->ops->PolyFillArc)(pBackingDrawable,
1930 pBackingGC, narcs, pArcsCopy);
1931 DEALLOCATE_LOCAL(pArcsCopy);
1939 *-----------------------------------------------------------------------
1941 * Perform a PolyText8, routing output to backing-store as needed.
1947 *-----------------------------------------------------------------------
1950 miBSPolyText8(pDrawable, pGC, x, y, count, chars)
1951 DrawablePtr pDrawable;
1958 SETUP_BACKING (pDrawable, pGC);
1962 result = (* pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
1963 (* pBackingGC->ops->PolyText8)(pBackingDrawable, pBackingGC,
1964 x - pBackingStore->x, y - pBackingStore->y,
1972 *-----------------------------------------------------------------------
1974 * Perform a PolyText16, routing output to backing-store as needed.
1980 *-----------------------------------------------------------------------
1983 miBSPolyText16(pDrawable, pGC, x, y, count, chars)
1984 DrawablePtr pDrawable;
1988 unsigned short *chars;
1991 SETUP_BACKING (pDrawable, pGC);
1995 result = (* pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
1996 (* pBackingGC->ops->PolyText16)(pBackingDrawable, pBackingGC,
1997 x - pBackingStore->x, y - pBackingStore->y,
2006 *-----------------------------------------------------------------------
2008 * Perform a ImageText8, routing output to backing-store as needed.
2014 *-----------------------------------------------------------------------
2017 miBSImageText8(pDrawable, pGC, x, y, count, chars)
2018 DrawablePtr pDrawable;
2024 SETUP_BACKING (pDrawable, pGC);
2027 (* pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
2028 (* pBackingGC->ops->ImageText8)(pBackingDrawable, pBackingGC,
2029 x - pBackingStore->x, y - pBackingStore->y,
2036 *-----------------------------------------------------------------------
2037 * miBSImageText16 --
2038 * Perform a ImageText16, routing output to backing-store as needed.
2044 *-----------------------------------------------------------------------
2047 miBSImageText16(pDrawable, pGC, x, y, count, chars)
2048 DrawablePtr pDrawable;
2052 unsigned short *chars;
2054 SETUP_BACKING (pDrawable, pGC);
2057 (* pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
2058 (* pBackingGC->ops->ImageText16)(pBackingDrawable, pBackingGC,
2059 x - pBackingStore->x, y - pBackingStore->y,
2066 *-----------------------------------------------------------------------
2067 * miBSImageGlyphBlt --
2068 * Perform a ImageGlyphBlt, routing output to backing-store as needed.
2074 *-----------------------------------------------------------------------
2077 miBSImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
2078 DrawablePtr pDrawable;
2081 unsigned int nglyph;
2082 CharInfoPtr *ppci; /* array of character info */
2083 pointer pglyphBase; /* start of array of glyphs */
2085 SETUP_BACKING (pDrawable, pGC);
2088 (* pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci,
2090 (* pBackingGC->ops->ImageGlyphBlt)(pBackingDrawable, pBackingGC,
2091 x - pBackingStore->x, y - pBackingStore->y,
2092 nglyph, ppci, pglyphBase);
2098 *-----------------------------------------------------------------------
2099 * miBSPolyGlyphBlt --
2100 * Perform a PolyGlyphBlt, routing output to backing-store as needed.
2106 *-----------------------------------------------------------------------
2109 miBSPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
2110 DrawablePtr pDrawable;
2113 unsigned int nglyph;
2114 CharInfoPtr *ppci; /* array of character info */
2115 pointer pglyphBase; /* start of array of glyphs */
2117 SETUP_BACKING (pDrawable, pGC);
2120 (* pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
2122 (* pBackingGC->ops->PolyGlyphBlt)(pBackingDrawable, pBackingGC,
2123 x - pBackingStore->x, y - pBackingStore->y,
2124 nglyph, ppci, pglyphBase);
2129 *-----------------------------------------------------------------------
2131 * Perform a PushPixels, routing output to backing-store as needed.
2137 *-----------------------------------------------------------------------
2140 miBSPushPixels(pGC, pBitMap, pDst, w, h, x, y)
2146 SETUP_BACKING (pDst, pGC);
2149 (* pGC->ops->PushPixels)(pGC, pBitMap, pDst, w, h, x, y);
2150 if (pGC->miTranslate) {
2154 (* pBackingGC->ops->PushPixels)(pBackingGC, pBitMap,
2155 pBackingDrawable, w, h,
2156 x - pBackingStore->x, y - pBackingStore->y);
2161 #ifdef NEED_LINEHELPER
2163 *-----------------------------------------------------------------------
2166 * Results: should never be called
2168 * Side Effects: server dies
2170 *-----------------------------------------------------------------------
2175 FatalError("miBSLineHelper called\n");
2180 *-----------------------------------------------------------------------
2181 * miBSClearBackingStore --
2182 * Clear the given area of the backing pixmap with the background of
2183 * the window, whatever it is. If generateExposures is TRUE, generate
2184 * exposure events for the area. Note that if the area has any
2185 * part outside the saved portions of the window, we do not allow the
2186 * count in the expose events to be 0, since there will be more
2187 * expose events to come.
2193 * Areas of pixmap are cleared and Expose events are generated.
2195 *-----------------------------------------------------------------------
2198 miBSClearBackingStore(pWin, x, y, w, h, generateExposures)
2204 Bool generateExposures;
2208 miBSWindowPtr pBackingStore;
2213 pointer gcvalues[4];
2214 unsigned long gcmask;
2218 PixUnion background;
2219 char backgroundState;
2222 pBackingStore = (miBSWindowPtr)pWin->backStorage;
2223 pScreen = pWin->drawable.pScreen;
2225 if ((pBackingStore->status == StatusNoPixmap) ||
2226 (pBackingStore->status == StatusBadAlloc))
2230 w = (int) pWin->drawable.width - x;
2232 h = (int) pWin->drawable.height - y;
2238 pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1);
2241 REGION_INTERSECT( pScreen, pRgn, pRgn, &pBackingStore->SavedRegion);
2243 if (REGION_NOTEMPTY( pScreen, pRgn))
2246 * if clearing entire window, simply make new virtual
2247 * tile. For the root window, we also destroy the pixmap
2248 * to save a pile of memory
2250 if (x == 0 && y == 0 &&
2251 w == pWin->drawable.width &&
2252 h == pWin->drawable.height)
2255 miDestroyBSPixmap (pWin);
2256 if (pBackingStore->status != StatusContents)
2257 miTileVirtualBS (pWin);
2260 ts_x_origin = ts_y_origin = 0;
2262 backgroundState = pWin->backgroundState;
2263 background = pWin->background;
2264 if (backgroundState == ParentRelative) {
2268 while (pParent->backgroundState == ParentRelative) {
2269 ts_x_origin -= pParent->origin.x;
2270 ts_y_origin -= pParent->origin.y;
2271 pParent = pParent->parent;
2273 backgroundState = pParent->backgroundState;
2274 background = pParent->background;
2277 if ((backgroundState != None) &&
2278 ((pBackingStore->status == StatusContents) ||
2279 !SameBackground (pBackingStore->backgroundState,
2280 pBackingStore->background,
2284 if (!pBackingStore->pBackingPixmap)
2285 miCreateBSPixmap(pWin, NullBox);
2287 pGC = GetScratchGC(pWin->drawable.depth, pScreen);
2288 if (pGC && pBackingStore->pBackingPixmap)
2291 * First take care of any ParentRelative stuff by altering the
2292 * tile/stipple origin to match the coordinates of the upper-left
2293 * corner of the first ancestor without a ParentRelative background.
2294 * This coordinate is, of course, negative.
2297 if (backgroundState == BackgroundPixel)
2299 gcvalues[0] = (pointer) background.pixel;
2300 gcvalues[1] = (pointer)FillSolid;
2301 gcmask = GCForeground|GCFillStyle;
2305 gcvalues[0] = (pointer)FillTiled;
2306 gcvalues[1] = (pointer) background.pixmap;
2307 gcmask = GCFillStyle|GCTile;
2309 gcvalues[2] = (pointer)(ts_x_origin - pBackingStore->x);
2310 gcvalues[3] = (pointer)(ts_y_origin - pBackingStore->y);
2311 gcmask |= GCTileStipXOrigin|GCTileStipYOrigin;
2312 DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE);
2313 ValidateGC((DrawablePtr)pBackingStore->pBackingPixmap, pGC);
2316 * Figure out the array of rectangles to fill and fill them with
2317 * PolyFillRect in the proper mode, as set in the GC above.
2319 numRects = REGION_NUM_RECTS(pRgn);
2320 rects = (xRectangle *)ALLOCATE_LOCAL(numRects*sizeof(xRectangle));
2324 for (i = 0, pBox = REGION_RECTS(pRgn);
2328 rects[i].x = pBox->x1 - pBackingStore->x;
2329 rects[i].y = pBox->y1 - pBackingStore->y;
2330 rects[i].width = pBox->x2 - pBox->x1;
2331 rects[i].height = pBox->y2 - pBox->y1;
2333 (* pGC->ops->PolyFillRect) (
2334 (DrawablePtr)pBackingStore->pBackingPixmap,
2335 pGC, numRects, rects);
2336 DEALLOCATE_LOCAL(rects);
2342 if (!generateExposures)
2344 REGION_DESTROY(pScreen, pRgn);
2350 * result must be screen relative, but is currently
2351 * drawable relative.
2353 REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x,
2359 REGION_DESTROY( pScreen, pRgn);
2366 miBSClearBackingRegion (pWin, pRgn)
2373 i = REGION_NUM_RECTS(pRgn);
2374 pBox = REGION_RECTS(pRgn);
2377 (void) miBSClearBackingStore(pWin, pBox->x1, pBox->y1,
2378 pBox->x2 - pBox->x1,
2379 pBox->y2 - pBox->y1,
2386 * fill a region of the destination with virtual bits
2388 * pRgn is to be translated by (x,y)
2392 miBSFillVirtualBits (pDrawable, pGC, pRgn, x, y, state, pixunion, planeMask)
2393 DrawablePtr pDrawable;
2399 unsigned long planeMask;
2411 numRects = REGION_NUM_RECTS(pRgn);
2412 pRect = (xRectangle *)ALLOCATE_LOCAL(numRects * sizeof(xRectangle));
2416 if (pDrawable->type != DRAWABLE_PIXMAP)
2418 pWin = (WindowPtr) pDrawable;
2419 if (!pWin->backStorage)
2424 gcval[i++] = (pointer)planeMask;
2425 gcmask |= GCPlaneMask;
2426 if (state == BackgroundPixel)
2428 if (pGC->fgPixel != pixunion.pixel)
2430 gcval[i++] = (pointer)pixunion.pixel;
2431 gcmask |= GCForeground;
2433 if (pGC->fillStyle != FillSolid)
2435 gcval[i++] = (pointer)FillSolid;
2436 gcmask |= GCFillStyle;
2441 if (pGC->fillStyle != FillTiled)
2443 gcval[i++] = (pointer)FillTiled;
2444 gcmask |= GCFillStyle;
2446 if (pGC->tileIsPixel || pGC->tile.pixmap != pixunion.pixmap)
2448 gcval[i++] = (pointer)pixunion.pixmap;
2451 if (pGC->patOrg.x != x)
2453 gcval[i++] = (pointer)x;
2454 gcmask |= GCTileStipXOrigin;
2456 if (pGC->patOrg.y != y)
2458 gcval[i++] = (pointer)y;
2459 gcmask |= GCTileStipYOrigin;
2463 DoChangeGC (pGC, gcmask, (XID *)gcval, 1);
2466 (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
2468 if (pDrawable->serialNumber != pGC->serialNumber)
2469 ValidateGC (pDrawable, pGC);
2471 pBox = REGION_RECTS(pRgn);
2472 for (i = numRects; --i >= 0; pBox++, pRect++)
2474 pRect->x = pBox->x1 + x;
2475 pRect->y = pBox->y1 + y;
2476 pRect->width = pBox->x2 - pBox->x1;
2477 pRect->height = pBox->y2 - pBox->y1;
2480 (*pGC->ops->PolyFillRect) (pDrawable, pGC, numRects, pRect);
2482 (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
2483 DEALLOCATE_LOCAL (pRect);
2487 *-----------------------------------------------------------------------
2489 * Create and install backing store info for a window
2491 *-----------------------------------------------------------------------
2498 register miBSWindowPtr pBackingStore;
2499 register ScreenPtr pScreen;
2501 if (pWin->drawable.pScreen->backingStoreSupport == NotUseful)
2503 pScreen = pWin->drawable.pScreen;
2504 if (!(pBackingStore = (miBSWindowPtr)pWin->backStorage))
2507 pBackingStore = (miBSWindowPtr)xalloc(sizeof(miBSWindowRec));
2511 pBackingStore->pBackingPixmap = NullPixmap;
2512 pBackingStore->x = 0;
2513 pBackingStore->y = 0;
2514 REGION_INIT( pScreen, &pBackingStore->SavedRegion, NullBox, 1);
2515 pBackingStore->viewable = (char)pWin->viewable;
2516 pBackingStore->status = StatusNoPixmap;
2517 pBackingStore->backgroundState = None;
2518 pWin->backStorage = (pointer) pBackingStore;
2522 * Now want to initialize the backing pixmap and SavedRegion if
2523 * necessary. The initialization consists of finding all the
2524 * currently-obscured regions, by taking the inverse of the window's
2525 * clip list, storing the result in SavedRegion, and exposing those
2526 * areas of the window.
2529 if (pBackingStore->status == StatusNoPixmap &&
2530 ((pWin->backingStore == WhenMapped && pWin->viewable) ||
2531 (pWin->backingStore == Always)))
2534 RegionPtr pSavedRegion;
2536 pSavedRegion = &pBackingStore->SavedRegion;
2538 box.x1 = pWin->drawable.x;
2539 box.x2 = box.x1 + (int) pWin->drawable.width;
2540 box.y1 = pWin->drawable.y;
2541 box.y2 = pWin->drawable.y + (int) pWin->drawable.height;
2543 REGION_INVERSE( pScreen, pSavedRegion, &pWin->clipList, &box);
2544 REGION_TRANSLATE( pScreen, pSavedRegion,
2548 if (wBoundingShape (pWin))
2549 REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion,
2550 wBoundingShape (pWin));
2551 if (wClipShape (pWin))
2552 REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion,
2555 /* if window is already on-screen, assume it has been drawn to */
2557 pBackingStore->status = StatusVDirty;
2558 miTileVirtualBS (pWin);
2561 * deliver all the newly available regions
2562 * as exposure events to the window
2565 miSendExposures(pWin, pSavedRegion, 0, 0);
2567 else if (!pWin->viewable)
2570 * Turn off backing store when we're not supposed to
2571 * be saving anything
2573 if (pBackingStore->status != StatusNoPixmap)
2575 REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
2576 miDestroyBSPixmap (pWin);
2582 *-----------------------------------------------------------------------
2584 * Destroy and free all the stuff associated with the backing-store
2585 * for the given window.
2591 * The backing pixmap and all the regions and GC's are destroyed.
2593 *-----------------------------------------------------------------------
2599 miBSWindowPtr pBackingStore;
2600 register ScreenPtr pScreen = pWin->drawable.pScreen;
2602 pBackingStore = (miBSWindowPtr)pWin->backStorage;
2605 miDestroyBSPixmap (pWin);
2607 REGION_UNINIT( pScreen, &pBackingStore->SavedRegion);
2609 xfree(pBackingStore);
2610 pWin->backStorage = NULL;
2615 *-----------------------------------------------------------------------
2616 * miResizeBackingStore --
2617 * Alter the size of the backing pixmap as necessary when the
2618 * SavedRegion changes size. The contents of the old pixmap are
2619 * copied/shifted into the new/same pixmap.
2622 * The new Pixmap is created as necessary.
2625 * The old pixmap is destroyed.
2627 *-----------------------------------------------------------------------
2630 miResizeBackingStore(pWin, dx, dy, saveBits)
2632 int dx, dy; /* bits are moving this far */
2633 Bool saveBits; /* bits are useful */
2635 miBSWindowPtr pBackingStore;
2636 PixmapPtr pBackingPixmap;
2640 PixmapPtr pNewPixmap;
2644 pBackingStore = (miBSWindowPtr)(pWin->backStorage);
2645 pBackingPixmap = pBackingStore->pBackingPixmap;
2646 if (!pBackingPixmap)
2648 pScreen = pWin->drawable.pScreen;
2649 extents = REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion);
2650 pNewPixmap = pBackingPixmap;
2652 nw = extents->x2 - extents->x1;
2653 nh = extents->y2 - extents->y1;
2655 /* the policy here could be more sophisticated */
2656 if (nw != pBackingPixmap->drawable.width ||
2657 nh != pBackingPixmap->drawable.height)
2661 pNewPixmap = NullPixmap;
2662 pBackingStore->status = StatusNoPixmap;
2666 pNewPixmap = (PixmapPtr)(*pScreen->CreatePixmap)
2669 pWin->drawable.depth);
2673 pBackingStore->status = StatusNoPixmap;
2675 pBackingStore->status = StatusBadAlloc;
2682 pBackingStore->x = 0;
2683 pBackingStore->y = 0;
2687 nx = pBackingStore->x - extents->x1 + dx;
2688 ny = pBackingStore->y - extents->y1 + dy;
2689 pBackingStore->x = extents->x1;
2690 pBackingStore->y = extents->y1;
2692 if (saveBits && (pNewPixmap != pBackingPixmap || nx != 0 || ny != 0))
2694 pGC = GetScratchGC(pNewPixmap->drawable.depth, pScreen);
2697 ValidateGC((DrawablePtr)pNewPixmap, pGC);
2698 /* if we implement a policy where the pixmap can be larger than
2699 * the region extents, we might want to optimize this copyarea
2700 * by only copying the old extents, rather than the entire
2703 (*pGC->ops->CopyArea)((DrawablePtr)pBackingPixmap,
2704 (DrawablePtr)pNewPixmap, pGC,
2706 pBackingPixmap->drawable.width,
2707 pBackingPixmap->drawable.height,
2713 /* SavedRegion is used in the backingGC clip; force an update */
2714 pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
2715 if (pNewPixmap != pBackingPixmap)
2717 (* pScreen->DestroyPixmap)(pBackingPixmap);
2718 pBackingStore->pBackingPixmap = pNewPixmap;
2723 *-----------------------------------------------------------------------
2724 * miBSSaveDoomedAreas --
2725 * Saved the areas of the given window that are about to be
2726 * obscured. If the window has moved, pObscured is expected to
2727 * be at the new screen location and (dx,dy) is expected to be the offset
2728 * to the window's previous location.
2734 * The region is copied from the screen into pBackingPixmap and
2735 * SavedRegion is updated.
2737 *-----------------------------------------------------------------------
2740 miBSSaveDoomedAreas(pWin, pObscured, dx, dy)
2741 register WindowPtr pWin;
2742 RegionPtr pObscured;
2745 miBSWindowPtr pBackingStore;
2749 pBackingStore = (miBSWindowPtr)pWin->backStorage;
2750 pScreen = pWin->drawable.pScreen;
2753 * If the window isn't realized, it's being unmapped, thus we don't
2754 * want to save anything if backingStore isn't Always.
2756 if (!pWin->realized)
2758 pBackingStore->viewable = (char)pWin->viewable;
2759 if (pWin->backingStore != Always)
2761 REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
2762 miDestroyBSPixmap (pWin);
2765 if (pBackingStore->status == StatusBadAlloc)
2766 pBackingStore->status = StatusNoPixmap;
2769 /* Don't even pretend to save anything for a virtual background None */
2770 if ((pBackingStore->status == StatusVirtual) &&
2771 (pBackingStore->backgroundState == None))
2774 if (REGION_NOTEMPTY(pScreen, pObscured))
2777 x = pWin->drawable.x;
2778 y = pWin->drawable.y;
2779 REGION_TRANSLATE(pScreen, pObscured, -x, -y);
2780 oldExtents = *REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion);
2781 REGION_UNION( pScreen, &pBackingStore->SavedRegion,
2782 &pBackingStore->SavedRegion,
2785 * only save the bits if we've actually
2786 * started using backing store
2788 if (pBackingStore->status != StatusVirtual)
2790 miBSScreenPtr pScreenPriv;
2792 pScreenPriv = (miBSScreenPtr) pScreen->devPrivates[miBSScreenIndex].ptr;
2793 if (!pBackingStore->pBackingPixmap)
2794 miCreateBSPixmap (pWin, &oldExtents);
2796 miResizeBackingStore(pWin, 0, 0, TRUE);
2798 if (pBackingStore->pBackingPixmap) {
2799 if (pBackingStore->x | pBackingStore->y)
2801 REGION_TRANSLATE( pScreen, pObscured,
2804 x += pBackingStore->x;
2805 y += pBackingStore->y;
2807 (* pScreenPriv->funcs->SaveAreas) (pBackingStore->pBackingPixmap,
2808 pObscured, x - dx, y - dy, pWin);
2811 REGION_TRANSLATE(pScreen, pObscured, x, y);
2816 *-----------------------------------------------------------------------
2817 * miBSRestoreAreas --
2818 * Restore areas from backing-store that are no longer obscured.
2819 * expects prgnExposed to contain a screen-relative area.
2822 * The region to generate exposure events on (which may be
2823 * different from the region to paint).
2826 * Areas are copied from pBackingPixmap to the screen. prgnExposed
2827 * is altered to contain the region that could not be restored from
2831 * This is called before sending any exposure events to the client,
2832 * and so might be called if the window has grown. Changing the backing
2833 * pixmap doesn't require revalidating the backingGC because the
2834 * client's next output request will result in a call to ValidateGC,
2835 * since the window clip region has changed, which will in turn call
2836 * miValidateBackingStore.
2837 *-----------------------------------------------------------------------
2840 miBSRestoreAreas(pWin, prgnExposed)
2841 register WindowPtr pWin;
2842 RegionPtr prgnExposed;
2844 PixmapPtr pBackingPixmap;
2845 miBSWindowPtr pBackingStore;
2846 RegionPtr prgnSaved;
2847 RegionPtr prgnRestored;
2848 register ScreenPtr pScreen;
2849 RegionPtr exposures = prgnExposed;
2851 pScreen = pWin->drawable.pScreen;
2852 pBackingStore = (miBSWindowPtr)pWin->backStorage;
2853 pBackingPixmap = pBackingStore->pBackingPixmap;
2855 prgnSaved = &pBackingStore->SavedRegion;
2857 if (pBackingStore->status == StatusContents)
2859 REGION_TRANSLATE(pScreen, prgnSaved, pWin->drawable.x,
2862 prgnRestored = REGION_CREATE( pScreen, (BoxPtr)NULL, 1);
2863 REGION_INTERSECT( pScreen, prgnRestored, prgnExposed, prgnSaved);
2866 * Since prgnExposed is no longer obscured, we no longer
2867 * will have a valid copy of it in backing-store, but there is a valid
2868 * copy of it on screen, so subtract the area we just restored from
2869 * from the area to be exposed.
2872 if (REGION_NOTEMPTY( pScreen, prgnRestored))
2874 miBSScreenPtr pScreenPriv;
2876 REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed);
2877 REGION_SUBTRACT( pScreen, prgnExposed, prgnExposed, prgnRestored);
2880 * Do the actual restoration
2883 pScreenPriv = (miBSScreenPtr)
2884 pScreen->devPrivates[miBSScreenIndex].ptr;
2885 (* pScreenPriv->funcs->RestoreAreas) (pBackingPixmap,
2887 pWin->drawable.x + pBackingStore->x,
2888 pWin->drawable.y + pBackingStore->y, pWin);
2890 * if the saved region is completely empty, dispose of the
2891 * backing pixmap, otherwise, retranslate the saved
2892 * region to window relative
2895 if (REGION_NOTEMPTY(pScreen, prgnSaved))
2897 REGION_TRANSLATE(pScreen, prgnSaved,
2900 miResizeBackingStore(pWin, 0, 0, TRUE);
2903 miDestroyBSPixmap (pWin);
2906 REGION_TRANSLATE(pScreen, prgnSaved,
2907 -pWin->drawable.x, -pWin->drawable.y);
2908 REGION_DESTROY( pScreen, prgnRestored);
2911 else if ((pBackingStore->status == StatusVirtual) ||
2912 (pBackingStore->status == StatusVDirty))
2914 REGION_TRANSLATE(pScreen, prgnSaved,
2915 pWin->drawable.x, pWin->drawable.y);
2916 exposures = REGION_CREATE( pScreen, NullBox, 1);
2917 if (SameBackground (pBackingStore->backgroundState,
2918 pBackingStore->background,
2919 pWin->backgroundState,
2922 REGION_SUBTRACT( pScreen, exposures, prgnExposed, prgnSaved);
2926 miTileVirtualBS(pWin);
2928 /* we need to expose all we have (virtually) retiled */
2929 REGION_UNION( pScreen, exposures, prgnExposed, prgnSaved);
2931 REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed);
2932 REGION_TRANSLATE(pScreen, prgnSaved,
2933 -pWin->drawable.x, -pWin->drawable.y);
2935 else if (pWin->viewable && !pBackingStore->viewable &&
2936 pWin->backingStore != Always)
2939 * The window was just mapped and nothing has been saved in
2940 * backing-store from the last time it was mapped. We want to capture
2941 * any output to regions that are already obscured but there are no
2942 * bits to snag off the screen, so we initialize things just as we did
2943 * in miBSAllocate, above.
2947 prgnSaved = &pBackingStore->SavedRegion;
2949 box.x1 = pWin->drawable.x;
2950 box.x2 = box.x1 + (int) pWin->drawable.width;
2951 box.y1 = pWin->drawable.y;
2952 box.y2 = box.y1 + (int) pWin->drawable.height;
2954 REGION_INVERSE( pScreen, prgnSaved, &pWin->clipList, &box);
2955 REGION_TRANSLATE( pScreen, prgnSaved,
2959 if (wBoundingShape (pWin))
2960 REGION_INTERSECT(pScreen, prgnSaved, prgnSaved,
2961 wBoundingShape (pWin));
2962 if (wClipShape (pWin))
2963 REGION_INTERSECT(pScreen, prgnSaved, prgnSaved,
2966 miTileVirtualBS(pWin);
2968 exposures = REGION_CREATE( pScreen, &box, 1);
2970 pBackingStore->viewable = (char)pWin->viewable;
2976 *-----------------------------------------------------------------------
2977 * miBSTranslateBackingStore --
2978 * Shift the backing-store in the given direction. Called when bit
2979 * gravity is shifting things around.
2982 * An occluded region of the window which should be sent exposure events.
2983 * This region should be in absolute coordinates (i.e. include
2984 * new window position).
2987 * If the window changed size as well as position, the backing pixmap
2988 * is resized. The contents of the backing pixmap are shifted
2991 * Bob and I have rewritten this routine quite a few times, each
2992 * time it gets a few more cases correct, and introducing some
2993 * interesting bugs. Naturally, I think the code is correct this
2996 * Let me try to explain what this routine is for:
2998 * It's called from SlideAndSizeWindow whenever a window
2999 * with backing store is resized. There are two separate
3002 * a) The window has ForgetGravity
3004 * In this case, windx, windy will be 0 and oldClip will
3005 * be NULL. This indicates that all of the window contents
3006 * currently saved offscreen should be discarded, and the
3007 * entire window exposed. TranslateBackingStore, then, should
3008 * prepare a completely new backing store region based on the
3009 * new window clipList and return that region for exposure.
3011 * b) The window has some other gravity
3013 * In this case, windx, windy will be set to the distance
3014 * that the bits should move within the window. oldClip
3015 * will be set to the old visible portion of the window.
3016 * TranslateBackingStore, then, should adjust the backing
3017 * store to accommodate the portion of the existing backing
3018 * store bits which coorespond to backing store bits which
3019 * will still be occluded in the new configuration. oldx,oldy
3020 * are set to the old position of the window on the screen.
3022 * Furthermore, in this case any contents of the screen which
3023 * are about to become occluded should be fetched from the screen
3024 * and placed in backing store. This is to avoid the eventual
3025 * occlusion by the win gravity shifting the child window bits around
3026 * on top of this window, and potentially losing information
3028 * It's also called from SetShape, but I think (he says not
3029 * really knowing for sure) that this code will even work
3031 *-----------------------------------------------------------------------
3035 miBSTranslateBackingStore(pWin, windx, windy, oldClip, oldx, oldy)
3037 int windx; /* bit translation distance in window */
3039 RegionPtr oldClip; /* Region being copied */
3040 int oldx; /* old window position */
3043 register miBSWindowPtr pBackingStore;
3044 register RegionPtr pSavedRegion;
3045 register RegionPtr newSaved, doomed;
3046 register ScreenPtr pScreen;
3048 int scrdx; /* bit translation distance on screen */
3050 int dx; /* distance window moved on screen */
3053 pScreen = pWin->drawable.pScreen;
3054 pBackingStore = (miBSWindowPtr)(pWin->backStorage);
3055 if ((pBackingStore->status == StatusNoPixmap) ||
3056 (pBackingStore->status == StatusBadAlloc))
3060 * Compute the new saved region
3063 newSaved = REGION_CREATE( pScreen, NullBox, 1);
3064 extents.x1 = pWin->drawable.x;
3065 extents.x2 = pWin->drawable.x + (int) pWin->drawable.width;
3066 extents.y1 = pWin->drawable.y;
3067 extents.y2 = pWin->drawable.y + (int) pWin->drawable.height;
3068 REGION_INVERSE( pScreen, newSaved, &pWin->clipList, &extents);
3070 REGION_TRANSLATE( pScreen, newSaved,
3071 -pWin->drawable.x, -pWin->drawable.y);
3073 if (wBoundingShape (pWin) || wClipShape (pWin)) {
3074 if (wBoundingShape (pWin))
3075 REGION_INTERSECT( pScreen, newSaved, newSaved,
3076 wBoundingShape (pWin));
3077 if (wClipShape (pWin))
3078 REGION_INTERSECT( pScreen, newSaved, newSaved, wClipShape (pWin));
3082 pSavedRegion = &pBackingStore->SavedRegion;
3084 /* now find any visible areas we can save from the screen */
3085 /* and then translate newSaved to old local coordinates */
3088 /* bit gravity makes things virtually too hard, punt */
3089 if (((windx != 0) || (windy != 0)) &&
3090 (pBackingStore->status != StatusContents))
3091 miCreateBSPixmap(pWin, NullBox);
3094 * The window is moving this far on the screen
3096 dx = pWin->drawable.x - oldx;
3097 dy = pWin->drawable.y - oldy;
3099 * The bits will be moving on the screen by the
3100 * amount the window is moving + the amount the
3101 * bits are moving within the window
3107 * intersect at old bit position to discover the
3108 * bits on the screen which can be put into the
3111 REGION_TRANSLATE( pScreen, oldClip, windx - oldx, windy - oldy);
3112 doomed = REGION_CREATE( pScreen, NullBox, 1);
3113 REGION_INTERSECT( pScreen, doomed, oldClip, newSaved);
3114 REGION_TRANSLATE( pScreen, oldClip, oldx - windx, oldy - windy);
3117 * Translate the old saved region to the position in the
3118 * window where it will appear to be
3120 REGION_TRANSLATE( pScreen, pSavedRegion, windx, windy);
3123 * Add the old saved region to the new saved region, so
3124 * that calls to RestoreAreas will be able to fetch those
3127 REGION_UNION( pScreen, newSaved, newSaved, pSavedRegion);
3130 * Swap the new saved region into the window
3135 tmp = *pSavedRegion;
3136 *pSavedRegion = *newSaved;
3139 miResizeBackingStore (pWin, windx, windy, TRUE);
3142 * Compute the newly enabled region
3143 * of backing store. This region will be
3144 * set to background in the backing pixmap and
3145 * sent as exposure events to the client.
3147 REGION_SUBTRACT( pScreen, newSaved, pSavedRegion, newSaved);
3150 * Fetch bits which will be obscured from
3153 if (REGION_NOTEMPTY( pScreen, doomed))
3156 * Don't clear regions which have bits on the
3159 REGION_SUBTRACT( pScreen, newSaved, newSaved, doomed);
3162 * Make the region to SaveDoomedAreas absolute, instead
3163 * of window relative.
3165 REGION_TRANSLATE( pScreen, doomed,
3166 pWin->drawable.x, pWin->drawable.y);
3167 (* pScreen->SaveDoomedAreas) (pWin, doomed, scrdx, scrdy);
3170 REGION_DESTROY(pScreen, doomed);
3173 * and clear whatever there is that's new
3175 if (REGION_NOTEMPTY( pScreen, newSaved))
3177 miBSClearBackingRegion (pWin, newSaved);
3179 * Make the exposed region absolute
3181 REGION_TRANSLATE(pScreen, newSaved,
3187 REGION_DESTROY(pScreen, newSaved);
3188 newSaved = NullRegion;
3194 * ForgetGravity: just reset backing store and
3195 * expose the whole mess
3197 REGION_COPY( pScreen, pSavedRegion, newSaved);
3198 REGION_TRANSLATE( pScreen, newSaved,
3199 pWin->drawable.x, pWin->drawable.y);
3201 miResizeBackingStore (pWin, 0, 0, FALSE);
3202 (void) miBSClearBackingStore (pWin, 0, 0, 0, 0, FALSE);
3209 * Inform the backing store layer that you are about to validate
3210 * a gc with a window, and that subsequent output to the window
3211 * is (or is not) guaranteed to be already clipped to the visible
3212 * regions of the window.
3216 miBSDrawGuarantee (pWin, pGC, guarantee)
3223 if (pWin->backStorage)
3225 pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
3227 (void) miBSCreateGCPrivate (pGC);
3228 pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
3234 * when the GC is Cheap pPriv will point
3235 * at some device's gc func structure. guarantee
3236 * will point at the ChangeGC entry of that struct
3237 * and will never match a valid guarantee value.
3239 switch (pPriv->guarantee)
3241 case GuaranteeNothing:
3242 case GuaranteeVisBack:
3243 pPriv->guarantee = guarantee;
3250 #define noBackingCopy (GCGraphicsExposures|GCClipXOrigin|GCClipYOrigin| \
3251 GCClipMask|GCSubwindowMode| \
3252 GCTileStipXOrigin|GCTileStipYOrigin)
3255 *-----------------------------------------------------------------------
3257 * Wrapper around output-library's ValidateGC routine
3265 * The idea here is to perform several functions:
3266 * - All the output calls must be intercepted and routed to
3267 * backing-store as necessary.
3268 * - pGC in the window's devBackingStore must be set up with the
3269 * clip list appropriate for writing to pBackingPixmap (i.e.
3270 * the inverse of the window's clipList intersected with the
3271 * clientClip of the GC). Since the destination for this GC is
3272 * a pixmap, it is sufficient to set the clip list as its
3274 *-----------------------------------------------------------------------
3278 miBSValidateGC (pGC, stateChanges, pDrawable)
3280 unsigned long stateChanges;
3281 DrawablePtr pDrawable;
3284 miBSWindowPtr pWindowPriv;
3288 RegionPtr backingCompositeClip = NULL;
3290 if (pDrawable->type != DRAWABLE_PIXMAP)
3292 pWin = (WindowPtr) pDrawable;
3293 pWindowPriv = (miBSWindowPtr) pWin->backStorage;
3294 lift_functions = (pWindowPriv == (miBSWindowPtr) NULL);
3298 pWin = (WindowPtr) NULL;
3299 lift_functions = TRUE;
3302 pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
3304 FUNC_PROLOGUE (pGC, pPriv);
3306 (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
3309 * rewrap funcs and ops as Validate may have changed them
3312 pPriv->wrapFuncs = pGC->funcs;
3313 pPriv->wrapOps = pGC->ops;
3315 if (!lift_functions && ((pPriv->guarantee == GuaranteeVisBack) ||
3316 (pWindowPriv->status == StatusNoPixmap) ||
3317 (pWindowPriv->status == StatusBadAlloc)))
3318 lift_functions = TRUE;
3321 * check to see if a new backingCompositeClip region must
3325 if (!lift_functions &&
3326 ((pDrawable->serialNumber != pPriv->serialNumber) ||
3327 (stateChanges&(GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode))))
3329 if (REGION_NOTEMPTY(pGC->pScreen, &pWindowPriv->SavedRegion))
3331 backingCompositeClip = REGION_CREATE(pGC->pScreen, NULL, 1);
3332 if ((pGC->clientClipType == CT_NONE) ||
3333 (pGC->clientClipType == CT_PIXMAP))
3335 REGION_COPY(pGC->pScreen, backingCompositeClip,
3336 &pWindowPriv->SavedRegion);
3341 * Make a new copy of the client clip, translated to
3342 * its proper origin.
3345 REGION_COPY(pGC->pScreen, backingCompositeClip,
3347 REGION_TRANSLATE(pGC->pScreen, backingCompositeClip,
3350 REGION_INTERSECT(pGC->pScreen, backingCompositeClip,
3351 backingCompositeClip,
3352 &pWindowPriv->SavedRegion);
3354 if (pGC->subWindowMode == IncludeInferiors)
3356 RegionPtr translatedClip;
3359 * any output in IncludeInferiors mode will not
3360 * be redirected to Inferiors backing store. This
3361 * can be fixed only at great cost to the shadow routines.
3363 translatedClip = NotClippedByChildren (pWin);
3364 REGION_TRANSLATE(pGC->pScreen, translatedClip,
3367 REGION_SUBTRACT(pGC->pScreen, backingCompositeClip,
3368 backingCompositeClip, translatedClip);
3369 REGION_DESTROY(pGC->pScreen, translatedClip);
3371 if (!REGION_NOTEMPTY(pGC->pScreen, backingCompositeClip))
3372 lift_functions = TRUE;
3376 lift_functions = TRUE;
3379 /* Reset the status when drawing to an unoccluded window so that
3380 * future SaveAreas will actually copy bits from the screen. Note that
3381 * output to root window in IncludeInferiors mode will not cause this
3382 * to change. This causes all transient graphics by the window
3383 * manager to the root window to not enable backing store.
3385 if (lift_functions && (pWindowPriv->status == StatusVirtual) &&
3386 (pWin->parent || pGC->subWindowMode != IncludeInferiors))
3387 pWindowPriv->status = StatusVDirty;
3391 * if no backing store has been allocated, and it's needed,
3395 if (!lift_functions && !pWindowPriv->pBackingPixmap)
3397 miCreateBSPixmap (pWin, NullBox);
3398 if (!pWindowPriv->pBackingPixmap)
3399 lift_functions = TRUE;
3403 * create the backing GC if needed, lift functions
3404 * if the creation fails
3407 if (!lift_functions && !pPriv->pBackingGC)
3410 XID noexpose = xFalse;
3412 /* We never want ops with the backingGC to generate GraphicsExpose */
3413 pBackingGC = CreateGC ((DrawablePtr)pWindowPriv->pBackingPixmap,
3414 GCGraphicsExposures, &noexpose, &status);
3415 if (status != Success)
3416 lift_functions = TRUE;
3418 pPriv->pBackingGC = pBackingGC;
3421 pBackingGC = pPriv->pBackingGC;
3423 pPriv->stateChanges |= stateChanges;
3427 if (backingCompositeClip)
3428 REGION_DESTROY( pGC->pScreen, backingCompositeClip);
3430 /* unwrap the GC again */
3431 miBSDestroyGCPrivate (pGC);
3437 * the rest of this function gets the pBackingGC
3438 * into shape for possible draws
3441 pPriv->stateChanges &= ~noBackingCopy;
3442 if (pPriv->stateChanges)
3443 CopyGC(pGC, pBackingGC, pPriv->stateChanges);
3444 if ((pGC->patOrg.x - pWindowPriv->x) != pBackingGC->patOrg.x ||
3445 (pGC->patOrg.y - pWindowPriv->y) != pBackingGC->patOrg.y)
3448 vals[0] = pGC->patOrg.x - pWindowPriv->x;
3449 vals[1] = pGC->patOrg.y - pWindowPriv->y;
3450 DoChangeGC(pBackingGC, GCTileStipXOrigin|GCTileStipYOrigin, vals, 0);
3452 pPriv->stateChanges = 0;
3454 if (backingCompositeClip)
3458 if (pGC->clientClipType == CT_PIXMAP)
3460 miBSScreenPtr pScreenPriv;
3462 (*pBackingGC->funcs->CopyClip)(pBackingGC, pGC);
3463 REGION_TRANSLATE(pGC->pScreen, backingCompositeClip,
3464 -pGC->clipOrg.x, -pGC->clipOrg.y);
3465 vals[0] = pGC->clipOrg.x - pWindowPriv->x;
3466 vals[1] = pGC->clipOrg.y - pWindowPriv->y;
3467 DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
3468 pScreenPriv = (miBSScreenPtr)
3469 pGC->pScreen->devPrivates[miBSScreenIndex].ptr;
3470 (* pScreenPriv->funcs->SetClipmaskRgn)
3471 (pBackingGC, backingCompositeClip);
3472 REGION_DESTROY( pGC->pScreen, backingCompositeClip);
3476 vals[0] = -pWindowPriv->x;
3477 vals[1] = -pWindowPriv->y;
3478 DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
3479 (*pBackingGC->funcs->ChangeClip) (pBackingGC, CT_REGION, backingCompositeClip, 0);
3481 pPriv->serialNumber = pDrawable->serialNumber;
3484 if (pWindowPriv->pBackingPixmap->drawable.serialNumber
3485 != pBackingGC->serialNumber)
3487 ValidateGC((DrawablePtr)pWindowPriv->pBackingPixmap, pBackingGC);
3490 if (pBackingGC->clientClip == 0)
3491 ErrorF ("backing store clip list nil");
3493 FUNC_EPILOGUE (pGC, pPriv);
3497 miBSChangeGC (pGC, mask)
3501 miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
3503 FUNC_PROLOGUE (pGC, pPriv);
3505 (*pGC->funcs->ChangeGC) (pGC, mask);
3507 FUNC_EPILOGUE (pGC, pPriv);
3511 miBSCopyGC (pGCSrc, mask, pGCDst)
3512 GCPtr pGCSrc, pGCDst;
3515 miBSGCPtr pPriv = (miBSGCPtr) (pGCDst)->devPrivates[miBSGCIndex].ptr;
3517 FUNC_PROLOGUE (pGCDst, pPriv);
3519 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
3521 FUNC_EPILOGUE (pGCDst, pPriv);
3528 miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
3530 FUNC_PROLOGUE (pGC, pPriv);
3532 if (pPriv->pBackingGC)
3533 FreeGC(pPriv->pBackingGC, (GContext)0);
3535 (*pGC->funcs->DestroyGC) (pGC);
3537 FUNC_EPILOGUE (pGC, pPriv);
3543 miBSChangeClip(pGC, type, pvalue, nrects)
3549 miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
3551 FUNC_PROLOGUE (pGC, pPriv);
3553 (* pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
3555 FUNC_EPILOGUE (pGC, pPriv);
3559 miBSCopyClip(pgcDst, pgcSrc)
3560 GCPtr pgcDst, pgcSrc;
3562 miBSGCPtr pPriv = (miBSGCPtr) (pgcDst)->devPrivates[miBSGCIndex].ptr;
3564 FUNC_PROLOGUE (pgcDst, pPriv);
3566 (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
3568 FUNC_EPILOGUE (pgcDst, pPriv);
3572 miBSDestroyClip(pGC)
3575 miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
3577 FUNC_PROLOGUE (pGC, pPriv);
3579 (* pGC->funcs->DestroyClip)(pGC);
3581 FUNC_EPILOGUE (pGC, pPriv);
3585 miDestroyBSPixmap (pWin)
3588 miBSWindowPtr pBackingStore;
3591 pScreen = pWin->drawable.pScreen;
3592 pBackingStore = (miBSWindowPtr) pWin->backStorage;
3593 if (pBackingStore->pBackingPixmap)
3594 (* pScreen->DestroyPixmap)(pBackingStore->pBackingPixmap);
3595 pBackingStore->pBackingPixmap = NullPixmap;
3596 pBackingStore->x = 0;
3597 pBackingStore->y = 0;
3598 if (pBackingStore->backgroundState == BackgroundPixmap)
3599 (* pScreen->DestroyPixmap)(pBackingStore->background.pixmap);
3600 pBackingStore->backgroundState = None;
3601 pBackingStore->status = StatusNoPixmap;
3602 pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
3606 miTileVirtualBS (pWin)
3609 miBSWindowPtr pBackingStore;
3611 pBackingStore = (miBSWindowPtr) pWin->backStorage;
3612 if (pBackingStore->backgroundState == BackgroundPixmap)
3613 (* pWin->drawable.pScreen->DestroyPixmap)
3614 (pBackingStore->background.pixmap);
3615 pBackingStore->backgroundState = pWin->backgroundState;
3616 pBackingStore->background = pWin->background;
3617 if (pBackingStore->backgroundState == BackgroundPixmap)
3618 pBackingStore->background.pixmap->refcnt++;
3620 if (pBackingStore->status != StatusVDirty)
3621 pBackingStore->status = StatusVirtual;
3624 * punt parent relative tiles and do it now
3626 if (pBackingStore->backgroundState == ParentRelative)
3627 miCreateBSPixmap (pWin, NullBox);
3631 static int BSAllocationsFailed = 0;
3632 #define FAILEDSIZE 32
3633 static struct { int w, h; } failedRecord[FAILEDSIZE];
3634 static int failedIndex;
3638 miCreateBSPixmap (pWin, pExtents)
3642 miBSWindowPtr pBackingStore;
3644 PixUnion background;
3645 char backgroundState;
3649 pScreen = pWin->drawable.pScreen;
3650 pBackingStore = (miBSWindowPtr) pWin->backStorage;
3651 if (pBackingStore->status == StatusBadAlloc)
3653 backSet = ((pBackingStore->status == StatusVirtual) ||
3654 (pBackingStore->status == StatusVDirty));
3656 extents = REGION_EXTENTS( pScreen, &pBackingStore->SavedRegion);
3658 if (!pBackingStore->pBackingPixmap)
3660 /* the policy here could be more sophisticated */
3661 pBackingStore->x = extents->x1;
3662 pBackingStore->y = extents->y1;
3663 pBackingStore->pBackingPixmap =
3664 (PixmapPtr)(* pScreen->CreatePixmap)
3666 extents->x2 - extents->x1,
3667 extents->y2 - extents->y1,
3668 pWin->drawable.depth);
3670 if (!pBackingStore->pBackingPixmap)
3673 BSAllocationsFailed++;
3675 * record failed allocations
3677 failedRecord[failedIndex].w = pWin->drawable.width;
3678 failedRecord[failedIndex].h = pWin->drawable.height;
3680 if (failedIndex == FAILEDSIZE)
3684 pBackingStore->status = StatusNoPixmap;
3686 pBackingStore->status = StatusBadAlloc;
3691 pBackingStore->status = StatusContents;
3695 backgroundState = pWin->backgroundState;
3696 background = pWin->background;
3698 pWin->backgroundState = pBackingStore->backgroundState;
3699 pWin->background = pBackingStore->background;
3700 if (pWin->backgroundState == BackgroundPixmap)
3701 pWin->background.pixmap->refcnt++;
3707 if (pExtents->y1 != pExtents->y2)
3711 exposed = miBSClearBackingStore(pWin,
3712 pExtents->x1, pExtents->y1,
3713 pExtents->x2 - pExtents->x1,
3714 pExtents->y2 - pExtents->y1,
3718 miSendExposures(pWin, exposed, pWin->drawable.x, pWin->drawable.y);
3719 REGION_DESTROY( pScreen, exposed);
3725 if (pWin->backgroundState == BackgroundPixmap)
3726 (* pScreen->DestroyPixmap) (pWin->background.pixmap);
3727 pWin->backgroundState = backgroundState;
3728 pWin->background = background;
3729 if (pBackingStore->backgroundState == BackgroundPixmap)
3730 (* pScreen->DestroyPixmap) (pBackingStore->background.pixmap);
3731 pBackingStore->backgroundState = None;
3736 *-----------------------------------------------------------------------
3738 * Handle the restoration of areas exposed by graphics operations.
3744 * prgnExposed has the areas exposed from backing-store removed
3747 *-----------------------------------------------------------------------
3750 miBSExposeCopy (pSrc, pDst, pGC, prgnExposed, srcx, srcy, dstx, dsty, plane)
3754 RegionPtr prgnExposed;
3757 unsigned long plane;
3760 miBSWindowPtr pBackingStore;
3761 RegionPtr (*copyProc)();
3763 register BoxPtr pBox;
3765 register int dx, dy;
3768 if (!REGION_NOTEMPTY(pGC->pScreen, prgnExposed))
3770 pBackingStore = (miBSWindowPtr)pSrc->backStorage;
3772 if ((pBackingStore->status == StatusNoPixmap) ||
3773 (pBackingStore->status == StatusBadAlloc))
3776 REGION_INIT( pGC->pScreen, &tempRgn, NullBox, 0);
3777 REGION_INTERSECT( pGC->pScreen, &tempRgn, prgnExposed,
3778 &pBackingStore->SavedRegion);
3779 REGION_SUBTRACT( pGC->pScreen, prgnExposed, prgnExposed, &tempRgn);
3782 copyProc = pGC->ops->CopyPlane;
3784 copyProc = pGC->ops->CopyArea;
3790 switch (pBackingStore->status) {
3793 pScratchGC = GetScratchGC (pDst->depth, pDst->pScreen);
3797 if (pGC->alu != pScratchGC->alu)
3798 gcMask = GCFunction;
3799 if (pGC->planemask != pScratchGC->planemask)
3800 gcMask |= GCPlaneMask;
3802 CopyGC (pGC, pScratchGC, gcMask);
3803 miBSFillVirtualBits (pDst, pScratchGC, &tempRgn, dx, dy,
3804 (int) pBackingStore->backgroundState,
3805 pBackingStore->background,
3807 FreeScratchGC (pScratchGC);
3810 case StatusContents:
3811 for (i = REGION_NUM_RECTS(&tempRgn), pBox = REGION_RECTS(&tempRgn);
3815 (* copyProc) (pBackingStore->pBackingPixmap, pDst, pGC,
3816 pBox->x1 - pBackingStore->x,
3817 pBox->y1 - pBackingStore->y,
3818 pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
3819 pBox->x1 + dx, pBox->y1 + dy, plane);
3823 REGION_UNINIT( pGC->pScreen, &tempRgn);