3 Copyright (c) 1989 X Consortium
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
28 /* $XConsortium: mbufbf.c,v 1.5 94/04/17 20:32:53 dpw Exp $ */
29 /* $XFree86: xc/programs/Xserver/Xext/mbufbf.c,v 3.0 1994/05/08 05:17:30 dawes Exp $ */
38 #include "windowstr.h"
39 #include "scrnintstr.h"
40 #include "pixmapstr.h"
41 #include "extnsionst.h"
42 #include "dixstruct.h"
45 #include "regionstr.h"
53 #define _MULTIBUF_SERVER_ /* don't want Xlib structures */
54 #define _MULTIBUF_BUFFER_
55 #include "multibufst.h"
58 Support for doublebuffer hardare
60 This code is designed to support doublebuffer hardware where the
61 displayed buffer is selected on a per-pixel basis by an additional bit
62 plane, called the select plane. It could probably be easily modified
63 to work with systems that use window-id planes.
65 This is done by creating a new drawable type, DRAWABLE_BUFFER. The
66 type has the same exact layout as a window drawable. Your code should
67 treat a DRAWABLE_BUFFER the same as it would tread a DRAWABLE_WINDOW
68 when handling the gc drawing functions. In addition, PaintWindowBackground,
69 CopyWindow, and all of the gc drawing functions to be able to draw into both
70 framebuffers. Which framebuffer to draw into is selected by the contents of
71 pWin->devPrivates[frameWindowPrivateIndex].
72 The content of the devPrivate is either from frameBuffer[0] or
73 frameBuffer[1], depending on which buffer is being drawn into. When
74 pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[0],
75 the functions should draw into the front framebuffer. When
76 pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[1],
77 the functions should draw into the back framebuffer.
79 In addition, you need to provide a function that allows you to copy
80 bits between the buffers (optional since CopyArea can be used) and a
81 function that draws into the select plane. Then, you need to register
82 your functions and other information, by calling:
85 RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
86 CopyBufferBitsFunc, DrawSelectPlaneFunc)
88 xMbufBufferInfo *pInfo;
89 DevUnion *frameBuffer;
92 "pInfo" is an array indicating which visuals and depths that double
93 buffering is supported on. "nInfo" is the length of the array.
95 "frameBuffer" is array of length 2. The contents of the array element
96 is ddx-specific. The content of frameBuffer[0] should, when placed in
97 the window private, indicate that framebuffer 0 should be drawn into.
98 The contents of frameBuffer[1], when placed into the window private,
99 should indicate that framebuffer 1 should be drawn into.
101 "selectPlane" is ddx-specific. It should contain information
102 neccessary for your displayProc to access the select plane.
103 It is passed to DrawSelectPlaneFunc.
105 "CopyBufferBitsFunc" is a ddx-specific function that copies from one
106 buffer of a multibuffered window to another buffer. If the CopyBufferBitsFunc
107 is NULL, a default function will be used that calls pScreen->CopyArea.
109 void CopyBufferBitsFunc(pMBWindow, srcBufferNum, dstBufferNum)
110 mbufWindowPtr pMBWindow;
111 int srcBufferNum, dstBufferNum;
113 "DrawSelectPlaneFunc" is a ddx-specific function that fills the
114 regions "prgn" of select plane with the value "bufferNum". If
115 selectPlane is a DrawablePtr (such as a PixmapPtr), you can pass
116 NULL for DrawSelectPlaneFunc, a default function will be used that
117 calls FillRectangle on the selectPlane.
119 void DrawSelectPlaneFunc(pScreen, selectPlane, prgn, bufferNum)
121 DevUnion selectPlane;
131 #define MAX_BUFFERS 2 /* Only supports 2 buffers */
132 #define FRONT_BUFFER 0
133 #define BACK_BUFFER 1
136 /* Buffer drawables have the same structure as window drawables */
137 typedef WindowRec BufferRec;
138 typedef WindowPtr BufferPtr;
142 * Call RegisterHdwrBuffer for every screen that has doublebuffer hardware.
145 static int bufNumInfo[MAXSCREENS];
146 static xMbufBufferInfo *bufInfo[MAXSCREENS];
147 static DevUnion *bufFrameBuffer[MAXSCREENS];
148 static DevUnion bufselectPlane[MAXSCREENS];
149 static void (* bufCopyBufferBitsFunc[MAXSCREENS])();
150 static void (* bufDrawSelectPlaneFunc[MAXSCREENS])();
152 static Bool bufMultibufferInit();
156 RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
157 CopyBufferBitsFunc, DrawSelectPlaneFunc)
160 xMbufBufferInfo *pInfo;
161 DevUnion *frameBuffer;
162 DevUnion selectPlane;
163 void (* CopyBufferBitsFunc)();
164 void (* DrawSelectPlaneFunc)();
166 bufNumInfo[pScreen->myNum] = nInfo;
167 bufInfo[pScreen->myNum] = pInfo;
168 bufFrameBuffer[pScreen->myNum] = frameBuffer;
169 bufselectPlane[pScreen->myNum] = selectPlane;
171 bufCopyBufferBitsFunc[pScreen->myNum] = CopyBufferBitsFunc;
172 bufDrawSelectPlaneFunc[pScreen->myNum] = DrawSelectPlaneFunc;
174 /* Register ourselves with device-independent multibuffers code */
175 RegisterMultibufferInit(pScreen, bufMultibufferInit);
180 * Called by Multibuffer extension initialization.
181 * Initializes mbufScreenRec and its devPrivate.
184 static Bool NoopDDA_True() { return TRUE; }
185 static Bool bufPositionWindow();
186 static int bufCreateImageBuffers();
187 static void bufDestroyImageBuffers();
188 static void bufDisplayImageBuffers();
189 static void bufClearImageBufferArea();
190 static void bufDestroyBuffer();
191 static void bufCopyBufferBits();
192 static void bufDrawSelectPlane();
193 static void bufWrapScreenFuncs();
194 static void bufResetProc();
196 static void bufPostValidateTree();
197 static void bufClipNotify();
198 static void bufWindowExposures();
199 static Bool bufChangeWindowAttributes();
200 static void bufClearToBackground();
201 static void bufCopyWindow();
203 extern WindowPtr *WindowTable;
206 bufMultibufferInit(pScreen, pMBScreen)
208 mbufScreenPtr pMBScreen;
210 mbufBufferPrivPtr pMBPriv;
213 /* Multibuffer info */
214 pMBScreen->nInfo = bufNumInfo[pScreen->myNum];
215 pMBScreen->pInfo = bufInfo[pScreen->myNum];
218 pMBScreen->CreateImageBuffers = bufCreateImageBuffers;
219 pMBScreen->DestroyImageBuffers = bufDestroyImageBuffers;
220 pMBScreen->DisplayImageBuffers = bufDisplayImageBuffers;
221 pMBScreen->ClearImageBufferArea = bufClearImageBufferArea;
222 pMBScreen->ChangeMBufferAttributes = NoopDDA_True;
223 pMBScreen->ChangeBufferAttributes = NoopDDA_True;
224 pMBScreen->DeleteBufferDrawable = bufDestroyBuffer;
225 pMBScreen->WrapScreenFuncs = bufWrapScreenFuncs;
226 pMBScreen->ResetProc = bufResetProc;
227 /* Create devPrivate part */
228 pMBPriv = (mbufBufferPrivPtr) xalloc(sizeof *pMBPriv);
232 pMBScreen->devPrivate.ptr = (pointer) pMBPriv;
233 pMBPriv->frameBuffer = bufFrameBuffer[pScreen->myNum];
234 pMBPriv->selectPlane = bufselectPlane[pScreen->myNum];
237 * Initializing the subtractRgn to the screen area will ensure that
238 * the selectPlane will get cleared on the first PostValidateTree.
243 box.x2 = pScreen->width;
244 box.y2 = pScreen->height;
246 pMBPriv->rgnChanged = TRUE;
247 REGION_INIT(pScreen, &pMBPriv->backBuffer, &box, 1);
248 REGION_INIT(pScreen, &pMBPriv->subtractRgn, &box, 1);
249 REGION_INIT(pScreen, &pMBPriv->unionRgn, NullBox, 0);
252 pMBPriv->CopyBufferBits = bufCopyBufferBitsFunc[pScreen->myNum];
253 pMBPriv->DrawSelectPlane = bufDrawSelectPlaneFunc[pScreen->myNum];
255 if (!pMBPriv->CopyBufferBits)
256 pMBPriv->CopyBufferBits = bufCopyBufferBits;
258 if (!pMBPriv->DrawSelectPlane)
259 pMBPriv->DrawSelectPlane = bufDrawSelectPlane;
261 /* screen functions */
262 pMBPriv->funcsWrapped = 0;
263 pMBPriv->inClearToBackground = FALSE;
264 pMBPriv->WindowExposures = NULL;
265 pMBPriv->CopyWindow = NULL;
266 pMBPriv->ClearToBackground = NULL;
267 pMBPriv->ClipNotify = NULL;
268 pMBPriv->ChangeWindowAttributes = NULL;
270 /* Start out wrapped to clear select plane */
271 WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree);
276 UpdateBufferFromWindow(pBuffer, pWin)
280 pBuffer->drawable.x = pWin->drawable.x;
281 pBuffer->drawable.y = pWin->drawable.y;
282 pBuffer->drawable.width = pWin->drawable.width;
283 pBuffer->drawable.height = pWin->drawable.height;
285 pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER;
287 /* Update for PaintWindowBackground */
288 pBuffer->parent = pWin->parent;
291 * Make the borderClip the same as the clipList so
292 * NotClippedByChildren comes out with just clipList.
295 pBuffer->clipList = pWin->clipList;
296 pBuffer->borderClip = pWin->clipList;
297 pBuffer->winSize = pWin->winSize;
298 pBuffer->borderSize = pWin->borderSize;
300 pBuffer->origin = pWin->origin;
304 bufCreateBuffer(pScreen, pWin, bufferNum)
309 mbufBufferPrivPtr pMBPriv;
310 DevUnion *devPrivates;
314 pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
316 pBuffer = AllocateWindow(pWin->drawable.pScreen);
320 /* XXX- Until we know what is needed, copy everything. */
321 devPrivates = pBuffer->devPrivates;
323 pBuffer->devPrivates = devPrivates;
325 pBuffer->drawable.type = DRAWABLE_BUFFER;
326 pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER;
328 pBuffer->nextSib = NULL;
329 pBuffer->prevSib = NULL;
330 pBuffer->firstChild = NULL;
331 pBuffer->lastChild = NULL;
333 /* XXX - Worry about backingstore later */
334 pBuffer->backStorage = NULL;
335 pBuffer->backingStore = NotUseful;
337 /* XXX - Need to call pScreen->CreateWindow for tile/stipples
338 * or should I just copy the devPrivates?
341 for (i=0; i < pScreen->WindowPrivateLen; i++)
342 pBuffer->devPrivates[i] = pWin->devPrivates[i];
344 pBuffer->devPrivates[frameWindowPrivateIndex] =
345 pMBPriv->frameBuffer[bufferNum];
351 bufDestroyBuffer(pDrawable)
352 DrawablePtr pDrawable;
359 bufCreateImageBuffers (pWin, nbuf, ids, action, hint)
367 mbufScreenPtr pMBScreen;
368 mbufWindowPtr pMBWindow;
369 mbufBufferPtr pMBBuffer;
372 pScreen = pWin->drawable.pScreen;
373 pMBScreen = MB_SCREEN_PRIV(pScreen);
374 pMBWindow = MB_WINDOW_PRIV(pWin);
376 pMBWindow->devPrivate.ptr = (pointer) REGION_CREATE(pScreen, 0,0);
377 if (!pMBWindow->devPrivate.ptr)
379 REGION_COPY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr,
382 for (i = 0; i < nbuf; i++)
384 pMBBuffer = pMBWindow->buffers + i;
385 pMBBuffer->pDrawable = (DrawablePtr) bufCreateBuffer(pScreen,pWin,i);
387 if (!pMBBuffer->pDrawable)
390 if (!AddResource (ids[i], MultibufferDrawableResType,
391 (pointer) pMBBuffer->pDrawable))
393 bufDestroyBuffer((BufferPtr) pMBBuffer->pDrawable);
396 pMBBuffer->pDrawable->id = ids[i];
399 * If window is already mapped, generate exposures and
400 * clear the area of the newly buffers.
403 if ((pWin->realized) && (i != pMBWindow->displayedMultibuffer))
404 (* pMBScreen->ClearImageBufferArea)(pMBBuffer, 0,0, 0,0, TRUE);
411 bufDestroyImageBuffers(pWin)
415 mbufWindowPtr pMBWindow;
417 pScreen = pWin->drawable.pScreen;
419 if (pMBWindow = MB_WINDOW_PRIV(pWin))
421 mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
424 * if the backbuffer is currently being displayed, move the bits
425 * to the frontbuffer and display it instead.
428 if (pWin->realized && (pMBWindow->displayedMultibuffer == BACK_BUFFER))
430 (* pMBPriv->CopyBufferBits)(pMBWindow, BACK_BUFFER, FRONT_BUFFER);
431 REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer,
432 &pMBPriv->backBuffer, &pWin->clipList);
433 (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
434 &pWin->clipList, FRONT_BUFFER);
437 /* Switch window rendering to front buffer */
438 pWin->devPrivates[frameWindowPrivateIndex] =
439 pMBPriv->frameBuffer[FRONT_BUFFER];
441 REGION_DESTROY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr);
442 pMBWindow->devPrivate.ptr = NULL;
447 * Can be replaced by pScreen->ClearToBackground if pBuffer->eventMask
448 * and wOtherEventsMasks(pBuffer) were setup.
452 bufClearImageBufferArea(pMBBuffer, x,y, w,h, generateExposures)
453 mbufBufferPtr pMBBuffer;
456 Bool generateExposures;
460 RegionPtr pBSReg = NullRegion;
466 pBuffer = (BufferPtr) pMBBuffer->pDrawable;
467 /* compute everything using ints to avoid overflow */
469 x1 = pBuffer->drawable.x + x;
470 y1 = pBuffer->drawable.y + y;
474 x2 = x1 + (int) pBuffer->drawable.width - (int) x;
478 y2 = y1 + (int) pBuffer->drawable.height - (int) y;
480 extents = &pBuffer->clipList.extents;
482 /* clip the resulting rectangle to the window clipList extents. This
483 * makes sure that the result will fit in a box, given that the
484 * screen is < 32768 on a side.
487 if (x1 < extents->x1)
489 if (x2 > extents->x2)
491 if (y1 < extents->y1)
493 if (y2 > extents->y2)
496 if (x2 <= x1 || y2 <= y1)
507 pScreen = pBuffer->drawable.pScreen;
508 REGION_INIT(pScreen, ®, &box, 1);
509 if (pBuffer->backStorage)
512 * If the window has backing-store on, call through the
513 * ClearToBackground vector to handle the special semantics
514 * (i.e. things backing store is to be cleared out and
515 * an Expose event is to be generated for those areas in backing
516 * store if generateExposures is TRUE).
518 pBSReg = (* pScreen->ClearBackingStore)(pBuffer, x, y, w, h,
522 REGION_INTERSECT(pScreen, ®, ®, &pBuffer->clipList);
523 if (pBuffer->backgroundState != None)
524 (*pScreen->PaintWindowBackground)(pBuffer, ®, PW_BACKGROUND);
525 if (generateExposures)
526 MultibufferExpose(pMBBuffer, ®);
528 /* XXBS - This is the original miClearToBackground code.
529 * WindowExposures needs to be called (or the functionality emulated)
530 * in order for backingStore to work, but first, pBuffer->eventMask
531 * and wOtherEventsMasks(pBuffer) need to be setup correctly.
534 if (generateExposures)
535 (*pScreen->WindowExposures)(pBuffer, ®, pBSReg);
536 else if (pBuffer->backgroundState != None)
537 (*pScreen->PaintWindowBackground)(pBuffer, ®, PW_BACKGROUND);
539 REGION_UNINIT(pScreen, ®);
541 REGION_DESTROY(pScreen, pBSReg);
545 bufWrapScreenFuncs(pScreen)
548 mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
550 WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree);
551 WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClipNotify, bufClipNotify);
552 WRAP_SCREEN_FUNC(pScreen,pMBPriv,WindowExposures,bufWindowExposures);
553 WRAP_SCREEN_FUNC(pScreen,pMBPriv,ChangeWindowAttributes, bufChangeWindowAttributes);
554 WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClearToBackground,bufClearToBackground);
555 WRAP_SCREEN_FUNC(pScreen,pMBPriv,CopyWindow,bufCopyWindow);
559 bufResetProc(pScreen)
562 mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
565 * frameBuffer, selectPlane, and pInfo should be freed by
566 * whoever called RegisterDoubleBufferHardware
569 REGION_UNINIT(pScreen, &pMBPriv->backBuffer);
570 REGION_UNINIT(pScreen, &pMBPriv->subtractRgn);
571 REGION_UNINIT(pScreen, &pMBPriv->unionRgn);
575 /*---------------------------------------------------------------------------*/
578 * Used if CopyBufferBitsFunc is not provided when registering.
579 * This should work for everybody since CopyArea needs to support
580 * copying between buffers anyway.
584 bufCopyBufferBits(pMBWindow, srcBufferNum, dstBufferNum)
585 mbufWindowPtr pMBWindow;
586 int srcBufferNum, dstBufferNum;
588 DrawablePtr pSrcBuffer, pDstBuffer;
591 pSrcBuffer = pMBWindow->buffers[srcBufferNum].pDrawable;
592 pDstBuffer = pMBWindow->buffers[dstBufferNum].pDrawable;
594 pGC = GetScratchGC (pDstBuffer->depth, pDstBuffer->pScreen);
598 ValidateGC (pDstBuffer, pGC);
599 (* pGC->ops->CopyArea) (pSrcBuffer, pDstBuffer, pGC,
600 0,0, pDstBuffer->width, pDstBuffer->height, 0,0);
605 * Used if DrawSelectPlanFunc is not provided for when registering.
606 * However, it only works if selectPlane.ptr is a drawable. Also
607 * assumes that painting with color 0 selects the front buffer,
608 * while color 1 selects the back buffer.
612 bufDrawSelectPlane(pScreen, selectPlane, prgn, bufferNum)
614 DevUnion selectPlane;
618 DrawablePtr pDrawable;
621 register BoxPtr pbox;
622 register xRectangle *prect;
626 if (REGION_NUM_RECTS(prgn) == 0)
629 pDrawable = (DrawablePtr) selectPlane.ptr;
630 pGC = GetScratchGC (pDrawable->depth, pScreen);
634 prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) *
642 value = (XID) bufferNum;
643 DoChangeGC(pGC, GCForeground, &value, 0);
644 ValidateGC(pDrawable, pGC);
646 numRects = REGION_NUM_RECTS(prgn);
647 pbox = REGION_RECTS(prgn);
648 for (i= numRects; --i >= 0; pbox++, prect++)
652 prect->width = pbox->x2 - pbox->x1;
653 prect->height = pbox->y2 - pbox->y1;
656 (* pGC->ops->PolyFillRect)(pDrawable, pGC, numRects, prect);
658 DEALLOCATE_LOCAL(prect);
664 bufDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf)
666 mbufBufferPtr *ppMBBuffer;
667 mbufWindowPtr *ppMBWindow;
671 BufferPtr pPrevBuffer, pNewBuffer;
673 mbufBufferPrivPtr pMBPriv;
674 mbufBufferPtr pPrevMBBuffer;
676 pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
678 for (i = 0; i < nbuf; i++)
680 number = ppMBBuffer[i]->number; /* 0=frontbuffer, 1=backbuffer */
681 pWin = ppMBWindow[i]->pWindow;
682 pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]);
684 pPrevBuffer = (BufferPtr) pPrevMBBuffer->pDrawable;
685 pNewBuffer = (BufferPtr) ppMBBuffer[i]->pDrawable;
687 if (pPrevBuffer != pNewBuffer)
689 RegionPtr backBuffer = &pMBPriv->backBuffer;
692 * Update the select plane and the backBuffer region.
695 (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
696 &pWin->clipList, number);
698 if (number == BACK_BUFFER)
699 REGION_UNION(pScreen, backBuffer, backBuffer,
702 REGION_SUBTRACT(pScreen, backBuffer, backBuffer,
705 /* Switch which framebuffer the window draws into */
706 pWin->devPrivates[frameWindowPrivateIndex] =
707 pMBPriv->frameBuffer[number];
710 switch (ppMBWindow[i]->updateAction)
712 case MultibufferUpdateActionUndefined:
714 case MultibufferUpdateActionBackground:
715 (* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea)
716 (pPrevMBBuffer, 0,0, 0,0, FALSE);
718 case MultibufferUpdateActionUntouched:
720 case MultibufferUpdateActionCopied:
721 if (pPrevBuffer != pNewBuffer)
723 (* pMBPriv->CopyBufferBits) (ppMBWindow[i],
724 ppMBBuffer[i]->number, pPrevMBBuffer->number);
731 /* Updates the backBuffer region and paints the selectPlane. */
734 bufPostValidateTree(pParent, pChild, kind)
735 WindowPtr pParent, pChild;
739 mbufBufferPrivPtr pMBPriv;
742 pScreen = pParent->drawable.pScreen;
744 pScreen = pChild->drawable.pScreen;
746 return; /* Hopeless */
748 pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
750 UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree);
751 if (pScreen->PostValidateTree)
752 (* pScreen->PostValidateTree)(pParent, pChild, kind);
753 REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree);
755 /* Does backBuffer need to change? */
756 if (pMBPriv->rgnChanged)
759 RegionPtr pSubtractRgn, pUnionRgn;
762 pMBPriv->rgnChanged = FALSE;
764 pSubtractRgn = &pMBPriv->subtractRgn;
765 pUnionRgn = &pMBPriv->unionRgn;
766 REGION_VALIDATE(pScreen, pSubtractRgn, &overlap);
769 FatalError("bufPostValidateTree: subtractRgn overlaps");
771 REGION_VALIDATE(pScreen, pUnionRgn, &overlap);
774 FatalError("bufPostValidateTree: unionRgn overlaps");
777 /* Update backBuffer: subtract must come before union */
778 REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer,
780 REGION_UNION(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer,
783 /* Paint gained and lost backbuffer areas in select plane */
784 REGION_INIT(pScreen, &exposed, NullBox, 0);
785 REGION_SUBTRACT(pScreen, &exposed, pSubtractRgn, pUnionRgn);
786 (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
787 &exposed, FRONT_BUFFER);
789 REGION_SUBTRACT(pScreen, &exposed, pUnionRgn, pSubtractRgn);
790 (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
791 &exposed, BACK_BUFFER);
793 REGION_UNINIT(pScreen, &exposed);
794 REGION_EMPTY(pScreen, pSubtractRgn);
795 REGION_EMPTY(pScreen, pUnionRgn);
799 /* XXX - Knows region internals. */
802 RegionsEqual(reg1, reg2)
807 BoxPtr rects1, rects2;
809 if (reg1->extents.x1 != reg2->extents.x1) return FALSE;
810 if (reg1->extents.x2 != reg2->extents.x2) return FALSE;
811 if (reg1->extents.y1 != reg2->extents.y1) return FALSE;
812 if (reg1->extents.y2 != reg2->extents.y2) return FALSE;
813 if (REGION_NUM_RECTS(reg1) != REGION_NUM_RECTS(reg2)) return FALSE;
815 rects1 = REGION_RECTS(reg1);
816 rects2 = REGION_RECTS(reg2);
817 for (i = 0; i != REGION_NUM_RECTS(reg1); i++) {
818 if (rects1[i].x1 != rects2[i].x1) return FALSE;
819 if (rects1[i].x2 != rects2[i].x2) return FALSE;
820 if (rects1[i].y1 != rects2[i].y1) return FALSE;
821 if (rects1[i].y2 != rects2[i].y2) return FALSE;
827 * If the window is multibuffered and displaying the backbuffer,
828 * add the old clipList to the subtractRgn and add the new clipList
829 * to the unionRgn. PostValidateTree will use subtractRgn and unionRgn
830 * to update the backBuffer region and the selectPlane.
832 * Copy changes to the window structure into the buffers.
833 * Send ClobberNotify events.
837 bufClipNotify(pWin, dx,dy)
841 ScreenPtr pScreen = pWin->drawable.pScreen;
842 mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
843 mbufWindowPtr pMBWindow;
846 UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify);
847 if (pScreen->ClipNotify)
848 (* pScreen->ClipNotify)(pWin, dx,dy);
849 REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify);
851 if (pMBWindow = MB_WINDOW_PRIV(pWin))
853 RegionPtr pOldClipList = (RegionPtr) pMBWindow->devPrivate.ptr;
855 if (! RegionsEqual(pOldClipList, &pWin->clipList))
857 if (pMBWindow->displayedMultibuffer == BACK_BUFFER)
859 pMBPriv->rgnChanged = TRUE;
860 REGION_APPEND(pScreen, &pMBPriv->subtractRgn, pOldClipList);
861 REGION_APPEND(pScreen, &pMBPriv->unionRgn, &pWin->clipList);
864 REGION_COPY(pScreen, pOldClipList,&pWin->clipList);
867 /* Update buffer x,y,w,h, and clipList */
868 for (i=0; i<pMBWindow->numMultibuffer; i++)
870 mbufBufferPtr pMBBuffer = pMBWindow->buffers + i;
871 if (pMBBuffer->clobber != pWin->visibility)
873 pMBBuffer->clobber = pWin->visibility;
874 MultibufferClobber(pMBBuffer);
876 UpdateBufferFromWindow(pMBBuffer->pDrawable, pWin);
882 * Updates buffer's background fields when the window's changes.
883 * This is necessary because pScreen->PaintWindowBackground
884 * is used to paint the buffer.
886 * XXBS - Backingstore state will have be tracked too if it is supported.
890 bufChangeWindowAttributes(pWin, mask)
894 ScreenPtr pScreen = pWin->drawable.pScreen;
895 mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
896 mbufWindowPtr pMBWindow;
899 UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes);
900 ret = (* pScreen->ChangeWindowAttributes)(pWin, mask);
901 REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes);
903 if (pMBWindow = MB_WINDOW_PRIV(pWin))
905 if (mask & (CWBackPixmap | CWBackPixel))
910 for (i=0; i<pMBWindow->displayedMultibuffer; i++)
912 pBuffer = (BufferPtr) pMBWindow->buffers[i].pDrawable;
913 pBuffer->backgroundState = pWin->backgroundState;
914 pBuffer->background = pWin->background;
922 * Send exposures and clear the background for a buffer whenever
923 * its corresponding window is exposed, except when called by
928 bufWindowExposures(pWin, prgn, other_exposed)
930 register RegionPtr prgn, other_exposed;
932 ScreenPtr pScreen = pWin->drawable.pScreen;
933 mbufWindowPtr pMBWindow = MB_WINDOW_PRIV(pWin);
934 mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
939 handleBuffers = (!pMBPriv->inClearToBackground) &&
940 (pWin->drawable.type == DRAWABLE_WINDOW) &&
941 pMBWindow && (prgn && !REGION_NIL(prgn));
943 /* miWindowExposures munges prgn and other_exposed. */
946 REGION_INIT(pScreen, &tmp_rgn, NullBox, 0);
947 REGION_COPY(pScreen, &tmp_rgn,prgn);
950 UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures);
951 (* pScreen->WindowExposures) (pWin, prgn, other_exposed);
952 REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures);
958 * Send expose events to all clients. Paint the exposed region for all
959 * buffers except the displayed buffer since it is handled when the
962 * XXBS - Will have to be re-written to handle BackingStore on buffers.
965 for (i=0; i<pMBWindow->numMultibuffer; i++)
967 mbufBufferPtr pMBBuffer;
970 pMBBuffer = pMBWindow->buffers + i;
971 pBuffer = (BufferPtr) pMBBuffer->pDrawable;
973 if (i != pMBWindow->displayedMultibuffer)
974 (* pScreen->PaintWindowBackground)(pBuffer,&tmp_rgn,PW_BACKGROUND);
975 if ((pMBBuffer->otherEventMask | pMBBuffer->eventMask) & ExposureMask)
976 MultibufferExpose(pMBBuffer, &tmp_rgn);
979 REGION_UNINIT(pScreen, &tmp_rgn);
983 * Set ``inClearToBackground'' so that WindowExposures does not attempt
984 * to send expose events or clear the background on the buffers.
988 bufClearToBackground(pWin, x,y,w,h, sendExpose)
993 ScreenPtr pScreen = pWin->drawable.pScreen;
994 mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
996 pMBPriv->inClearToBackground = TRUE;
998 UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground);
999 (* pScreen->ClearToBackground)(pWin, x,y,w,h, sendExpose);
1000 REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground);
1002 pMBPriv->inClearToBackground = FALSE;
1006 * Move bits in both buffers. It does this by calling pScreen->CopyWindow
1007 * twice, once with the root window's devPrivate[frameWindowPrivateIndex]
1008 * pointing to the frontbuffer pixmap and once with it pointed to the
1009 * backbuffer pixmap. It does this if there are *any* existing multibuffered
1010 * window... a possible optimization is to copy the backbuffer only if this
1011 * window or its inferiors are multibuffered. May be faster, maybe not.
1013 * XXX - Only works if your CopyWindow checks the root window's devPrivate
1014 * to see which buffer to draw into. Works for cfbPaintWindow.
1019 bufCopyWindow(pWin, ptOldOrg, prgnSrc)
1021 DDXPointRec ptOldOrg;
1024 ScreenPtr pScreen = pWin->drawable.pScreen;
1025 mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
1029 UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow);
1031 pwinroot = WindowTable[pScreen->myNum];
1032 save = pwinroot->devPrivates[frameWindowPrivateIndex];
1038 pwinroot->devPrivates[frameWindowPrivateIndex] =
1039 pMBPriv->frameBuffer[FRONT_BUFFER];
1040 (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
1046 /* CopyWindow translates prgnSrc... translate it back for 2nd call. */
1047 REGION_TRANSLATE(pScreen, prgnSrc,
1048 ptOldOrg.x - pWin->drawable.x,
1049 ptOldOrg.y - pWin->drawable.y);
1050 pwinroot->devPrivates[frameWindowPrivateIndex] =
1051 pMBPriv->frameBuffer[BACK_BUFFER];
1052 (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
1054 pwinroot->devPrivates[frameWindowPrivateIndex] = save;
1055 REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow);