3 Copyright 1989, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
30 #ifdef HAVE_DIX_CONFIG_H
31 #include <dix-config.h>
36 #include <X11/Xproto.h>
39 #include "windowstr.h"
40 #include "scrnintstr.h"
41 #include "pixmapstr.h"
42 #include "extnsionst.h"
43 #include "dixstruct.h"
46 #include "regionstr.h"
52 #define _MULTIBUF_SERVER_ /* don't want Xlib structures */
53 #define _MULTIBUF_BUFFER_
54 #include <X11/extensions/multibufst.h>
57 Support for doublebuffer hardare
59 This code is designed to support doublebuffer hardware where the
60 displayed buffer is selected on a per-pixel basis by an additional bit
61 plane, called the select plane. It could probably be easily modified
62 to work with systems that use window-id planes.
64 This is done by creating a new drawable type, DRAWABLE_BUFFER. The
65 type has the same exact layout as a window drawable. Your code should
66 treat a DRAWABLE_BUFFER the same as it would tread a DRAWABLE_WINDOW
67 when handling the gc drawing functions. In addition, PaintWindowBackground,
68 CopyWindow, and all of the gc drawing functions to be able to draw into both
69 framebuffers. Which framebuffer to draw into is selected by the contents of
70 pWin->devPrivates[frameWindowPrivateIndex].
71 The content of the devPrivate is either from frameBuffer[0] or
72 frameBuffer[1], depending on which buffer is being drawn into. When
73 pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[0],
74 the functions should draw into the front framebuffer. When
75 pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[1],
76 the functions should draw into the back framebuffer.
78 In addition, you need to provide a function that allows you to copy
79 bits between the buffers (optional since CopyArea can be used) and a
80 function that draws into the select plane. Then, you need to register
81 your functions and other information, by calling:
84 RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
85 CopyBufferBitsFunc, DrawSelectPlaneFunc)
87 xMbufBufferInfo *pInfo;
88 DevUnion *frameBuffer;
91 "pInfo" is an array indicating which visuals and depths that double
92 buffering is supported on. "nInfo" is the length of the array.
94 "frameBuffer" is array of length 2. The contents of the array element
95 is ddx-specific. The content of frameBuffer[0] should, when placed in
96 the window private, indicate that framebuffer 0 should be drawn into.
97 The contents of frameBuffer[1], when placed into the window private,
98 should indicate that framebuffer 1 should be drawn into.
100 "selectPlane" is ddx-specific. It should contain information
101 neccessary for your displayProc to access the select plane.
102 It is passed to DrawSelectPlaneFunc.
104 "CopyBufferBitsFunc" is a ddx-specific function that copies from one
105 buffer of a multibuffered window to another buffer. If the CopyBufferBitsFunc
106 is NULL, a default function will be used that calls pScreen->CopyArea.
108 void CopyBufferBitsFunc(pMBWindow, srcBufferNum, dstBufferNum)
109 mbufWindowPtr pMBWindow;
110 int srcBufferNum, dstBufferNum;
112 "DrawSelectPlaneFunc" is a ddx-specific function that fills the
113 regions "prgn" of select plane with the value "bufferNum". If
114 selectPlane is a DrawablePtr (such as a PixmapPtr), you can pass
115 NULL for DrawSelectPlaneFunc, a default function will be used that
116 calls FillRectangle on the selectPlane.
118 void DrawSelectPlaneFunc(pScreen, selectPlane, prgn, bufferNum)
120 DevUnion selectPlane;
130 #define MAX_BUFFERS 2 /* Only supports 2 buffers */
131 #define FRONT_BUFFER 0
132 #define BACK_BUFFER 1
135 /* Buffer drawables have the same structure as window drawables */
136 typedef WindowRec BufferRec
;
137 typedef WindowPtr BufferPtr
;
141 * Call RegisterHdwrBuffer for every screen that has doublebuffer hardware.
144 static int bufNumInfo
[MAXSCREENS
];
145 static xMbufBufferInfo
*bufInfo
[MAXSCREENS
];
146 static DevUnion
*bufFrameBuffer
[MAXSCREENS
];
147 static DevUnion bufselectPlane
[MAXSCREENS
];
148 static void (* bufCopyBufferBitsFunc
[MAXSCREENS
])();
149 static void (* bufDrawSelectPlaneFunc
[MAXSCREENS
])();
151 static Bool
bufMultibufferInit();
155 RegisterDoubleBufferHardware(pScreen
, nInfo
, pInfo
, frameBuffer
, selectPlane
,
156 CopyBufferBitsFunc
, DrawSelectPlaneFunc
)
159 xMbufBufferInfo
*pInfo
;
160 DevUnion
*frameBuffer
;
161 DevUnion selectPlane
;
162 void (* CopyBufferBitsFunc
)();
163 void (* DrawSelectPlaneFunc
)();
165 bufNumInfo
[pScreen
->myNum
] = nInfo
;
166 bufInfo
[pScreen
->myNum
] = pInfo
;
167 bufFrameBuffer
[pScreen
->myNum
] = frameBuffer
;
168 bufselectPlane
[pScreen
->myNum
] = selectPlane
;
170 bufCopyBufferBitsFunc
[pScreen
->myNum
] = CopyBufferBitsFunc
;
171 bufDrawSelectPlaneFunc
[pScreen
->myNum
] = DrawSelectPlaneFunc
;
173 /* Register ourselves with device-independent multibuffers code */
174 RegisterMultibufferInit(pScreen
, bufMultibufferInit
);
179 * Called by Multibuffer extension initialization.
180 * Initializes mbufScreenRec and its devPrivate.
183 static Bool
NoopDDA_True() { return TRUE
; }
184 static Bool
bufPositionWindow();
185 static int bufCreateImageBuffers();
186 static void bufDestroyImageBuffers();
187 static void bufDisplayImageBuffers();
188 static void bufClearImageBufferArea();
189 static void bufDestroyBuffer();
190 static void bufCopyBufferBits();
191 static void bufDrawSelectPlane();
192 static void bufWrapScreenFuncs();
193 static void bufResetProc();
195 static void bufPostValidateTree();
196 static void bufClipNotify();
197 static void bufWindowExposures();
198 static Bool
bufChangeWindowAttributes();
199 static void bufClearToBackground();
200 static void bufCopyWindow();
202 extern WindowPtr
*WindowTable
;
205 bufMultibufferInit(pScreen
, pMBScreen
)
207 mbufScreenPtr pMBScreen
;
209 mbufBufferPrivPtr pMBPriv
;
212 /* Multibuffer info */
213 pMBScreen
->nInfo
= bufNumInfo
[pScreen
->myNum
];
214 pMBScreen
->pInfo
= bufInfo
[pScreen
->myNum
];
217 pMBScreen
->CreateImageBuffers
= bufCreateImageBuffers
;
218 pMBScreen
->DestroyImageBuffers
= bufDestroyImageBuffers
;
219 pMBScreen
->DisplayImageBuffers
= bufDisplayImageBuffers
;
220 pMBScreen
->ClearImageBufferArea
= bufClearImageBufferArea
;
221 pMBScreen
->ChangeMBufferAttributes
= NoopDDA_True
;
222 pMBScreen
->ChangeBufferAttributes
= NoopDDA_True
;
223 pMBScreen
->DeleteBufferDrawable
= bufDestroyBuffer
;
224 pMBScreen
->WrapScreenFuncs
= bufWrapScreenFuncs
;
225 pMBScreen
->ResetProc
= bufResetProc
;
226 /* Create devPrivate part */
227 pMBPriv
= (mbufBufferPrivPtr
) xalloc(sizeof *pMBPriv
);
231 pMBScreen
->devPrivate
.ptr
= (pointer
) pMBPriv
;
232 pMBPriv
->frameBuffer
= bufFrameBuffer
[pScreen
->myNum
];
233 pMBPriv
->selectPlane
= bufselectPlane
[pScreen
->myNum
];
236 * Initializing the subtractRgn to the screen area will ensure that
237 * the selectPlane will get cleared on the first PostValidateTree.
242 box
.x2
= pScreen
->width
;
243 box
.y2
= pScreen
->height
;
245 pMBPriv
->rgnChanged
= TRUE
;
246 REGION_INIT(pScreen
, &pMBPriv
->backBuffer
, &box
, 1);
247 REGION_INIT(pScreen
, &pMBPriv
->subtractRgn
, &box
, 1);
248 REGION_NULL(pScreen
, &pMBPriv
->unionRgn
);
251 pMBPriv
->CopyBufferBits
= bufCopyBufferBitsFunc
[pScreen
->myNum
];
252 pMBPriv
->DrawSelectPlane
= bufDrawSelectPlaneFunc
[pScreen
->myNum
];
254 if (!pMBPriv
->CopyBufferBits
)
255 pMBPriv
->CopyBufferBits
= bufCopyBufferBits
;
257 if (!pMBPriv
->DrawSelectPlane
)
258 pMBPriv
->DrawSelectPlane
= bufDrawSelectPlane
;
260 /* screen functions */
261 pMBPriv
->funcsWrapped
= 0;
262 pMBPriv
->inClearToBackground
= FALSE
;
263 pMBPriv
->WindowExposures
= NULL
;
264 pMBPriv
->CopyWindow
= NULL
;
265 pMBPriv
->ClearToBackground
= NULL
;
266 pMBPriv
->ClipNotify
= NULL
;
267 pMBPriv
->ChangeWindowAttributes
= NULL
;
269 /* Start out wrapped to clear select plane */
270 WRAP_SCREEN_FUNC(pScreen
,pMBPriv
,PostValidateTree
, bufPostValidateTree
);
275 UpdateBufferFromWindow(pBuffer
, pWin
)
279 pBuffer
->drawable
.x
= pWin
->drawable
.x
;
280 pBuffer
->drawable
.y
= pWin
->drawable
.y
;
281 pBuffer
->drawable
.width
= pWin
->drawable
.width
;
282 pBuffer
->drawable
.height
= pWin
->drawable
.height
;
284 pBuffer
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
286 /* Update for PaintWindowBackground */
287 pBuffer
->parent
= pWin
->parent
;
290 * Make the borderClip the same as the clipList so
291 * NotClippedByChildren comes out with just clipList.
294 pBuffer
->clipList
= pWin
->clipList
;
295 pBuffer
->borderClip
= pWin
->clipList
;
296 pBuffer
->winSize
= pWin
->winSize
;
297 pBuffer
->borderSize
= pWin
->borderSize
;
299 pBuffer
->origin
= pWin
->origin
;
303 bufCreateBuffer(pScreen
, pWin
, bufferNum
)
308 mbufBufferPrivPtr pMBPriv
;
309 DevUnion
*devPrivates
;
313 pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
315 pBuffer
= AllocateWindow(pWin
->drawable
.pScreen
);
319 /* XXX- Until we know what is needed, copy everything. */
320 devPrivates
= pBuffer
->devPrivates
;
322 pBuffer
->devPrivates
= devPrivates
;
324 pBuffer
->drawable
.type
= DRAWABLE_BUFFER
;
325 pBuffer
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
327 pBuffer
->nextSib
= NULL
;
328 pBuffer
->prevSib
= NULL
;
329 pBuffer
->firstChild
= NULL
;
330 pBuffer
->lastChild
= NULL
;
332 /* XXX - Worry about backingstore later */
333 pBuffer
->backStorage
= NULL
;
334 pBuffer
->backingStore
= NotUseful
;
336 /* XXX - Need to call pScreen->CreateWindow for tile/stipples
337 * or should I just copy the devPrivates?
340 for (i
=0; i
< pScreen
->WindowPrivateLen
; i
++)
341 pBuffer
->devPrivates
[i
] = pWin
->devPrivates
[i
];
343 pBuffer
->devPrivates
[frameWindowPrivateIndex
] =
344 pMBPriv
->frameBuffer
[bufferNum
];
350 bufDestroyBuffer(pDrawable
)
351 DrawablePtr pDrawable
;
358 bufCreateImageBuffers (pWin
, nbuf
, ids
, action
, hint
)
366 mbufScreenPtr pMBScreen
;
367 mbufWindowPtr pMBWindow
;
368 mbufBufferPtr pMBBuffer
;
371 pScreen
= pWin
->drawable
.pScreen
;
372 pMBScreen
= MB_SCREEN_PRIV(pScreen
);
373 pMBWindow
= MB_WINDOW_PRIV(pWin
);
375 pMBWindow
->devPrivate
.ptr
= (pointer
) REGION_CREATE(pScreen
, 0,0);
376 if (!pMBWindow
->devPrivate
.ptr
)
378 REGION_COPY(pScreen
, (RegionPtr
) pMBWindow
->devPrivate
.ptr
,
381 for (i
= 0; i
< nbuf
; i
++)
383 pMBBuffer
= pMBWindow
->buffers
+ i
;
384 pMBBuffer
->pDrawable
= (DrawablePtr
) bufCreateBuffer(pScreen
,pWin
,i
);
386 if (!pMBBuffer
->pDrawable
)
389 if (!AddResource (ids
[i
], MultibufferDrawableResType
,
390 (pointer
) pMBBuffer
->pDrawable
))
392 bufDestroyBuffer((BufferPtr
) pMBBuffer
->pDrawable
);
395 pMBBuffer
->pDrawable
->id
= ids
[i
];
398 * If window is already mapped, generate exposures and
399 * clear the area of the newly buffers.
402 if ((pWin
->realized
) && (i
!= pMBWindow
->displayedMultibuffer
))
403 (* pMBScreen
->ClearImageBufferArea
)(pMBBuffer
, 0,0, 0,0, TRUE
);
410 bufDestroyImageBuffers(pWin
)
414 mbufWindowPtr pMBWindow
;
416 pScreen
= pWin
->drawable
.pScreen
;
418 if (pMBWindow
= MB_WINDOW_PRIV(pWin
))
420 mbufBufferPrivPtr pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
423 * if the backbuffer is currently being displayed, move the bits
424 * to the frontbuffer and display it instead.
427 if (pWin
->realized
&& (pMBWindow
->displayedMultibuffer
== BACK_BUFFER
))
429 (* pMBPriv
->CopyBufferBits
)(pMBWindow
, BACK_BUFFER
, FRONT_BUFFER
);
430 REGION_SUBTRACT(pScreen
, &pMBPriv
->backBuffer
,
431 &pMBPriv
->backBuffer
, &pWin
->clipList
);
432 (* pMBPriv
->DrawSelectPlane
)(pScreen
, pMBPriv
->selectPlane
,
433 &pWin
->clipList
, FRONT_BUFFER
);
436 /* Switch window rendering to front buffer */
437 pWin
->devPrivates
[frameWindowPrivateIndex
] =
438 pMBPriv
->frameBuffer
[FRONT_BUFFER
];
440 REGION_DESTROY(pScreen
, (RegionPtr
) pMBWindow
->devPrivate
.ptr
);
441 pMBWindow
->devPrivate
.ptr
= NULL
;
446 * Can be replaced by pScreen->ClearToBackground if pBuffer->eventMask
447 * and wOtherEventsMasks(pBuffer) were setup.
451 bufClearImageBufferArea(pMBBuffer
, x
,y
, w
,h
, generateExposures
)
452 mbufBufferPtr pMBBuffer
;
455 Bool generateExposures
;
459 RegionPtr pBSReg
= NullRegion
;
465 pBuffer
= (BufferPtr
) pMBBuffer
->pDrawable
;
466 /* compute everything using ints to avoid overflow */
468 x1
= pBuffer
->drawable
.x
+ x
;
469 y1
= pBuffer
->drawable
.y
+ y
;
473 x2
= x1
+ (int) pBuffer
->drawable
.width
- (int) x
;
477 y2
= y1
+ (int) pBuffer
->drawable
.height
- (int) y
;
479 extents
= &pBuffer
->clipList
.extents
;
481 /* clip the resulting rectangle to the window clipList extents. This
482 * makes sure that the result will fit in a box, given that the
483 * screen is < 32768 on a side.
486 if (x1
< extents
->x1
)
488 if (x2
> extents
->x2
)
490 if (y1
< extents
->y1
)
492 if (y2
> extents
->y2
)
495 if (x2
<= x1
|| y2
<= y1
)
506 pScreen
= pBuffer
->drawable
.pScreen
;
507 REGION_INIT(pScreen
, ®
, &box
, 1);
508 if (pBuffer
->backStorage
)
511 * If the window has backing-store on, call through the
512 * ClearToBackground vector to handle the special semantics
513 * (i.e. things backing store is to be cleared out and
514 * an Expose event is to be generated for those areas in backing
515 * store if generateExposures is TRUE).
517 pBSReg
= (* pScreen
->ClearBackingStore
)(pBuffer
, x
, y
, w
, h
,
521 REGION_INTERSECT(pScreen
, ®
, ®
, &pBuffer
->clipList
);
522 if (pBuffer
->backgroundState
!= None
)
523 (*pScreen
->PaintWindowBackground
)(pBuffer
, ®
, PW_BACKGROUND
);
524 if (generateExposures
)
525 MultibufferExpose(pMBBuffer
, ®
);
527 /* XXBS - This is the original miClearToBackground code.
528 * WindowExposures needs to be called (or the functionality emulated)
529 * in order for backingStore to work, but first, pBuffer->eventMask
530 * and wOtherEventsMasks(pBuffer) need to be setup correctly.
533 if (generateExposures
)
534 (*pScreen
->WindowExposures
)(pBuffer
, ®
, pBSReg
);
535 else if (pBuffer
->backgroundState
!= None
)
536 (*pScreen
->PaintWindowBackground
)(pBuffer
, ®
, PW_BACKGROUND
);
538 REGION_UNINIT(pScreen
, ®
);
540 REGION_DESTROY(pScreen
, pBSReg
);
544 bufWrapScreenFuncs(pScreen
)
547 mbufBufferPrivPtr pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
549 WRAP_SCREEN_FUNC(pScreen
,pMBPriv
,PostValidateTree
, bufPostValidateTree
);
550 WRAP_SCREEN_FUNC(pScreen
,pMBPriv
,ClipNotify
, bufClipNotify
);
551 WRAP_SCREEN_FUNC(pScreen
,pMBPriv
,WindowExposures
,bufWindowExposures
);
552 WRAP_SCREEN_FUNC(pScreen
,pMBPriv
,ChangeWindowAttributes
, bufChangeWindowAttributes
);
553 WRAP_SCREEN_FUNC(pScreen
,pMBPriv
,ClearToBackground
,bufClearToBackground
);
554 WRAP_SCREEN_FUNC(pScreen
,pMBPriv
,CopyWindow
,bufCopyWindow
);
558 bufResetProc(pScreen
)
561 mbufBufferPrivPtr pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
564 * frameBuffer, selectPlane, and pInfo should be freed by
565 * whoever called RegisterDoubleBufferHardware
568 REGION_UNINIT(pScreen
, &pMBPriv
->backBuffer
);
569 REGION_UNINIT(pScreen
, &pMBPriv
->subtractRgn
);
570 REGION_UNINIT(pScreen
, &pMBPriv
->unionRgn
);
574 /*---------------------------------------------------------------------------*/
577 * Used if CopyBufferBitsFunc is not provided when registering.
578 * This should work for everybody since CopyArea needs to support
579 * copying between buffers anyway.
583 bufCopyBufferBits(pMBWindow
, srcBufferNum
, dstBufferNum
)
584 mbufWindowPtr pMBWindow
;
585 int srcBufferNum
, dstBufferNum
;
587 DrawablePtr pSrcBuffer
, pDstBuffer
;
590 pSrcBuffer
= pMBWindow
->buffers
[srcBufferNum
].pDrawable
;
591 pDstBuffer
= pMBWindow
->buffers
[dstBufferNum
].pDrawable
;
593 pGC
= GetScratchGC (pDstBuffer
->depth
, pDstBuffer
->pScreen
);
597 ValidateGC (pDstBuffer
, pGC
);
598 (* pGC
->ops
->CopyArea
) (pSrcBuffer
, pDstBuffer
, pGC
,
599 0,0, pDstBuffer
->width
, pDstBuffer
->height
, 0,0);
604 * Used if DrawSelectPlanFunc is not provided for when registering.
605 * However, it only works if selectPlane.ptr is a drawable. Also
606 * assumes that painting with color 0 selects the front buffer,
607 * while color 1 selects the back buffer.
611 bufDrawSelectPlane(pScreen
, selectPlane
, prgn
, bufferNum
)
613 DevUnion selectPlane
;
617 DrawablePtr pDrawable
;
620 register BoxPtr pbox
;
621 register xRectangle
*prect
;
625 if (REGION_NUM_RECTS(prgn
) == 0)
628 pDrawable
= (DrawablePtr
) selectPlane
.ptr
;
629 pGC
= GetScratchGC (pDrawable
->depth
, pScreen
);
633 prect
= (xRectangle
*)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn
) *
641 value
= (XID
) bufferNum
;
642 DoChangeGC(pGC
, GCForeground
, &value
, 0);
643 ValidateGC(pDrawable
, pGC
);
645 numRects
= REGION_NUM_RECTS(prgn
);
646 pbox
= REGION_RECTS(prgn
);
647 for (i
= numRects
; --i
>= 0; pbox
++, prect
++)
651 prect
->width
= pbox
->x2
- pbox
->x1
;
652 prect
->height
= pbox
->y2
- pbox
->y1
;
655 (* pGC
->ops
->PolyFillRect
)(pDrawable
, pGC
, numRects
, prect
);
657 DEALLOCATE_LOCAL(prect
);
663 bufDisplayImageBuffers(pScreen
, ppMBWindow
, ppMBBuffer
, nbuf
)
665 mbufBufferPtr
*ppMBBuffer
;
666 mbufWindowPtr
*ppMBWindow
;
670 BufferPtr pPrevBuffer
, pNewBuffer
;
672 mbufBufferPrivPtr pMBPriv
;
673 mbufBufferPtr pPrevMBBuffer
;
675 pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
677 for (i
= 0; i
< nbuf
; i
++)
679 number
= ppMBBuffer
[i
]->number
; /* 0=frontbuffer, 1=backbuffer */
680 pWin
= ppMBWindow
[i
]->pWindow
;
681 pPrevMBBuffer
= MB_DISPLAYED_BUFFER(ppMBWindow
[i
]);
683 pPrevBuffer
= (BufferPtr
) pPrevMBBuffer
->pDrawable
;
684 pNewBuffer
= (BufferPtr
) ppMBBuffer
[i
]->pDrawable
;
686 if (pPrevBuffer
!= pNewBuffer
)
688 RegionPtr backBuffer
= &pMBPriv
->backBuffer
;
691 * Update the select plane and the backBuffer region.
694 (* pMBPriv
->DrawSelectPlane
)(pScreen
, pMBPriv
->selectPlane
,
695 &pWin
->clipList
, number
);
697 if (number
== BACK_BUFFER
)
698 REGION_UNION(pScreen
, backBuffer
, backBuffer
,
701 REGION_SUBTRACT(pScreen
, backBuffer
, backBuffer
,
704 /* Switch which framebuffer the window draws into */
705 pWin
->devPrivates
[frameWindowPrivateIndex
] =
706 pMBPriv
->frameBuffer
[number
];
709 switch (ppMBWindow
[i
]->updateAction
)
711 case MultibufferUpdateActionUndefined
:
713 case MultibufferUpdateActionBackground
:
714 (* MB_SCREEN_PRIV(pScreen
)->ClearImageBufferArea
)
715 (pPrevMBBuffer
, 0,0, 0,0, FALSE
);
717 case MultibufferUpdateActionUntouched
:
719 case MultibufferUpdateActionCopied
:
720 if (pPrevBuffer
!= pNewBuffer
)
722 (* pMBPriv
->CopyBufferBits
) (ppMBWindow
[i
],
723 ppMBBuffer
[i
]->number
, pPrevMBBuffer
->number
);
730 /* Updates the backBuffer region and paints the selectPlane. */
733 bufPostValidateTree(pParent
, pChild
, kind
)
734 WindowPtr pParent
, pChild
;
738 mbufBufferPrivPtr pMBPriv
;
741 pScreen
= pParent
->drawable
.pScreen
;
743 pScreen
= pChild
->drawable
.pScreen
;
745 return; /* Hopeless */
747 pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
749 UNWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, PostValidateTree
);
750 if (pScreen
->PostValidateTree
)
751 (* pScreen
->PostValidateTree
)(pParent
, pChild
, kind
);
752 REWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, PostValidateTree
);
754 /* Does backBuffer need to change? */
755 if (pMBPriv
->rgnChanged
)
758 RegionPtr pSubtractRgn
, pUnionRgn
;
761 pMBPriv
->rgnChanged
= FALSE
;
763 pSubtractRgn
= &pMBPriv
->subtractRgn
;
764 pUnionRgn
= &pMBPriv
->unionRgn
;
765 REGION_VALIDATE(pScreen
, pSubtractRgn
, &overlap
);
768 FatalError("bufPostValidateTree: subtractRgn overlaps");
770 REGION_VALIDATE(pScreen
, pUnionRgn
, &overlap
);
773 FatalError("bufPostValidateTree: unionRgn overlaps");
776 /* Update backBuffer: subtract must come before union */
777 REGION_SUBTRACT(pScreen
, &pMBPriv
->backBuffer
, &pMBPriv
->backBuffer
,
779 REGION_UNION(pScreen
, &pMBPriv
->backBuffer
, &pMBPriv
->backBuffer
,
782 /* Paint gained and lost backbuffer areas in select plane */
783 REGION_NULL(pScreen
, &exposed
);
784 REGION_SUBTRACT(pScreen
, &exposed
, pSubtractRgn
, pUnionRgn
);
785 (* pMBPriv
->DrawSelectPlane
)(pScreen
, pMBPriv
->selectPlane
,
786 &exposed
, FRONT_BUFFER
);
788 REGION_SUBTRACT(pScreen
, &exposed
, pUnionRgn
, pSubtractRgn
);
789 (* pMBPriv
->DrawSelectPlane
)(pScreen
, pMBPriv
->selectPlane
,
790 &exposed
, BACK_BUFFER
);
792 REGION_UNINIT(pScreen
, &exposed
);
793 REGION_EMPTY(pScreen
, pSubtractRgn
);
794 REGION_EMPTY(pScreen
, pUnionRgn
);
799 * If the window is multibuffered and displaying the backbuffer,
800 * add the old clipList to the subtractRgn and add the new clipList
801 * to the unionRgn. PostValidateTree will use subtractRgn and unionRgn
802 * to update the backBuffer region and the selectPlane.
804 * Copy changes to the window structure into the buffers.
805 * Send ClobberNotify events.
809 bufClipNotify(pWin
, dx
,dy
)
813 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
814 mbufBufferPrivPtr pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
815 mbufWindowPtr pMBWindow
;
818 UNWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, ClipNotify
);
819 if (pScreen
->ClipNotify
)
820 (* pScreen
->ClipNotify
)(pWin
, dx
,dy
);
821 REWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, ClipNotify
);
823 if (pMBWindow
= MB_WINDOW_PRIV(pWin
))
825 RegionPtr pOldClipList
= (RegionPtr
) pMBWindow
->devPrivate
.ptr
;
827 if (! REGION_EQUAL(pScreen
, pOldClipList
, &pWin
->clipList
))
829 if (pMBWindow
->displayedMultibuffer
== BACK_BUFFER
)
831 pMBPriv
->rgnChanged
= TRUE
;
832 REGION_APPEND(pScreen
, &pMBPriv
->subtractRgn
, pOldClipList
);
833 REGION_APPEND(pScreen
, &pMBPriv
->unionRgn
, &pWin
->clipList
);
836 REGION_COPY(pScreen
, pOldClipList
,&pWin
->clipList
);
839 /* Update buffer x,y,w,h, and clipList */
840 for (i
=0; i
<pMBWindow
->numMultibuffer
; i
++)
842 mbufBufferPtr pMBBuffer
= pMBWindow
->buffers
+ i
;
843 if (pMBBuffer
->clobber
!= pWin
->visibility
)
845 pMBBuffer
->clobber
= pWin
->visibility
;
846 MultibufferClobber(pMBBuffer
);
848 UpdateBufferFromWindow(pMBBuffer
->pDrawable
, pWin
);
854 * Updates buffer's background fields when the window's changes.
855 * This is necessary because pScreen->PaintWindowBackground
856 * is used to paint the buffer.
858 * XXBS - Backingstore state will have be tracked too if it is supported.
862 bufChangeWindowAttributes(pWin
, mask
)
866 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
867 mbufBufferPrivPtr pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
868 mbufWindowPtr pMBWindow
;
871 UNWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, Bool
, ChangeWindowAttributes
);
872 ret
= (* pScreen
->ChangeWindowAttributes
)(pWin
, mask
);
873 REWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, Bool
, ChangeWindowAttributes
);
875 if (pMBWindow
= MB_WINDOW_PRIV(pWin
))
877 if (mask
& (CWBackPixmap
| CWBackPixel
))
882 for (i
=0; i
<pMBWindow
->displayedMultibuffer
; i
++)
884 pBuffer
= (BufferPtr
) pMBWindow
->buffers
[i
].pDrawable
;
885 pBuffer
->backgroundState
= pWin
->backgroundState
;
886 pBuffer
->background
= pWin
->background
;
894 * Send exposures and clear the background for a buffer whenever
895 * its corresponding window is exposed, except when called by
900 bufWindowExposures(pWin
, prgn
, other_exposed
)
902 register RegionPtr prgn
, other_exposed
;
904 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
905 mbufWindowPtr pMBWindow
= MB_WINDOW_PRIV(pWin
);
906 mbufBufferPrivPtr pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
911 handleBuffers
= (!pMBPriv
->inClearToBackground
) &&
912 (pWin
->drawable
.type
== DRAWABLE_WINDOW
) &&
913 pMBWindow
&& (prgn
&& !REGION_NIL(prgn
));
915 /* miWindowExposures munges prgn and other_exposed. */
918 REGION_NULL(pScreen
, &tmp_rgn
);
919 REGION_COPY(pScreen
, &tmp_rgn
, prgn
);
922 UNWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, WindowExposures
);
923 (* pScreen
->WindowExposures
) (pWin
, prgn
, other_exposed
);
924 REWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, WindowExposures
);
930 * Send expose events to all clients. Paint the exposed region for all
931 * buffers except the displayed buffer since it is handled when the
934 * XXBS - Will have to be re-written to handle BackingStore on buffers.
937 for (i
=0; i
<pMBWindow
->numMultibuffer
; i
++)
939 mbufBufferPtr pMBBuffer
;
942 pMBBuffer
= pMBWindow
->buffers
+ i
;
943 pBuffer
= (BufferPtr
) pMBBuffer
->pDrawable
;
945 if (i
!= pMBWindow
->displayedMultibuffer
)
946 (* pScreen
->PaintWindowBackground
)(pBuffer
,&tmp_rgn
,PW_BACKGROUND
);
947 if ((pMBBuffer
->otherEventMask
| pMBBuffer
->eventMask
) & ExposureMask
)
948 MultibufferExpose(pMBBuffer
, &tmp_rgn
);
951 REGION_UNINIT(pScreen
, &tmp_rgn
);
955 * Set ``inClearToBackground'' so that WindowExposures does not attempt
956 * to send expose events or clear the background on the buffers.
960 bufClearToBackground(pWin
, x
,y
,w
,h
, sendExpose
)
965 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
966 mbufBufferPrivPtr pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
968 pMBPriv
->inClearToBackground
= TRUE
;
970 UNWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, ClearToBackground
);
971 (* pScreen
->ClearToBackground
)(pWin
, x
,y
,w
,h
, sendExpose
);
972 REWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, ClearToBackground
);
974 pMBPriv
->inClearToBackground
= FALSE
;
978 * Move bits in both buffers. It does this by calling pScreen->CopyWindow
979 * twice, once with the root window's devPrivate[frameWindowPrivateIndex]
980 * pointing to the frontbuffer pixmap and once with it pointed to the
981 * backbuffer pixmap. It does this if there are *any* existing multibuffered
982 * window... a possible optimization is to copy the backbuffer only if this
983 * window or its inferiors are multibuffered. May be faster, maybe not.
985 * XXX - Only works if your CopyWindow checks the root window's devPrivate
986 * to see which buffer to draw into. Works for cfbPaintWindow.
991 bufCopyWindow(pWin
, ptOldOrg
, prgnSrc
)
993 DDXPointRec ptOldOrg
;
996 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
997 mbufBufferPrivPtr pMBPriv
= MB_SCREEN_PRIV_BUFFER(pScreen
);
1001 UNWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, CopyWindow
);
1003 pwinroot
= WindowTable
[pScreen
->myNum
];
1004 save
= pwinroot
->devPrivates
[frameWindowPrivateIndex
];
1010 pwinroot
->devPrivates
[frameWindowPrivateIndex
] =
1011 pMBPriv
->frameBuffer
[FRONT_BUFFER
];
1012 (* pScreen
->CopyWindow
)(pWin
, ptOldOrg
, prgnSrc
);
1018 /* CopyWindow translates prgnSrc... translate it back for 2nd call. */
1019 REGION_TRANSLATE(pScreen
, prgnSrc
,
1020 ptOldOrg
.x
- pWin
->drawable
.x
,
1021 ptOldOrg
.y
- pWin
->drawable
.y
);
1022 pwinroot
->devPrivates
[frameWindowPrivateIndex
] =
1023 pMBPriv
->frameBuffer
[BACK_BUFFER
];
1024 (* pScreen
->CopyWindow
)(pWin
, ptOldOrg
, prgnSrc
);
1026 pwinroot
->devPrivates
[frameWindowPrivateIndex
] = save
;
1027 REWRAP_SCREEN_FUNC(pScreen
, pMBPriv
, void, CopyWindow
);