First import
[xorg_rtime.git] / xorg-server-1.4 / mi / mibstore.c
blob70839ce31fc407913e41535faf0b6560853caf33
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
9 documentation.
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
28 All Rights Reserved
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
36 permission.
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
40 implied warranty.
42 ******************************************************************/
45 #define NEED_EVENTS
46 #ifdef HAVE_DIX_CONFIG_H
47 #include <dix-config.h>
48 #endif
50 #include <X11/X.h>
51 #include <X11/Xmd.h>
52 #include <X11/Xproto.h>
53 #include "misc.h"
54 #include "regionstr.h"
55 #include "scrnintstr.h"
56 #include "gcstruct.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 */
62 #include "mi.h"
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.
71 /* #define BSEAGER */
73 /*-
74 * NOTES ON USAGE:
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
92 * to code option).
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
103 * CopyArea.
105 * JUSTIFICATION
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);
149 #define MoreCopy0 ;
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); \
157 int i; \
158 int bsx = pBackingStore->x; \
159 int bsy = pBackingStore->y; \
160 for (i = n; --i >= 0; ) \
162 *dstCopy++ = *srcCopy++ - bsx; \
163 *dstCopy++ = *srcCopy++ - bsy; \
164 morecopy \
168 #define copyPoints(src,dst,n,mode) \
169 if (mode == CoordModeOrigin) \
171 copyData(src,dst,n,MoreCopy0); \
173 else \
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,
193 char *pdstStart);
194 static Bool miBSChangeWindowAttributes(WindowPtr pWin,
195 unsigned long mask);
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,
204 int dx, int dy);
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,
212 int oldx, int oldy);
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,
216 int guarantee);
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 = {
234 miBSValidateGC,
235 miBSChangeGC,
236 miBSCopyGC,
237 miBSDestroyGC,
238 miBSChangeClip,
239 miBSDestroyClip,
240 miBSCopyClip,
243 static void miBSFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
244 DDXPointPtr pptInit, int *pwidthInit,
245 int fSorted);
246 static void miBSSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
247 DDXPointPtr ppt, int *pwidth, int nspans,
248 int fSorted);
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,
254 int dstx, int dsty);
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,
263 xSegment *pSegs);
264 static void miBSPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
265 int nrects, xRectangle *pRects);
266 static void miBSPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
267 xArc *parcs);
268 static void miBSFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
269 int shape, int mode, int count,
270 DDXPointPtr pPts);
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,
293 int x, int y);
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
317 * store enabled
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,
326 int nrects);
327 static void miBSCheapDestroyClip(GCPtr pGC);
328 static void miBSCheapCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
330 static GCFuncs miBSCheapGCFuncs = {
331 miBSCheapValidateGC,
332 miBSCheapChangeGC,
333 miBSCheapCopyGC,
334 miBSCheapDestroyGC,
335 miBSCheapChangeClip,
336 miBSCheapDestroyClip,
337 miBSCheapCopyClip,
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.
352 _X_EXPORT void
353 miInitializeBackingStore (pScreen)
354 ScreenPtr pScreen;
356 miBSScreenPtr pScreenPriv;
358 if (miBSGeneration != serverGeneration)
360 miBSScreenIndex = AllocateScreenPrivateIndex ();
361 if (miBSScreenIndex < 0)
362 return;
363 miBSGCIndex = AllocateGCPrivateIndex ();
364 miBSGeneration = serverGeneration;
366 if (!AllocateGCPrivate(pScreen, miBSGCIndex, 0))
367 return;
368 pScreenPriv = (miBSScreenPtr) xalloc (sizeof (miBSScreenRec));
369 if (!pScreenPriv)
370 return;
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 = \
402 ((miBSScreenPtr) \
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
413 static Bool
414 miBSCloseScreen (i, pScreen)
415 int i;
416 ScreenPtr 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);
437 static void
438 miBSGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
439 DrawablePtr pDrawable;
440 int sx, sy, w, h;
441 unsigned int format;
442 unsigned long planemask;
443 char *pdstLine;
445 ScreenPtr pScreen = pDrawable->pScreen;
446 BoxRec bounds;
447 unsigned char depth;
449 SCREEN_PROLOGUE (pScreen, GetImage);
451 if (pDrawable->type != DRAWABLE_PIXMAP &&
452 ((WindowPtr) pDrawable)->visibility != VisibilityUnobscured)
454 PixmapPtr pPixmap;
455 miBSWindowPtr pWindowPriv;
456 GCPtr pGC = NULL;
457 WindowPtr pWin, pSrcWin;
458 int xoff, yoff;
459 RegionRec Remaining;
460 RegionRec Border;
461 RegionRec Inside;
462 BoxPtr pBox;
463 int n;
465 pWin = (WindowPtr) pDrawable;
466 pPixmap = 0;
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);
473 for (;;)
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))
487 if (!pPixmap)
489 XID subWindowMode = IncludeInferiors;
490 int x, y;
492 pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, depth);
493 if (!pPixmap)
494 goto punt;
495 pGC = GetScratchGC (depth, pScreen);
496 if (!pGC)
498 (*pScreen->DestroyPixmap) (pPixmap);
499 goto punt;
501 ChangeGC (pGC, GCSubwindowMode, &subWindowMode);
502 ValidateGC ((DrawablePtr)pPixmap, pGC);
503 REGION_NULL(pScreen, &Border);
504 REGION_NULL(pScreen, &Inside);
505 pSrcWin = (WindowPtr) pDrawable;
506 x = sx;
507 y = sy;
508 if (pSrcWin->parent)
510 x += pSrcWin->origin.x;
511 y += pSrcWin->origin.y;
512 pSrcWin = pSrcWin->parent;
514 (*pGC->ops->CopyArea) ((DrawablePtr)pSrcWin,
515 (DrawablePtr)pPixmap, pGC,
516 x, y, w, h,
517 0, 0);
518 REGION_SUBTRACT(pScreen, &Remaining, &Remaining,
519 &((WindowPtr) pDrawable)->borderClip);
522 REGION_INTERSECT(pScreen, &Inside, &Remaining, &pWin->winSize);
523 REGION_TRANSLATE(pScreen, &Inside,
524 -pWin->drawable.x,
525 -pWin->drawable.y);
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)
537 case StatusContents:
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,
546 pBox->x2 - pBox->x1,
547 pBox->y2 - pBox->y1,
548 pBox->x1 + xoff,
549 pBox->y1 + yoff);
550 ++pBox;
552 break;
553 case StatusVirtual:
554 case StatusVDirty:
555 if (pWindowPriv->backgroundState == BackgroundPixmap ||
556 pWindowPriv->backgroundState == BackgroundPixel)
557 miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Inside,
558 xoff, yoff,
559 (int) pWindowPriv->backgroundState,
560 pWindowPriv->background, ~0L);
561 break;
564 REGION_SUBTRACT(pScreen, &Border, &pWin->borderSize,
565 &pWin->winSize);
566 REGION_INTERSECT(pScreen, &Border, &Border, &Remaining);
567 if (REGION_NUM_RECTS(&Border) > 0)
569 REGION_TRANSLATE(pScreen, &Border, -pWin->drawable.x,
570 -pWin->drawable.y);
571 miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Border,
572 xoff, yoff,
573 pWin->borderIsPixel ? (int)BackgroundPixel : (int)BackgroundPixmap,
574 pWin->border, ~0L);
578 if (pWin->viewable && pWin->firstChild)
579 pWin = pWin->firstChild;
580 else
582 while (!pWin->nextSib && pWin != (WindowPtr) pDrawable)
583 pWin = pWin->parent;
584 if (pWin == (WindowPtr) pDrawable)
585 break;
586 pWin = pWin->nextSib;
590 REGION_UNINIT(pScreen, &Remaining);
592 if (pPixmap)
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);
599 FreeScratchGC (pGC);
601 else
603 goto punt;
606 else
608 punt: ;
609 (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
610 format, planemask, pdstLine);
613 SCREEN_EPILOGUE (pScreen, GetImage, miBSGetImage);
616 static void
617 miBSGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
618 DrawablePtr pDrawable;
619 int wMax;
620 DDXPointPtr ppt;
621 int *pwidth;
622 int nspans;
623 char *pdstStart;
625 ScreenPtr pScreen = pDrawable->pScreen;
626 BoxRec bounds;
627 int i;
628 WindowPtr pWin;
629 int dx, dy;
631 SCREEN_PROLOGUE (pScreen, GetSpans);
633 if (pDrawable->type != DRAWABLE_PIXMAP && ((WindowPtr) pDrawable)->backStorage)
635 PixmapPtr pPixmap;
636 miBSWindowPtr pWindowPriv;
637 GCPtr pGC;
639 pWin = (WindowPtr) pDrawable;
640 pWindowPriv = (miBSWindowPtr) pWin->backStorage;
641 pPixmap = pWindowPriv->pBackingPixmap;
643 bounds.x1 = ppt->x;
644 bounds.y1 = ppt->y;
645 bounds.x2 = bounds.x1 + *pwidth;
646 bounds.y2 = ppt->y;
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))
661 case rgnPART:
662 if (!pPixmap)
664 miCreateBSPixmap (pWin, NullBox);
665 if (!(pPixmap = pWindowPriv->pBackingPixmap))
666 break;
668 pWindowPriv->status = StatusNoPixmap;
669 pGC = GetScratchGC(pPixmap->drawable.depth,
670 pPixmap->drawable.pScreen);
671 if (pGC)
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 -
679 pWindowPriv->x,
680 bounds.y1 + pPixmap->drawable.y - pWin->drawable.y -
681 pWindowPriv->y);
682 FreeScratchGC(pGC);
684 pWindowPriv->status = StatusContents;
685 /* fall through */
686 case rgnIN:
687 if (!pPixmap)
689 miCreateBSPixmap (pWin, NullBox);
690 if (!(pPixmap = pWindowPriv->pBackingPixmap))
691 break;
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++)
697 ppt[i].x += dx;
698 ppt[i].y += dy;
700 (*pScreen->GetSpans) ((DrawablePtr) pPixmap, wMax, ppt, pwidth,
701 nspans, pdstStart);
702 break;
703 case rgnOUT:
704 (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans,
705 pdstStart);
706 break;
709 else
711 (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
714 SCREEN_EPILOGUE (pScreen, GetSpans, miBSGetSpans);
717 static Bool
718 miBSChangeWindowAttributes (pWin, mask)
719 WindowPtr pWin;
720 unsigned long mask;
722 ScreenPtr pScreen;
723 Bool ret;
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)
734 miBSAllocate (pWin);
735 else
736 miBSFree (pWin);
739 SCREEN_EPILOGUE (pScreen, ChangeWindowAttributes, miBSChangeWindowAttributes);
741 return ret;
745 * GC Create wrapper. Set up the cheap GC func wrappers to track
746 * GC validation on BackingStore windows
749 static Bool
750 miBSCreateGC (pGC)
751 GCPtr pGC;
753 ScreenPtr pScreen = pGC->pScreen;
754 Bool ret;
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);
766 return ret;
769 static Bool
770 miBSDestroyWindow (pWin)
771 WindowPtr pWin;
773 ScreenPtr pScreen = pWin->drawable.pScreen;
774 Bool ret;
776 SCREEN_PROLOGUE (pScreen, DestroyWindow);
778 ret = (*pScreen->DestroyWindow) (pWin);
780 miBSFree (pWin);
782 SCREEN_EPILOGUE (pScreen, DestroyWindow, miBSDestroyWindow);
784 return ret;
788 * cheap GC func wrappers. Simply track validation on windows
789 * with backing store to enable the real func/op wrappers
792 static void
793 miBSCheapValidateGC (pGC, stateChanges, pDrawable)
794 GCPtr pGC;
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);
806 else
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);
817 static void
818 miBSCheapChangeGC (pGC, mask)
819 GCPtr pGC;
820 unsigned long mask;
822 CHEAP_FUNC_PROLOGUE (pGC);
824 (*pGC->funcs->ChangeGC) (pGC, mask);
826 CHEAP_FUNC_EPILOGUE (pGC);
829 static void
830 miBSCheapCopyGC (pGCSrc, mask, pGCDst)
831 GCPtr pGCSrc, pGCDst;
832 unsigned long mask;
834 CHEAP_FUNC_PROLOGUE (pGCDst);
836 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
838 CHEAP_FUNC_EPILOGUE (pGCDst);
841 static void
842 miBSCheapDestroyGC (pGC)
843 GCPtr pGC;
845 CHEAP_FUNC_PROLOGUE (pGC);
847 (*pGC->funcs->DestroyGC) (pGC);
849 /* leave it unwrapped */
852 static void
853 miBSCheapChangeClip (pGC, type, pvalue, nrects)
854 GCPtr pGC;
855 int type;
856 pointer pvalue;
857 int nrects;
859 CHEAP_FUNC_PROLOGUE (pGC);
861 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
863 CHEAP_FUNC_EPILOGUE (pGC);
866 static void
867 miBSCheapCopyClip(pgcDst, pgcSrc)
868 GCPtr pgcDst, pgcSrc;
870 CHEAP_FUNC_PROLOGUE (pgcDst);
872 (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
874 CHEAP_FUNC_EPILOGUE (pgcDst);
877 static void
878 miBSCheapDestroyClip(pGC)
879 GCPtr 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
892 static Bool
893 miBSCreateGCPrivate (pGC)
894 GCPtr pGC;
896 miBSGCRec *pPriv;
898 pPriv = (miBSGCRec *) xalloc (sizeof (miBSGCRec));
899 if (!pPriv)
900 return FALSE;
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;
910 return TRUE;
913 static void
914 miBSDestroyGCPrivate (GCPtr pGC)
916 miBSGCRec *pPriv;
918 pPriv = (miBSGCRec *) pGC->devPrivates[miBSGCIndex].ptr;
919 if (pPriv)
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 *-----------------------------------------------------------------------
936 * miBSFillSpans --
937 * Perform a FillSpans, routing output to backing-store as needed.
939 * Results:
940 * None.
942 * Side Effects:
944 *-----------------------------------------------------------------------
946 static void
947 miBSFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
948 DrawablePtr pDrawable;
949 GCPtr pGC;
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 */
953 int fSorted;
955 DDXPointPtr pptCopy, pptReset;
956 int *pwidthCopy;
957 SETUP_BACKING (pDrawable, pGC);
959 PROLOGUE(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)
972 int dx, dy;
973 int nReset;
975 pptReset = pptCopy;
976 dx = pDrawable->x - pBackingDrawable->x;
977 dy = pDrawable->y - pBackingDrawable->y;
978 nReset = nInit;
979 while (nReset--)
981 pptReset->x -= dx;
982 pptReset->y -= dy;
983 ++pptReset;
986 (* pBackingGC->ops->FillSpans)(pBackingDrawable,
987 pBackingGC, nInit, pptCopy, pwidthCopy,
988 fSorted);
990 if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy);
991 if (pptCopy) DEALLOCATE_LOCAL(pptCopy);
993 EPILOGUE (pGC);
997 *-----------------------------------------------------------------------
998 * miBSSetSpans --
999 * Perform a SetSpans, routing output to backing-store as needed.
1001 * Results:
1002 * None.
1004 * Side Effects:
1006 *-----------------------------------------------------------------------
1008 static void
1009 miBSSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
1010 DrawablePtr pDrawable;
1011 GCPtr pGC;
1012 char *psrc;
1013 DDXPointPtr ppt;
1014 int *pwidth;
1015 int nspans;
1016 int fSorted;
1018 DDXPointPtr pptCopy, pptReset;
1019 int *pwidthCopy;
1020 SETUP_BACKING (pDrawable, pGC);
1022 PROLOGUE(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,
1032 nspans, fSorted);
1033 if (pGC->miTranslate)
1035 int dx, dy;
1036 int nReset;
1038 pptReset = pptCopy;
1039 dx = pDrawable->x - pBackingDrawable->x;
1040 dy = pDrawable->y - pBackingDrawable->y;
1041 nReset = nspans;
1042 while (nReset--)
1044 pptReset->x -= dx;
1045 pptReset->y -= dy;
1046 ++pptReset;
1049 (* pBackingGC->ops->SetSpans)(pBackingDrawable, pBackingGC,
1050 psrc, pptCopy, pwidthCopy, nspans, fSorted);
1052 if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy);
1053 if (pptCopy) DEALLOCATE_LOCAL(pptCopy);
1055 EPILOGUE (pGC);
1059 *-----------------------------------------------------------------------
1060 * miBSPutImage --
1061 * Perform a PutImage, routing output to backing-store as needed.
1063 * Results:
1064 * None.
1066 * Side Effects:
1068 *-----------------------------------------------------------------------
1070 static void
1071 miBSPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
1072 DrawablePtr pDrawable;
1073 GCPtr pGC;
1074 int depth;
1075 int x;
1076 int y;
1077 int w;
1078 int h;
1079 int leftPad;
1080 int format;
1081 char *pBits;
1083 SETUP_BACKING (pDrawable, pGC);
1085 PROLOGUE(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);
1093 EPILOGUE (pGC);
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 *-----------------------------------------------------------------------
1103 * miBSDoCopy --
1104 * Perform a CopyArea or CopyPlane within a window that has backing
1105 * store enabled.
1107 * Results:
1108 * TRUE if the copy was performed or FALSE if a regular one should
1109 * be done.
1111 * Side Effects:
1112 * Things are copied (no s***!)
1114 * Notes:
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 *-----------------------------------------------------------------------
1128 static Bool
1129 miBSDoCopy(
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) */
1145 struct BoxDraw {
1146 BoxPtr pBox; /* Source box */
1147 enum {
1148 win, pix
1149 } source; /* Place from which to copy */
1150 } *boxes; /* Array of box/drawable pairs covering
1151 * source box. */
1152 int *sequence; /* Sequence of boxes to move */
1153 int i, j, k, l, y;
1154 BoxPtr pBox;
1155 int dx, dy, nrects;
1156 Bool graphicsExposures;
1157 CopyPlaneProcPtr pixCopyProc;
1158 int numRectsExp, numRectsObs;
1159 BoxPtr pBoxExp, pBoxObs;
1161 SETUP_BACKING (pWin, pGC);
1162 (void)oldFuncs;
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,
1183 -pWin->drawable.x,
1184 -pWin->drawable.y);
1185 REGION_TRANSLATE(pGC->pScreen, pRgnObs,
1186 -pWin->drawable.x,
1187 -pWin->drawable.y);
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);
1198 return (FALSE);
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));
1209 *ppRgn = NULL;
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);
1218 return(TRUE);
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);
1227 k++)
1229 if (pBoxExp[i].y1 < pBoxObs[j].y1)
1231 boxes[k].pBox = &pBoxExp[i];
1232 boxes[k].source = win;
1233 i++;
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;
1240 j++;
1242 else
1244 boxes[k].pBox = &pBoxExp[i];
1245 boxes[k].source = win;
1246 i++;
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;
1260 i++;
1261 k++;
1262 } while (i < numRectsExp);
1265 else
1269 boxes[k].pBox = &pBoxObs[j];
1270 boxes[k].source = pix;
1271 j++;
1272 k++;
1273 } while (j < numRectsObs);
1276 if (dsty <= srcy)
1279 * Scroll up or vertically stationary, so vertical order is ok.
1281 if (dstx <= srcx)
1284 * Scroll left or horizontally stationary, so horizontal order
1285 * is ok as well.
1287 for (i = 0; i < nrects; i++)
1289 sequence[i] = i;
1292 else
1295 * Scroll right. Need to reverse the rectangles within each
1296 * band.
1298 for (i = 0, j = 1, k = 0;
1299 i < nrects;
1300 j = i + 1, k = i)
1302 y = boxes[i].pBox->y1;
1303 while ((j < nrects) && (boxes[j].pBox->y1 == y))
1305 j++;
1307 for (j--; j >= k; j--, i++)
1309 sequence[i] = j;
1314 else
1317 * Scroll down. Must reverse vertical banding, at least.
1319 if (dstx < srcx)
1322 * Scroll left. Horizontal order is ok.
1324 for (i = nrects - 1, j = i - 1, k = i, l = 0;
1325 i >= 0;
1326 j = i - 1, k = i)
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))
1335 j--;
1337 for (j++; j <= k; j++, i--, l++)
1339 sequence[l] = j;
1343 else
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
1349 * to compute).
1351 for (i = 0, j = nrects - 1; i < nrects; i++, j--)
1353 sequence[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;
1367 dx = dstx - srcx;
1368 dy = dsty - srcy;
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.
1376 if (plane != 0)
1378 pixCopyProc = pBackingGC->ops->CopyPlane;
1380 else
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);
1409 else
1411 (void) (* pixCopyProc) (&(pWin->drawable), pBackingDrawable, pBackingGC,
1412 pBox->x1, pBox->y1,
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,
1417 pBox->x1, pBox->y1,
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
1430 * events.
1432 REGION_UNION(pGC->pScreen, pRgnExp, pRgnExp, pRgnObs);
1433 box.x1 = srcx;
1434 box.x2 = srcx + w;
1435 box.y1 = srcy;
1436 box.y2 = srcy + h;
1437 if (RECT_IN_REGION(pGC->pScreen, pRgnExp, &box) == rgnIN)
1439 REGION_EMPTY(pGC->pScreen, pRgnExp);
1441 else
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,
1451 -pWin->drawable.x,
1452 -pWin->drawable.y);
1453 miBSClearBackingRegion (pWin, pRgnExp);
1455 if (graphicsExposures)
1456 *ppRgn = pRgnExp;
1457 else
1458 REGION_DESTROY(pGC->pScreen, pRgnExp);
1459 REGION_DESTROY(pGC->pScreen, pRgnObs);
1461 return (TRUE);
1465 *-----------------------------------------------------------------------
1466 * miBSCopyArea --
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.
1473 * Results:
1474 * None.
1476 * Side Effects:
1478 *-----------------------------------------------------------------------
1480 static RegionPtr
1481 miBSCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
1482 DrawablePtr pSrc;
1483 DrawablePtr pDst;
1484 GCPtr pGC;
1485 int srcx;
1486 int srcy;
1487 int w;
1488 int h;
1489 int dstx;
1490 int dsty;
1492 BoxPtr pExtents;
1493 long dx, dy;
1494 int bsrcx, bsrcy, bw, bh, bdstx, bdsty;
1495 RegionPtr pixExposed = 0, winExposed = 0;
1497 SETUP_BACKING(pDst, pGC);
1499 PROLOGUE(pGC);
1501 if ((pSrc != pDst) ||
1502 (!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty,
1503 (unsigned long) 0, (CopyPlaneProcPtr)pGC->ops->CopyArea,
1504 &winExposed)))
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);
1521 bsrcx = srcx;
1522 bsrcy = srcy;
1523 bw = w;
1524 bh = h;
1525 bdstx = dstx;
1526 bdsty = dsty;
1527 dx = pExtents->x1 - bdstx;
1528 if (dx > 0)
1530 bsrcx += dx;
1531 bdstx += dx;
1532 bw -= dx;
1534 dy = pExtents->y1 - bdsty;
1535 if (dy > 0)
1537 bsrcy += dy;
1538 bdsty += dy;
1539 bh -= dy;
1541 dx = (bdstx + bw) - pExtents->x2;
1542 if (dx > 0)
1543 bw -= dx;
1544 dy = (bdsty + bh) - pExtents->y2;
1545 if (dy > 0)
1546 bh -= dy;
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);
1553 else
1554 pixExposed = (* pBackingGC->ops->CopyArea) (pSrc,
1555 pBackingDrawable, pBackingGC,
1556 srcx, srcy, w, h,
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
1565 if (winExposed)
1567 if (pixExposed){
1568 REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed);
1569 REGION_DESTROY(pDst->pScreen, pixExposed);
1571 } else
1572 winExposed = pixExposed;
1574 EPILOGUE (pGC);
1576 return winExposed;
1580 *-----------------------------------------------------------------------
1581 * miBSCopyPlane --
1583 * Results:
1584 * None.
1586 * Side Effects:
1588 *-----------------------------------------------------------------------
1590 static RegionPtr
1591 miBSCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
1592 DrawablePtr pSrc;
1593 DrawablePtr pDst;
1594 GC *pGC;
1595 int srcx,
1596 srcy;
1597 int w,
1599 int dstx,
1600 dsty;
1601 unsigned long plane;
1603 BoxPtr pExtents;
1604 long dx, dy;
1605 int bsrcx, bsrcy, bw, bh, bdstx, bdsty;
1606 RegionPtr winExposed = 0, pixExposed = 0;
1607 SETUP_BACKING(pDst, pGC);
1609 PROLOGUE(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);
1630 bsrcx = srcx;
1631 bsrcy = srcy;
1632 bw = w;
1633 bh = h;
1634 bdstx = dstx;
1635 bdsty = dsty;
1636 dx = pExtents->x1 - bdstx;
1637 if (dx > 0)
1639 bsrcx += dx;
1640 bdstx += dx;
1641 bw -= dx;
1643 dy = pExtents->y1 - bdsty;
1644 if (dy > 0)
1646 bsrcy += dy;
1647 bdsty += dy;
1648 bh -= dy;
1650 dx = (bdstx + bw) - pExtents->x2;
1651 if (dx > 0)
1652 bw -= dx;
1653 dy = (bdsty + bh) - pExtents->y2;
1654 if (dy > 0)
1655 bh -= dy;
1656 if (bw > 0 && bh > 0)
1657 pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc,
1658 pBackingDrawable,
1659 pBackingGC, bsrcx, bsrcy, bw, bh,
1660 bdstx - pBackingStore->x,
1661 bdsty - pBackingStore->y, plane);
1663 else
1664 pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc,
1665 pBackingDrawable,
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,
1671 dstx, dsty, plane);
1676 * compute the composite graphics exposure region
1678 if (winExposed)
1680 if (pixExposed)
1682 REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed);
1683 REGION_DESTROY(pDst->pScreen, pixExposed);
1685 } else
1686 winExposed = pixExposed;
1688 EPILOGUE (pGC);
1690 return winExposed;
1694 *-----------------------------------------------------------------------
1695 * miBSPolyPoint --
1696 * Perform a PolyPoint, routing output to backing-store as needed.
1698 * Results:
1699 * None.
1701 * Side Effects:
1703 *-----------------------------------------------------------------------
1705 static void
1706 miBSPolyPoint (pDrawable, pGC, mode, npt, pptInit)
1707 DrawablePtr pDrawable;
1708 GCPtr pGC;
1709 int mode; /* Origin or Previous */
1710 int npt;
1711 xPoint *pptInit;
1713 xPoint *pptCopy;
1714 SETUP_BACKING (pDrawable, pGC);
1716 PROLOGUE(pGC);
1718 pptCopy = (xPoint *)ALLOCATE_LOCAL(npt*sizeof(xPoint));
1719 if (pptCopy)
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);
1731 EPILOGUE (pGC);
1735 *-----------------------------------------------------------------------
1736 * miBSPolyLines --
1737 * Perform a Polylines, routing output to backing-store as needed.
1739 * Results:
1741 * Side Effects:
1743 *-----------------------------------------------------------------------
1745 static void
1746 miBSPolylines (pDrawable, pGC, mode, npt, pptInit)
1747 DrawablePtr pDrawable;
1748 GCPtr pGC;
1749 int mode;
1750 int npt;
1751 DDXPointPtr pptInit;
1753 DDXPointPtr pptCopy;
1754 SETUP_BACKING (pDrawable, pGC);
1756 PROLOGUE(pGC);
1758 pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(npt*sizeof(DDXPointRec));
1759 if (pptCopy)
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);
1769 EPILOGUE (pGC);
1773 *-----------------------------------------------------------------------
1774 * miBSPolySegment --
1775 * Perform a PolySegment, routing output to backing-store as needed.
1777 * Results:
1778 * None.
1780 * Side Effects:
1782 *-----------------------------------------------------------------------
1784 static void
1785 miBSPolySegment(pDrawable, pGC, nseg, pSegs)
1786 DrawablePtr pDrawable;
1787 GCPtr pGC;
1788 int nseg;
1789 xSegment *pSegs;
1791 xSegment *pSegsCopy;
1793 SETUP_BACKING (pDrawable, pGC);
1795 PROLOGUE(pGC);
1797 pSegsCopy = (xSegment *)ALLOCATE_LOCAL(nseg*sizeof(xSegment));
1798 if (pSegsCopy)
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);
1809 EPILOGUE (pGC);
1813 *-----------------------------------------------------------------------
1814 * miBSPolyRectangle --
1815 * Perform a PolyRectangle, routing output to backing-store as needed.
1817 * Results:
1818 * None
1820 * Side Effects:
1822 *-----------------------------------------------------------------------
1824 static void
1825 miBSPolyRectangle(pDrawable, pGC, nrects, pRects)
1826 DrawablePtr pDrawable;
1827 GCPtr pGC;
1828 int nrects;
1829 xRectangle *pRects;
1831 xRectangle *pRectsCopy;
1832 SETUP_BACKING (pDrawable, pGC);
1834 PROLOGUE(pGC);
1836 pRectsCopy =(xRectangle *)ALLOCATE_LOCAL(nrects*sizeof(xRectangle));
1837 if (pRectsCopy)
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);
1848 EPILOGUE (pGC);
1852 *-----------------------------------------------------------------------
1853 * miBSPolyArc --
1854 * Perform a PolyArc, routing output to backing-store as needed.
1856 * Results:
1858 * Side Effects:
1860 *-----------------------------------------------------------------------
1862 static void
1863 miBSPolyArc(pDrawable, pGC, narcs, parcs)
1864 DrawablePtr pDrawable;
1865 GCPtr pGC;
1866 int narcs;
1867 xArc *parcs;
1869 xArc *pArcsCopy;
1870 SETUP_BACKING (pDrawable, pGC);
1872 PROLOGUE(pGC);
1874 pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc));
1875 if (pArcsCopy)
1877 copyData(parcs, pArcsCopy, narcs, MoreCopy4);
1879 (* pGC->ops->PolyArc)(pDrawable, pGC, narcs, parcs);
1880 (* pBackingGC->ops->PolyArc)(pBackingDrawable, pBackingGC,
1881 narcs, pArcsCopy);
1883 DEALLOCATE_LOCAL(pArcsCopy);
1886 EPILOGUE (pGC);
1890 *-----------------------------------------------------------------------
1891 * miBSFillPolygon --
1892 * Perform a FillPolygon, routing output to backing-store as needed.
1894 * Results:
1895 * None.
1897 * Side Effects:
1899 *-----------------------------------------------------------------------
1901 static void
1902 miBSFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
1903 DrawablePtr pDrawable;
1904 GCPtr pGC;
1905 int shape, mode;
1906 int count;
1907 DDXPointPtr pPts;
1909 DDXPointPtr pPtsCopy;
1910 SETUP_BACKING (pDrawable, pGC);
1912 PROLOGUE(pGC);
1914 pPtsCopy = (DDXPointPtr)ALLOCATE_LOCAL(count*sizeof(DDXPointRec));
1915 if (pPtsCopy)
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,
1921 count, pPtsCopy);
1923 DEALLOCATE_LOCAL(pPtsCopy);
1926 EPILOGUE (pGC);
1930 *-----------------------------------------------------------------------
1931 * miBSPolyFillRect --
1932 * Perform a PolyFillRect, routing output to backing-store as needed.
1934 * Results:
1935 * None.
1937 * Side Effects:
1939 *-----------------------------------------------------------------------
1941 static void
1942 miBSPolyFillRect(pDrawable, pGC, nrectFill, prectInit)
1943 DrawablePtr pDrawable;
1944 GCPtr pGC;
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);
1951 PROLOGUE(pGC);
1953 pRectCopy =
1954 (xRectangle *)ALLOCATE_LOCAL(nrectFill*sizeof(xRectangle));
1955 if (pRectCopy)
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);
1966 EPILOGUE (pGC);
1970 *-----------------------------------------------------------------------
1971 * miBSPolyFillArc --
1972 * Perform a PolyFillArc, routing output to backing-store as needed.
1974 * Results:
1975 * None.
1977 * Side Effects:
1979 *-----------------------------------------------------------------------
1981 static void
1982 miBSPolyFillArc(pDrawable, pGC, narcs, parcs)
1983 DrawablePtr pDrawable;
1984 GCPtr pGC;
1985 int narcs;
1986 xArc *parcs;
1988 xArc *pArcsCopy;
1989 SETUP_BACKING (pDrawable, pGC);
1991 PROLOGUE(pGC);
1993 pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc));
1994 if (pArcsCopy)
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);
2003 EPILOGUE (pGC);
2008 *-----------------------------------------------------------------------
2009 * miBSPolyText8 --
2010 * Perform a PolyText8, routing output to backing-store as needed.
2012 * Results:
2014 * Side Effects:
2016 *-----------------------------------------------------------------------
2018 static int
2019 miBSPolyText8(pDrawable, pGC, x, y, count, chars)
2020 DrawablePtr pDrawable;
2021 GCPtr pGC;
2022 int x, y;
2023 int count;
2024 char *chars;
2026 int result;
2027 SETUP_BACKING (pDrawable, pGC);
2029 PROLOGUE(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,
2034 count, chars);
2036 EPILOGUE (pGC);
2037 return result;
2041 *-----------------------------------------------------------------------
2042 * miBSPolyText16 --
2043 * Perform a PolyText16, routing output to backing-store as needed.
2045 * Results:
2047 * Side Effects:
2049 *-----------------------------------------------------------------------
2051 static int
2052 miBSPolyText16(pDrawable, pGC, x, y, count, chars)
2053 DrawablePtr pDrawable;
2054 GCPtr pGC;
2055 int x, y;
2056 int count;
2057 unsigned short *chars;
2059 int result;
2060 SETUP_BACKING (pDrawable, pGC);
2062 PROLOGUE(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,
2067 count, chars);
2069 EPILOGUE (pGC);
2071 return result;
2075 *-----------------------------------------------------------------------
2076 * miBSImageText8 --
2077 * Perform a ImageText8, routing output to backing-store as needed.
2079 * Results:
2081 * Side Effects:
2083 *-----------------------------------------------------------------------
2085 static void
2086 miBSImageText8(pDrawable, pGC, x, y, count, chars)
2087 DrawablePtr pDrawable;
2088 GCPtr pGC;
2089 int x, y;
2090 int count;
2091 char *chars;
2093 SETUP_BACKING (pDrawable, pGC);
2094 PROLOGUE(pGC);
2096 (* pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
2097 (* pBackingGC->ops->ImageText8)(pBackingDrawable, pBackingGC,
2098 x - pBackingStore->x, y - pBackingStore->y,
2099 count, chars);
2101 EPILOGUE (pGC);
2105 *-----------------------------------------------------------------------
2106 * miBSImageText16 --
2107 * Perform a ImageText16, routing output to backing-store as needed.
2109 * Results:
2111 * Side Effects:
2113 *-----------------------------------------------------------------------
2115 static void
2116 miBSImageText16(pDrawable, pGC, x, y, count, chars)
2117 DrawablePtr pDrawable;
2118 GCPtr pGC;
2119 int x, y;
2120 int count;
2121 unsigned short *chars;
2123 SETUP_BACKING (pDrawable, pGC);
2124 PROLOGUE(pGC);
2126 (* pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
2127 (* pBackingGC->ops->ImageText16)(pBackingDrawable, pBackingGC,
2128 x - pBackingStore->x, y - pBackingStore->y,
2129 count, chars);
2131 EPILOGUE (pGC);
2135 *-----------------------------------------------------------------------
2136 * miBSImageGlyphBlt --
2137 * Perform a ImageGlyphBlt, routing output to backing-store as needed.
2139 * Results:
2141 * Side Effects:
2143 *-----------------------------------------------------------------------
2145 static void
2146 miBSImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
2147 DrawablePtr pDrawable;
2148 GCPtr pGC;
2149 int x, y;
2150 unsigned int nglyph;
2151 CharInfoPtr *ppci; /* array of character info */
2152 pointer pglyphBase; /* start of array of glyphs */
2154 SETUP_BACKING (pDrawable, pGC);
2155 PROLOGUE(pGC);
2157 (* pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci,
2158 pglyphBase);
2159 (* pBackingGC->ops->ImageGlyphBlt)(pBackingDrawable, pBackingGC,
2160 x - pBackingStore->x, y - pBackingStore->y,
2161 nglyph, ppci, pglyphBase);
2163 EPILOGUE (pGC);
2167 *-----------------------------------------------------------------------
2168 * miBSPolyGlyphBlt --
2169 * Perform a PolyGlyphBlt, routing output to backing-store as needed.
2171 * Results:
2173 * Side Effects:
2175 *-----------------------------------------------------------------------
2177 static void
2178 miBSPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
2179 DrawablePtr pDrawable;
2180 GCPtr pGC;
2181 int x, y;
2182 unsigned int nglyph;
2183 CharInfoPtr *ppci; /* array of character info */
2184 pointer pglyphBase; /* start of array of glyphs */
2186 SETUP_BACKING (pDrawable, pGC);
2187 PROLOGUE(pGC);
2189 (* pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
2190 ppci, pglyphBase);
2191 (* pBackingGC->ops->PolyGlyphBlt)(pBackingDrawable, pBackingGC,
2192 x - pBackingStore->x, y - pBackingStore->y,
2193 nglyph, ppci, pglyphBase);
2194 EPILOGUE (pGC);
2198 *-----------------------------------------------------------------------
2199 * miBSPushPixels --
2200 * Perform a PushPixels, routing output to backing-store as needed.
2202 * Results:
2204 * Side Effects:
2206 *-----------------------------------------------------------------------
2208 static void
2209 miBSPushPixels(pGC, pBitMap, pDst, w, h, x, y)
2210 GCPtr pGC;
2211 PixmapPtr pBitMap;
2212 DrawablePtr pDst;
2213 int w, h, x, y;
2215 SETUP_BACKING (pDst, pGC);
2216 PROLOGUE(pGC);
2218 (* pGC->ops->PushPixels)(pGC, pBitMap, pDst, w, h, x, y);
2219 if (pGC->miTranslate) {
2220 x -= pDst->x;
2221 y -= pDst->y;
2223 (* pBackingGC->ops->PushPixels)(pBackingGC, pBitMap,
2224 pBackingDrawable, w, h,
2225 x - pBackingStore->x, y - pBackingStore->y);
2227 EPILOGUE (pGC);
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.
2240 * Results:
2241 * None.
2243 * Side Effects:
2244 * Areas of pixmap are cleared and Expose events are generated.
2246 *-----------------------------------------------------------------------
2248 static RegionPtr
2249 miBSClearBackingStore(pWin, x, y, w, h, generateExposures)
2250 WindowPtr pWin;
2251 int x;
2252 int y;
2253 int w;
2254 int h;
2255 Bool generateExposures;
2257 RegionPtr pRgn;
2258 int i;
2259 miBSWindowPtr pBackingStore;
2260 ScreenPtr pScreen;
2261 GCPtr pGC;
2262 int ts_x_origin,
2263 ts_y_origin;
2264 pointer gcvalues[4];
2265 unsigned long gcmask;
2266 xRectangle *rects;
2267 BoxPtr pBox;
2268 BoxRec box;
2269 PixUnion background;
2270 char backgroundState;
2271 int numRects;
2273 pBackingStore = (miBSWindowPtr)pWin->backStorage;
2274 pScreen = pWin->drawable.pScreen;
2276 if ((pBackingStore->status == StatusNoPixmap) ||
2277 (pBackingStore->status == StatusBadAlloc))
2278 return NullRegion;
2280 if (w == 0)
2281 w = (int) pWin->drawable.width - x;
2282 if (h == 0)
2283 h = (int) pWin->drawable.height - y;
2285 box.x1 = x;
2286 box.y1 = y;
2287 box.x2 = x + w;
2288 box.y2 = y + h;
2289 pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1);
2290 if (!pRgn)
2291 return NullRegion;
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)
2305 if (!pWin->parent)
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) {
2316 WindowPtr pParent;
2318 pParent = pWin;
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,
2332 backgroundState,
2333 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;
2354 else
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));
2373 if (rects)
2375 for (i = 0, pBox = REGION_RECTS(pRgn);
2376 i < numRects;
2377 i++, pBox++)
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);
2389 FreeScratchGC(pGC);
2393 if (!generateExposures)
2395 REGION_DESTROY(pScreen, pRgn);
2396 pRgn = NULL;
2398 else
2401 * result must be screen relative, but is currently
2402 * drawable relative.
2404 REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x,
2405 pWin->drawable.y);
2408 else
2410 REGION_DESTROY( pScreen, pRgn);
2411 pRgn = NULL;
2413 return pRgn;
2416 static void
2417 miBSClearBackingRegion (pWin, pRgn)
2418 WindowPtr pWin;
2419 RegionPtr pRgn;
2421 BoxPtr pBox;
2422 int i;
2424 i = REGION_NUM_RECTS(pRgn);
2425 pBox = REGION_RECTS(pRgn);
2426 while (i--)
2428 (void) miBSClearBackingStore(pWin, pBox->x1, pBox->y1,
2429 pBox->x2 - pBox->x1,
2430 pBox->y2 - pBox->y1,
2431 FALSE);
2432 pBox++;
2437 * fill a region of the destination with virtual bits
2439 * pRgn is to be translated by (x,y)
2442 static void
2443 miBSFillVirtualBits (pDrawable, pGC, pRgn, x, y, state, pixunion, planeMask)
2444 DrawablePtr pDrawable;
2445 GCPtr pGC;
2446 RegionPtr pRgn;
2447 int x, y;
2448 int state;
2449 PixUnion pixunion;
2450 unsigned long planeMask;
2452 int i;
2453 BITS32 gcmask;
2454 pointer gcval[5];
2455 xRectangle *pRect;
2456 BoxPtr pBox;
2457 WindowPtr pWin;
2458 int numRects;
2460 if (state == None)
2461 return;
2462 numRects = REGION_NUM_RECTS(pRgn);
2463 pRect = (xRectangle *)ALLOCATE_LOCAL(numRects * sizeof(xRectangle));
2464 if (!pRect)
2465 return;
2466 pWin = 0;
2467 if (pDrawable->type != DRAWABLE_PIXMAP)
2469 pWin = (WindowPtr) pDrawable;
2470 if (!pWin->backStorage)
2471 pWin = 0;
2473 i = 0;
2474 gcmask = 0;
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;
2490 else
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;
2500 gcmask |= GCTile;
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;
2513 if (gcmask)
2514 DoChangeGC (pGC, gcmask, (XID *)gcval, 1);
2516 if (pWin)
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;
2530 pRect -= numRects;
2531 (*pGC->ops->PolyFillRect) (pDrawable, pGC, numRects, pRect);
2532 if (pWin)
2533 (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
2534 DEALLOCATE_LOCAL (pRect);
2538 *-----------------------------------------------------------------------
2539 * miBSAllocate --
2540 * Create and install backing store info for a window
2542 *-----------------------------------------------------------------------
2545 static void
2546 miBSAllocate(pWin)
2547 WindowPtr pWin;
2549 miBSWindowPtr pBackingStore;
2550 ScreenPtr pScreen;
2552 if (pWin->drawable.pScreen->backingStoreSupport == NotUseful)
2553 return;
2554 pScreen = pWin->drawable.pScreen;
2555 if (!(pBackingStore = (miBSWindowPtr)pWin->backStorage))
2558 pBackingStore = (miBSWindowPtr)xalloc(sizeof(miBSWindowRec));
2559 if (!pBackingStore)
2560 return;
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)))
2584 BoxRec box;
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,
2596 -pWin->drawable.x,
2597 -pWin->drawable.y);
2598 #ifdef SHAPE
2599 if (wBoundingShape (pWin))
2600 REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion,
2601 wBoundingShape (pWin));
2602 if (wClipShape (pWin))
2603 REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion,
2604 wClipShape (pWin));
2605 #endif
2606 /* if window is already on-screen, assume it has been drawn to */
2607 if (pWin->viewable)
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 *-----------------------------------------------------------------------
2634 * miBSFree --
2635 * Destroy and free all the stuff associated with the backing-store
2636 * for the given window.
2638 * Results:
2639 * None.
2641 * Side Effects:
2642 * The backing pixmap and all the regions and GC's are destroyed.
2644 *-----------------------------------------------------------------------
2646 static void
2647 miBSFree(pWin)
2648 WindowPtr pWin;
2650 miBSWindowPtr pBackingStore;
2651 ScreenPtr pScreen;
2653 pScreen = pWin->drawable.pScreen;
2655 pBackingStore = (miBSWindowPtr)pWin->backStorage;
2656 if (pBackingStore)
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.
2674 * Results:
2675 * The new Pixmap is created as necessary.
2677 * Side Effects:
2678 * The old pixmap is destroyed.
2680 *-----------------------------------------------------------------------
2682 static void
2683 miResizeBackingStore(
2684 WindowPtr pWin,
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;
2691 ScreenPtr pScreen;
2692 GC *pGC;
2693 BoxPtr extents;
2694 PixmapPtr pNewPixmap;
2695 int nx, ny;
2696 int nw, nh;
2698 pBackingStore = (miBSWindowPtr)(pWin->backStorage);
2699 pBackingPixmap = pBackingStore->pBackingPixmap;
2700 if (!pBackingPixmap)
2701 return;
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;
2718 else
2720 pNewPixmap = (PixmapPtr)(*pScreen->CreatePixmap)
2721 (pScreen,
2722 nw, nh,
2723 pWin->drawable.depth);
2724 if (!pNewPixmap)
2726 #ifdef BSEAGER
2727 pBackingStore->status = StatusNoPixmap;
2728 #else
2729 pBackingStore->status = StatusBadAlloc;
2730 #endif
2734 if (!pNewPixmap)
2736 pBackingStore->x = 0;
2737 pBackingStore->y = 0;
2739 else
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);
2749 if (pGC)
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
2755 * pixmap
2757 (*pGC->ops->CopyArea)((DrawablePtr)pBackingPixmap,
2758 (DrawablePtr)pNewPixmap, pGC,
2759 0, 0,
2760 pBackingPixmap->drawable.width,
2761 pBackingPixmap->drawable.height,
2762 nx, ny);
2763 FreeScratchGC(pGC);
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.
2784 * Results:
2785 * None.
2787 * Side Effects:
2788 * The region is copied from the screen into pBackingPixmap and
2789 * SavedRegion is updated.
2791 *-----------------------------------------------------------------------
2793 static void
2794 miBSSaveDoomedAreas(pWin, pObscured, dx, dy)
2795 WindowPtr pWin;
2796 RegionPtr pObscured;
2797 int dx, dy;
2799 miBSWindowPtr pBackingStore;
2800 ScreenPtr pScreen;
2801 int x, y;
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);
2817 return;
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))
2826 return;
2828 if (REGION_NOTEMPTY(pScreen, pObscured))
2830 BoxRec oldExtents;
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,
2837 pObscured);
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);
2846 else
2847 miResizeBackingStore(pWin, 0, 0, TRUE);
2849 if (pBackingStore->pBackingPixmap) {
2850 if (pBackingStore->x | pBackingStore->y)
2852 REGION_TRANSLATE( pScreen, pObscured,
2853 -pBackingStore->x,
2854 -pBackingStore->y);
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);
2865 else
2867 if (REGION_BROKEN (pScreen, pObscured))
2869 REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
2870 miDestroyBSPixmap (pWin);
2871 return;
2877 *-----------------------------------------------------------------------
2878 * miBSRestoreAreas --
2879 * Restore areas from backing-store that are no longer obscured.
2880 * expects prgnExposed to contain a screen-relative area.
2882 * Results:
2883 * The region to generate exposure events on (which may be
2884 * different from the region to paint).
2886 * Side Effects:
2887 * Areas are copied from pBackingPixmap to the screen. prgnExposed
2888 * is altered to contain the region that could not be restored from
2889 * backing-store.
2891 * Notes:
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 *-----------------------------------------------------------------------
2900 static RegionPtr
2901 miBSRestoreAreas(pWin, prgnExposed)
2902 WindowPtr pWin;
2903 RegionPtr prgnExposed;
2905 PixmapPtr pBackingPixmap;
2906 miBSWindowPtr pBackingStore;
2907 RegionPtr prgnSaved;
2908 RegionPtr prgnRestored;
2909 ScreenPtr pScreen;
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,
2921 pWin->drawable.y);
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,
2942 prgnRestored,
2943 pWin->drawable.x + pBackingStore->x,
2944 pWin->drawable.y + pBackingStore->y,
2945 pWin);
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,
2955 -pWin->drawable.x,
2956 -pWin->drawable.y);
2957 miResizeBackingStore(pWin, 0, 0, TRUE);
2959 else
2960 miDestroyBSPixmap (pWin);
2962 else
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,
2977 pWin->background))
2979 REGION_SUBTRACT( pScreen, exposures, prgnExposed, prgnSaved);
2981 else
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.
3002 BoxRec box;
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,
3013 -pWin->drawable.x,
3014 -pWin->drawable.y);
3015 #ifdef SHAPE
3016 if (wBoundingShape (pWin))
3017 REGION_INTERSECT(pScreen, prgnSaved, prgnSaved,
3018 wBoundingShape (pWin));
3019 if (wClipShape (pWin))
3020 REGION_INTERSECT(pScreen, prgnSaved, prgnSaved,
3021 wClipShape (pWin));
3022 #endif
3023 miTileVirtualBS(pWin);
3025 exposures = REGION_CREATE( pScreen, &box, 1);
3027 pBackingStore->viewable = (char)pWin->viewable;
3028 return exposures;
3033 *-----------------------------------------------------------------------
3034 * miBSTranslateBackingStore --
3035 * Shift the backing-store in the given direction. Called when bit
3036 * gravity is shifting things around.
3038 * Results:
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).
3043 * Side Effects:
3044 * If the window changed size as well as position, the backing pixmap
3045 * is resized. The contents of the backing pixmap are shifted
3047 * Warning:
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
3051 * time.
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
3057 * possibilities:
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
3087 * in that case.
3088 *-----------------------------------------------------------------------
3091 static RegionPtr
3092 miBSTranslateBackingStore(pWin, windx, windy, oldClip, oldx, oldy)
3093 WindowPtr pWin;
3094 int windx; /* bit translation distance in window */
3095 int windy;
3096 RegionPtr oldClip; /* Region being copied */
3097 int oldx; /* old window position */
3098 int oldy;
3100 miBSWindowPtr pBackingStore;
3101 RegionPtr pSavedRegion;
3102 RegionPtr newSaved, doomed;
3103 ScreenPtr pScreen;
3104 BoxRec extents;
3105 int scrdx; /* bit translation distance on screen */
3106 int scrdy;
3107 int dx; /* distance window moved on screen */
3108 int dy;
3110 pScreen = pWin->drawable.pScreen;
3111 pBackingStore = (miBSWindowPtr)(pWin->backStorage);
3112 if ((pBackingStore->status == StatusNoPixmap) ||
3113 (pBackingStore->status == StatusBadAlloc))
3114 return NullRegion;
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);
3129 #ifdef SHAPE
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));
3137 #endif
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 */
3143 if (oldClip)
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
3160 scrdx = windx + dx;
3161 scrdy = windy + dy;
3164 * intersect at old bit position to discover the
3165 * bits on the screen which can be put into the
3166 * new backing store
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
3182 * bits back
3184 REGION_UNION( pScreen, newSaved, newSaved, pSavedRegion);
3187 * Swap the new saved region into the window
3190 RegionRec tmp;
3192 tmp = *pSavedRegion;
3193 *pSavedRegion = *newSaved;
3194 *newSaved = tmp;
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
3208 * the screen
3210 if (REGION_NOTEMPTY( pScreen, doomed))
3213 * Don't clear regions which have bits on the
3214 * screen
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,
3239 pWin->drawable.x,
3240 pWin->drawable.y);
3242 else
3244 REGION_DESTROY(pScreen, newSaved);
3245 newSaved = NullRegion;
3248 else
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);
3262 return newSaved;
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.
3272 static void
3273 miBSDrawGuarantee (pWin, pGC, guarantee)
3274 WindowPtr pWin;
3275 GCPtr pGC;
3276 int guarantee;
3278 miBSGCPtr pPriv;
3280 if (pWin->backStorage)
3282 pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
3283 if (!pPriv)
3284 (void) miBSCreateGCPrivate (pGC);
3285 pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
3286 if (pPriv)
3289 * XXX KLUDGE ALERT
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;
3301 break;
3307 #define noBackingCopy (GCGraphicsExposures|GCClipXOrigin|GCClipYOrigin| \
3308 GCClipMask|GCSubwindowMode| \
3309 GCTileStipXOrigin|GCTileStipYOrigin)
3312 *-----------------------------------------------------------------------
3313 * miBSValidateGC --
3314 * Wrapper around output-library's ValidateGC routine
3316 * Results:
3317 * None.
3319 * Side Effects:
3321 * Notes:
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
3330 * clientClip.
3331 *-----------------------------------------------------------------------
3334 static void
3335 miBSValidateGC (pGC, stateChanges, pDrawable)
3336 GCPtr pGC;
3337 unsigned long stateChanges;
3338 DrawablePtr pDrawable;
3340 GCPtr pBackingGC;
3341 miBSWindowPtr pWindowPriv = NULL;
3342 miBSGCPtr pPriv;
3343 WindowPtr pWin;
3344 int lift_functions;
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);
3353 else
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
3379 * be generated
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);
3395 else
3398 * Make a new copy of the client clip, translated to
3399 * its proper origin.
3402 REGION_COPY(pGC->pScreen, backingCompositeClip,
3403 pGC->clientClip);
3404 REGION_TRANSLATE(pGC->pScreen, backingCompositeClip,
3405 pGC->clipOrg.x,
3406 pGC->clipOrg.y);
3407 REGION_INTERSECT(pGC->pScreen, backingCompositeClip,
3408 backingCompositeClip,
3409 &pWindowPriv->SavedRegion);
3411 if (pGC->subWindowMode == IncludeInferiors)
3413 RegionPtr translatedClip;
3415 /* XXX
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,
3422 -pDrawable->x,
3423 -pDrawable->y);
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;
3431 else
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,
3449 * create it now.
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)
3466 int status;
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;
3474 else
3475 pPriv->pBackingGC = pBackingGC;
3478 pBackingGC = pPriv->pBackingGC;
3480 pPriv->stateChanges |= stateChanges;
3482 if (lift_functions)
3484 if (backingCompositeClip)
3485 REGION_DESTROY( pGC->pScreen, backingCompositeClip);
3487 /* unwrap the GC again */
3488 miBSDestroyGCPrivate (pGC);
3490 return;
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)
3504 XID vals[2];
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)
3513 XID vals[2];
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);
3527 else
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);
3549 static void
3550 miBSChangeGC (pGC, mask)
3551 GCPtr pGC;
3552 unsigned long 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);
3563 static void
3564 miBSCopyGC (pGCSrc, mask, pGCDst)
3565 GCPtr pGCSrc, pGCDst;
3566 unsigned long mask;
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);
3577 static void
3578 miBSDestroyGC (pGC)
3579 GCPtr pGC;
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);
3592 xfree(pPriv);
3595 static void
3596 miBSChangeClip(pGC, type, pvalue, nrects)
3597 GCPtr pGC;
3598 int type;
3599 pointer pvalue;
3600 int 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);
3611 static void
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);
3624 static void
3625 miBSDestroyClip(pGC)
3626 GCPtr pGC;
3628 miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
3630 FUNC_PROLOGUE (pGC, pPriv);
3632 (* pGC->funcs->DestroyClip)(pGC);
3634 FUNC_EPILOGUE (pGC, pPriv);
3637 static void
3638 miDestroyBSPixmap (pWin)
3639 WindowPtr pWin;
3641 miBSWindowPtr pBackingStore;
3642 ScreenPtr pScreen;
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;
3658 static void
3659 miTileVirtualBS (pWin)
3660 WindowPtr 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);
3683 #ifdef DEBUG
3684 static int BSAllocationsFailed = 0;
3685 #define FAILEDSIZE 32
3686 static struct { int w, h; } failedRecord[FAILEDSIZE];
3687 static int failedIndex;
3688 #endif
3690 static void
3691 miCreateBSPixmap (pWin, pExtents)
3692 WindowPtr pWin;
3693 BoxPtr pExtents;
3695 miBSWindowPtr pBackingStore;
3696 ScreenPtr pScreen;
3697 PixUnion background;
3698 char backgroundState = 0;
3699 BoxPtr extents;
3700 Bool backSet;
3702 pScreen = pWin->drawable.pScreen;
3703 pBackingStore = (miBSWindowPtr) pWin->backStorage;
3704 if (pBackingStore->status == StatusBadAlloc)
3705 return;
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)
3720 (pScreen,
3721 extents->x2 - extents->x1,
3722 extents->y2 - extents->y1,
3723 pWin->drawable.depth);
3725 if (!pBackingStore->pBackingPixmap)
3727 #ifdef DEBUG
3728 BSAllocationsFailed++;
3730 * record failed allocations
3732 failedRecord[failedIndex].w = pWin->drawable.width;
3733 failedRecord[failedIndex].h = pWin->drawable.height;
3734 failedIndex++;
3735 if (failedIndex == FAILEDSIZE)
3736 failedIndex = 0;
3737 #endif
3738 #ifdef BSEAGER
3739 pBackingStore->status = StatusNoPixmap;
3740 #else
3741 pBackingStore->status = StatusBadAlloc;
3742 #endif
3743 return;
3746 pBackingStore->status = StatusContents;
3748 if (backSet)
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++;
3759 if (!pExtents)
3760 pExtents = extents;
3762 if (pExtents->y1 != pExtents->y2)
3764 RegionPtr exposed;
3766 exposed = miBSClearBackingStore(pWin,
3767 pExtents->x1, pExtents->y1,
3768 pExtents->x2 - pExtents->x1,
3769 pExtents->y2 - pExtents->y1,
3770 !backSet);
3771 if (exposed)
3773 miSendExposures(pWin, exposed, pWin->drawable.x, pWin->drawable.y);
3774 REGION_DESTROY( pScreen, exposed);
3778 if (backSet)
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 *-----------------------------------------------------------------------
3792 * miBSExposeCopy --
3793 * Handle the restoration of areas exposed by graphics operations.
3795 * Results:
3796 * None.
3798 * Side Effects:
3799 * prgnExposed has the areas exposed from backing-store removed
3800 * from it.
3802 *-----------------------------------------------------------------------
3804 static void
3805 miBSExposeCopy (pSrc, pDst, pGC, prgnExposed, srcx, srcy, dstx, dsty, plane)
3806 WindowPtr pSrc;
3807 DrawablePtr pDst;
3808 GCPtr pGC;
3809 RegionPtr prgnExposed;
3810 int srcx, srcy;
3811 int dstx, dsty;
3812 unsigned long plane;
3814 RegionRec tempRgn;
3815 miBSWindowPtr pBackingStore;
3816 CopyPlaneProcPtr copyProc;
3817 GCPtr pScratchGC;
3818 BoxPtr pBox;
3819 int i;
3820 int dx, dy;
3821 BITS32 gcMask;
3823 if (!REGION_NOTEMPTY(pGC->pScreen, prgnExposed))
3824 return;
3825 pBackingStore = (miBSWindowPtr)pSrc->backStorage;
3827 if ((pBackingStore->status == StatusNoPixmap) ||
3828 (pBackingStore->status == StatusBadAlloc))
3829 return;
3831 REGION_NULL( pGC->pScreen, &tempRgn);
3832 REGION_INTERSECT( pGC->pScreen, &tempRgn, prgnExposed,
3833 &pBackingStore->SavedRegion);
3834 REGION_SUBTRACT( pGC->pScreen, prgnExposed, prgnExposed, &tempRgn);
3836 if (plane != 0) {
3837 copyProc = pGC->ops->CopyPlane;
3838 } else {
3839 copyProc = (CopyPlaneProcPtr)pGC->ops->CopyArea;
3842 dx = dstx - srcx;
3843 dy = dsty - srcy;
3845 switch (pBackingStore->status) {
3846 case StatusVirtual:
3847 case StatusVDirty:
3848 pScratchGC = GetScratchGC (pDst->depth, pDst->pScreen);
3849 if (pScratchGC)
3851 gcMask = 0;
3852 if (pGC->alu != pScratchGC->alu)
3853 gcMask = GCFunction;
3854 if (pGC->planemask != pScratchGC->planemask)
3855 gcMask |= GCPlaneMask;
3856 if (gcMask)
3857 CopyGC (pGC, pScratchGC, gcMask);
3858 miBSFillVirtualBits (pDst, pScratchGC, &tempRgn, dx, dy,
3859 (int) pBackingStore->backgroundState,
3860 pBackingStore->background,
3861 ~0L);
3862 FreeScratchGC (pScratchGC);
3864 break;
3865 case StatusContents:
3866 for (i = REGION_NUM_RECTS(&tempRgn), pBox = REGION_RECTS(&tempRgn);
3867 --i >= 0;
3868 pBox++)
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);
3876 break;
3878 REGION_UNINIT( pGC->pScreen, &tempRgn);