1
/* $XFree86: xc/programs/Xserver/Xext/mbufbf.c,v 3.5tsi Exp $ */
4
Copyright 1989, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
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
OPEN GROUP 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 Open Group 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 Open Group.
28
/* $Xorg: mbufbf.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
32
#ifdef HAVE_DIX_CONFIG_H
33
#include <dix-config.h>
38
#include <X11/Xproto.h>
41
#include "windowstr.h"
42
#include "scrnintstr.h"
43
#include "pixmapstr.h"
44
#include "extnsionst.h"
45
#include "dixstruct.h"
48
#include "regionstr.h"
54
#define _MULTIBUF_SERVER_ /* don't want Xlib structures */
55
#define _MULTIBUF_BUFFER_
56
#include <X11/extensions/multibufst.h>
59
Support for doublebuffer hardare
61
This code is designed to support doublebuffer hardware where the
62
displayed buffer is selected on a per-pixel basis by an additional bit
63
plane, called the select plane. It could probably be easily modified
64
to work with systems that use window-id planes.
66
This is done by creating a new drawable type, DRAWABLE_BUFFER. The
67
type has the same exact layout as a window drawable. Your code should
68
treat a DRAWABLE_BUFFER the same as it would tread a DRAWABLE_WINDOW
69
when handling the gc drawing functions. In addition, PaintWindowBackground,
70
CopyWindow, and all of the gc drawing functions to be able to draw into both
71
framebuffers. Which framebuffer to draw into is selected by the contents of
72
pWin->devPrivates[frameWindowPrivateIndex].
73
The content of the devPrivate is either from frameBuffer[0] or
74
frameBuffer[1], depending on which buffer is being drawn into. When
75
pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[0],
76
the functions should draw into the front framebuffer. When
77
pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[1],
78
the functions should draw into the back framebuffer.
80
In addition, you need to provide a function that allows you to copy
81
bits between the buffers (optional since CopyArea can be used) and a
82
function that draws into the select plane. Then, you need to register
83
your functions and other information, by calling:
86
RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
87
CopyBufferBitsFunc, DrawSelectPlaneFunc)
89
xMbufBufferInfo *pInfo;
90
DevUnion *frameBuffer;
93
"pInfo" is an array indicating which visuals and depths that double
94
buffering is supported on. "nInfo" is the length of the array.
96
"frameBuffer" is array of length 2. The contents of the array element
97
is ddx-specific. The content of frameBuffer[0] should, when placed in
98
the window private, indicate that framebuffer 0 should be drawn into.
99
The contents of frameBuffer[1], when placed into the window private,
100
should indicate that framebuffer 1 should be drawn into.
102
"selectPlane" is ddx-specific. It should contain information
103
neccessary for your displayProc to access the select plane.
104
It is passed to DrawSelectPlaneFunc.
106
"CopyBufferBitsFunc" is a ddx-specific function that copies from one
107
buffer of a multibuffered window to another buffer. If the CopyBufferBitsFunc
108
is NULL, a default function will be used that calls pScreen->CopyArea.
110
void CopyBufferBitsFunc(pMBWindow, srcBufferNum, dstBufferNum)
111
mbufWindowPtr pMBWindow;
112
int srcBufferNum, dstBufferNum;
114
"DrawSelectPlaneFunc" is a ddx-specific function that fills the
115
regions "prgn" of select plane with the value "bufferNum". If
116
selectPlane is a DrawablePtr (such as a PixmapPtr), you can pass
117
NULL for DrawSelectPlaneFunc, a default function will be used that
118
calls FillRectangle on the selectPlane.
120
void DrawSelectPlaneFunc(pScreen, selectPlane, prgn, bufferNum)
122
DevUnion selectPlane;
132
#define MAX_BUFFERS 2 /* Only supports 2 buffers */
133
#define FRONT_BUFFER 0
134
#define BACK_BUFFER 1
137
/* Buffer drawables have the same structure as window drawables */
138
typedef WindowRec BufferRec;
139
typedef WindowPtr BufferPtr;
143
* Call RegisterHdwrBuffer for every screen that has doublebuffer hardware.
146
static int bufNumInfo[MAXSCREENS];
147
static xMbufBufferInfo *bufInfo[MAXSCREENS];
148
static DevUnion *bufFrameBuffer[MAXSCREENS];
149
static DevUnion bufselectPlane[MAXSCREENS];
150
static void (* bufCopyBufferBitsFunc[MAXSCREENS])();
151
static void (* bufDrawSelectPlaneFunc[MAXSCREENS])();
153
static Bool bufMultibufferInit();
157
RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
158
CopyBufferBitsFunc, DrawSelectPlaneFunc)
161
xMbufBufferInfo *pInfo;
162
DevUnion *frameBuffer;
163
DevUnion selectPlane;
164
void (* CopyBufferBitsFunc)();
165
void (* DrawSelectPlaneFunc)();
167
bufNumInfo[pScreen->myNum] = nInfo;
168
bufInfo[pScreen->myNum] = pInfo;
169
bufFrameBuffer[pScreen->myNum] = frameBuffer;
170
bufselectPlane[pScreen->myNum] = selectPlane;
172
bufCopyBufferBitsFunc[pScreen->myNum] = CopyBufferBitsFunc;
173
bufDrawSelectPlaneFunc[pScreen->myNum] = DrawSelectPlaneFunc;
175
/* Register ourselves with device-independent multibuffers code */
176
RegisterMultibufferInit(pScreen, bufMultibufferInit);
181
* Called by Multibuffer extension initialization.
182
* Initializes mbufScreenRec and its devPrivate.
185
static Bool NoopDDA_True() { return TRUE; }
186
static Bool bufPositionWindow();
187
static int bufCreateImageBuffers();
188
static void bufDestroyImageBuffers();
189
static void bufDisplayImageBuffers();
190
static void bufClearImageBufferArea();
191
static void bufDestroyBuffer();
192
static void bufCopyBufferBits();
193
static void bufDrawSelectPlane();
194
static void bufWrapScreenFuncs();
195
static void bufResetProc();
197
static void bufPostValidateTree();
198
static void bufClipNotify();
199
static void bufWindowExposures();
200
static Bool bufChangeWindowAttributes();
201
static void bufClearToBackground();
202
static void bufCopyWindow();
204
extern WindowPtr *WindowTable;
207
bufMultibufferInit(pScreen, pMBScreen)
209
mbufScreenPtr pMBScreen;
211
mbufBufferPrivPtr pMBPriv;
214
/* Multibuffer info */
215
pMBScreen->nInfo = bufNumInfo[pScreen->myNum];
216
pMBScreen->pInfo = bufInfo[pScreen->myNum];
219
pMBScreen->CreateImageBuffers = bufCreateImageBuffers;
220
pMBScreen->DestroyImageBuffers = bufDestroyImageBuffers;
221
pMBScreen->DisplayImageBuffers = bufDisplayImageBuffers;
222
pMBScreen->ClearImageBufferArea = bufClearImageBufferArea;
223
pMBScreen->ChangeMBufferAttributes = NoopDDA_True;
224
pMBScreen->ChangeBufferAttributes = NoopDDA_True;
225
pMBScreen->DeleteBufferDrawable = bufDestroyBuffer;
226
pMBScreen->WrapScreenFuncs = bufWrapScreenFuncs;
227
pMBScreen->ResetProc = bufResetProc;
228
/* Create devPrivate part */
229
pMBPriv = (mbufBufferPrivPtr) xalloc(sizeof *pMBPriv);
233
pMBScreen->devPrivate.ptr = (pointer) pMBPriv;
234
pMBPriv->frameBuffer = bufFrameBuffer[pScreen->myNum];
235
pMBPriv->selectPlane = bufselectPlane[pScreen->myNum];
238
* Initializing the subtractRgn to the screen area will ensure that
239
* the selectPlane will get cleared on the first PostValidateTree.
244
box.x2 = pScreen->width;
245
box.y2 = pScreen->height;
247
pMBPriv->rgnChanged = TRUE;
248
REGION_INIT(pScreen, &pMBPriv->backBuffer, &box, 1);
249
REGION_INIT(pScreen, &pMBPriv->subtractRgn, &box, 1);
250
REGION_NULL(pScreen, &pMBPriv->unionRgn);
253
pMBPriv->CopyBufferBits = bufCopyBufferBitsFunc[pScreen->myNum];
254
pMBPriv->DrawSelectPlane = bufDrawSelectPlaneFunc[pScreen->myNum];
256
if (!pMBPriv->CopyBufferBits)
257
pMBPriv->CopyBufferBits = bufCopyBufferBits;
259
if (!pMBPriv->DrawSelectPlane)
260
pMBPriv->DrawSelectPlane = bufDrawSelectPlane;
262
/* screen functions */
263
pMBPriv->funcsWrapped = 0;
264
pMBPriv->inClearToBackground = FALSE;
265
pMBPriv->WindowExposures = NULL;
266
pMBPriv->CopyWindow = NULL;
267
pMBPriv->ClearToBackground = NULL;
268
pMBPriv->ClipNotify = NULL;
269
pMBPriv->ChangeWindowAttributes = NULL;
271
/* Start out wrapped to clear select plane */
272
WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree);
277
UpdateBufferFromWindow(pBuffer, pWin)
281
pBuffer->drawable.x = pWin->drawable.x;
282
pBuffer->drawable.y = pWin->drawable.y;
283
pBuffer->drawable.width = pWin->drawable.width;
284
pBuffer->drawable.height = pWin->drawable.height;
286
pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER;
288
/* Update for PaintWindowBackground */
289
pBuffer->parent = pWin->parent;
292
* Make the borderClip the same as the clipList so
293
* NotClippedByChildren comes out with just clipList.
296
pBuffer->clipList = pWin->clipList;
297
pBuffer->borderClip = pWin->clipList;
298
pBuffer->winSize = pWin->winSize;
299
pBuffer->borderSize = pWin->borderSize;
301
pBuffer->origin = pWin->origin;
305
bufCreateBuffer(pScreen, pWin, bufferNum)
310
mbufBufferPrivPtr pMBPriv;
311
DevUnion *devPrivates;
315
pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
317
pBuffer = AllocateWindow(pWin->drawable.pScreen);
321
/* XXX- Until we know what is needed, copy everything. */
322
devPrivates = pBuffer->devPrivates;
324
pBuffer->devPrivates = devPrivates;
326
pBuffer->drawable.type = DRAWABLE_BUFFER;
327
pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER;
329
pBuffer->nextSib = NULL;
330
pBuffer->prevSib = NULL;
331
pBuffer->firstChild = NULL;
332
pBuffer->lastChild = NULL;
334
/* XXX - Worry about backingstore later */
335
pBuffer->backStorage = NULL;
336
pBuffer->backingStore = NotUseful;
338
/* XXX - Need to call pScreen->CreateWindow for tile/stipples
339
* or should I just copy the devPrivates?
342
for (i=0; i < pScreen->WindowPrivateLen; i++)
343
pBuffer->devPrivates[i] = pWin->devPrivates[i];
345
pBuffer->devPrivates[frameWindowPrivateIndex] =
346
pMBPriv->frameBuffer[bufferNum];
352
bufDestroyBuffer(pDrawable)
353
DrawablePtr pDrawable;
360
bufCreateImageBuffers (pWin, nbuf, ids, action, hint)
368
mbufScreenPtr pMBScreen;
369
mbufWindowPtr pMBWindow;
370
mbufBufferPtr pMBBuffer;
373
pScreen = pWin->drawable.pScreen;
374
pMBScreen = MB_SCREEN_PRIV(pScreen);
375
pMBWindow = MB_WINDOW_PRIV(pWin);
377
pMBWindow->devPrivate.ptr = (pointer) REGION_CREATE(pScreen, 0,0);
378
if (!pMBWindow->devPrivate.ptr)
380
REGION_COPY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr,
383
for (i = 0; i < nbuf; i++)
385
pMBBuffer = pMBWindow->buffers + i;
386
pMBBuffer->pDrawable = (DrawablePtr) bufCreateBuffer(pScreen,pWin,i);
388
if (!pMBBuffer->pDrawable)
391
if (!AddResource (ids[i], MultibufferDrawableResType,
392
(pointer) pMBBuffer->pDrawable))
394
bufDestroyBuffer((BufferPtr) pMBBuffer->pDrawable);
397
pMBBuffer->pDrawable->id = ids[i];
400
* If window is already mapped, generate exposures and
401
* clear the area of the newly buffers.
404
if ((pWin->realized) && (i != pMBWindow->displayedMultibuffer))
405
(* pMBScreen->ClearImageBufferArea)(pMBBuffer, 0,0, 0,0, TRUE);
412
bufDestroyImageBuffers(pWin)
416
mbufWindowPtr pMBWindow;
418
pScreen = pWin->drawable.pScreen;
420
if (pMBWindow = MB_WINDOW_PRIV(pWin))
422
mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
425
* if the backbuffer is currently being displayed, move the bits
426
* to the frontbuffer and display it instead.
429
if (pWin->realized && (pMBWindow->displayedMultibuffer == BACK_BUFFER))
431
(* pMBPriv->CopyBufferBits)(pMBWindow, BACK_BUFFER, FRONT_BUFFER);
432
REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer,
433
&pMBPriv->backBuffer, &pWin->clipList);
434
(* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
435
&pWin->clipList, FRONT_BUFFER);
438
/* Switch window rendering to front buffer */
439
pWin->devPrivates[frameWindowPrivateIndex] =
440
pMBPriv->frameBuffer[FRONT_BUFFER];
442
REGION_DESTROY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr);
443
pMBWindow->devPrivate.ptr = NULL;
448
* Can be replaced by pScreen->ClearToBackground if pBuffer->eventMask
449
* and wOtherEventsMasks(pBuffer) were setup.
453
bufClearImageBufferArea(pMBBuffer, x,y, w,h, generateExposures)
454
mbufBufferPtr pMBBuffer;
457
Bool generateExposures;
461
RegionPtr pBSReg = NullRegion;
467
pBuffer = (BufferPtr) pMBBuffer->pDrawable;
468
/* compute everything using ints to avoid overflow */
470
x1 = pBuffer->drawable.x + x;
471
y1 = pBuffer->drawable.y + y;
475
x2 = x1 + (int) pBuffer->drawable.width - (int) x;
479
y2 = y1 + (int) pBuffer->drawable.height - (int) y;
481
extents = &pBuffer->clipList.extents;
483
/* clip the resulting rectangle to the window clipList extents. This
484
* makes sure that the result will fit in a box, given that the
485
* screen is < 32768 on a side.
488
if (x1 < extents->x1)
490
if (x2 > extents->x2)
492
if (y1 < extents->y1)
494
if (y2 > extents->y2)
497
if (x2 <= x1 || y2 <= y1)
508
pScreen = pBuffer->drawable.pScreen;
509
REGION_INIT(pScreen, ®, &box, 1);
510
if (pBuffer->backStorage)
513
* If the window has backing-store on, call through the
514
* ClearToBackground vector to handle the special semantics
515
* (i.e. things backing store is to be cleared out and
516
* an Expose event is to be generated for those areas in backing
517
* store if generateExposures is TRUE).
519
pBSReg = (* pScreen->ClearBackingStore)(pBuffer, x, y, w, h,
523
REGION_INTERSECT(pScreen, ®, ®, &pBuffer->clipList);
524
if (pBuffer->backgroundState != None)
525
(*pScreen->PaintWindowBackground)(pBuffer, ®, PW_BACKGROUND);
526
if (generateExposures)
527
MultibufferExpose(pMBBuffer, ®);
529
/* XXBS - This is the original miClearToBackground code.
530
* WindowExposures needs to be called (or the functionality emulated)
531
* in order for backingStore to work, but first, pBuffer->eventMask
532
* and wOtherEventsMasks(pBuffer) need to be setup correctly.
535
if (generateExposures)
536
(*pScreen->WindowExposures)(pBuffer, ®, pBSReg);
537
else if (pBuffer->backgroundState != None)
538
(*pScreen->PaintWindowBackground)(pBuffer, ®, PW_BACKGROUND);
540
REGION_UNINIT(pScreen, ®);
542
REGION_DESTROY(pScreen, pBSReg);
546
bufWrapScreenFuncs(pScreen)
549
mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
551
WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree);
552
WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClipNotify, bufClipNotify);
553
WRAP_SCREEN_FUNC(pScreen,pMBPriv,WindowExposures,bufWindowExposures);
554
WRAP_SCREEN_FUNC(pScreen,pMBPriv,ChangeWindowAttributes, bufChangeWindowAttributes);
555
WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClearToBackground,bufClearToBackground);
556
WRAP_SCREEN_FUNC(pScreen,pMBPriv,CopyWindow,bufCopyWindow);
560
bufResetProc(pScreen)
563
mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
566
* frameBuffer, selectPlane, and pInfo should be freed by
567
* whoever called RegisterDoubleBufferHardware
570
REGION_UNINIT(pScreen, &pMBPriv->backBuffer);
571
REGION_UNINIT(pScreen, &pMBPriv->subtractRgn);
572
REGION_UNINIT(pScreen, &pMBPriv->unionRgn);
576
/*---------------------------------------------------------------------------*/
579
* Used if CopyBufferBitsFunc is not provided when registering.
580
* This should work for everybody since CopyArea needs to support
581
* copying between buffers anyway.
585
bufCopyBufferBits(pMBWindow, srcBufferNum, dstBufferNum)
586
mbufWindowPtr pMBWindow;
587
int srcBufferNum, dstBufferNum;
589
DrawablePtr pSrcBuffer, pDstBuffer;
592
pSrcBuffer = pMBWindow->buffers[srcBufferNum].pDrawable;
593
pDstBuffer = pMBWindow->buffers[dstBufferNum].pDrawable;
595
pGC = GetScratchGC (pDstBuffer->depth, pDstBuffer->pScreen);
599
ValidateGC (pDstBuffer, pGC);
600
(* pGC->ops->CopyArea) (pSrcBuffer, pDstBuffer, pGC,
601
0,0, pDstBuffer->width, pDstBuffer->height, 0,0);
606
* Used if DrawSelectPlanFunc is not provided for when registering.
607
* However, it only works if selectPlane.ptr is a drawable. Also
608
* assumes that painting with color 0 selects the front buffer,
609
* while color 1 selects the back buffer.
613
bufDrawSelectPlane(pScreen, selectPlane, prgn, bufferNum)
615
DevUnion selectPlane;
619
DrawablePtr pDrawable;
622
register BoxPtr pbox;
623
register xRectangle *prect;
627
if (REGION_NUM_RECTS(prgn) == 0)
630
pDrawable = (DrawablePtr) selectPlane.ptr;
631
pGC = GetScratchGC (pDrawable->depth, pScreen);
635
prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) *
643
value = (XID) bufferNum;
644
DoChangeGC(pGC, GCForeground, &value, 0);
645
ValidateGC(pDrawable, pGC);
647
numRects = REGION_NUM_RECTS(prgn);
648
pbox = REGION_RECTS(prgn);
649
for (i= numRects; --i >= 0; pbox++, prect++)
653
prect->width = pbox->x2 - pbox->x1;
654
prect->height = pbox->y2 - pbox->y1;
657
(* pGC->ops->PolyFillRect)(pDrawable, pGC, numRects, prect);
659
DEALLOCATE_LOCAL(prect);
665
bufDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf)
667
mbufBufferPtr *ppMBBuffer;
668
mbufWindowPtr *ppMBWindow;
672
BufferPtr pPrevBuffer, pNewBuffer;
674
mbufBufferPrivPtr pMBPriv;
675
mbufBufferPtr pPrevMBBuffer;
677
pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
679
for (i = 0; i < nbuf; i++)
681
number = ppMBBuffer[i]->number; /* 0=frontbuffer, 1=backbuffer */
682
pWin = ppMBWindow[i]->pWindow;
683
pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]);
685
pPrevBuffer = (BufferPtr) pPrevMBBuffer->pDrawable;
686
pNewBuffer = (BufferPtr) ppMBBuffer[i]->pDrawable;
688
if (pPrevBuffer != pNewBuffer)
690
RegionPtr backBuffer = &pMBPriv->backBuffer;
693
* Update the select plane and the backBuffer region.
696
(* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
697
&pWin->clipList, number);
699
if (number == BACK_BUFFER)
700
REGION_UNION(pScreen, backBuffer, backBuffer,
703
REGION_SUBTRACT(pScreen, backBuffer, backBuffer,
706
/* Switch which framebuffer the window draws into */
707
pWin->devPrivates[frameWindowPrivateIndex] =
708
pMBPriv->frameBuffer[number];
711
switch (ppMBWindow[i]->updateAction)
713
case MultibufferUpdateActionUndefined:
715
case MultibufferUpdateActionBackground:
716
(* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea)
717
(pPrevMBBuffer, 0,0, 0,0, FALSE);
719
case MultibufferUpdateActionUntouched:
721
case MultibufferUpdateActionCopied:
722
if (pPrevBuffer != pNewBuffer)
724
(* pMBPriv->CopyBufferBits) (ppMBWindow[i],
725
ppMBBuffer[i]->number, pPrevMBBuffer->number);
732
/* Updates the backBuffer region and paints the selectPlane. */
735
bufPostValidateTree(pParent, pChild, kind)
736
WindowPtr pParent, pChild;
740
mbufBufferPrivPtr pMBPriv;
743
pScreen = pParent->drawable.pScreen;
745
pScreen = pChild->drawable.pScreen;
747
return; /* Hopeless */
749
pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
751
UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree);
752
if (pScreen->PostValidateTree)
753
(* pScreen->PostValidateTree)(pParent, pChild, kind);
754
REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree);
756
/* Does backBuffer need to change? */
757
if (pMBPriv->rgnChanged)
760
RegionPtr pSubtractRgn, pUnionRgn;
763
pMBPriv->rgnChanged = FALSE;
765
pSubtractRgn = &pMBPriv->subtractRgn;
766
pUnionRgn = &pMBPriv->unionRgn;
767
REGION_VALIDATE(pScreen, pSubtractRgn, &overlap);
770
FatalError("bufPostValidateTree: subtractRgn overlaps");
772
REGION_VALIDATE(pScreen, pUnionRgn, &overlap);
775
FatalError("bufPostValidateTree: unionRgn overlaps");
778
/* Update backBuffer: subtract must come before union */
779
REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer,
781
REGION_UNION(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer,
784
/* Paint gained and lost backbuffer areas in select plane */
785
REGION_NULL(pScreen, &exposed);
786
REGION_SUBTRACT(pScreen, &exposed, pSubtractRgn, pUnionRgn);
787
(* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
788
&exposed, FRONT_BUFFER);
790
REGION_SUBTRACT(pScreen, &exposed, pUnionRgn, pSubtractRgn);
791
(* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
792
&exposed, BACK_BUFFER);
794
REGION_UNINIT(pScreen, &exposed);
795
REGION_EMPTY(pScreen, pSubtractRgn);
796
REGION_EMPTY(pScreen, pUnionRgn);
801
* If the window is multibuffered and displaying the backbuffer,
802
* add the old clipList to the subtractRgn and add the new clipList
803
* to the unionRgn. PostValidateTree will use subtractRgn and unionRgn
804
* to update the backBuffer region and the selectPlane.
806
* Copy changes to the window structure into the buffers.
807
* Send ClobberNotify events.
811
bufClipNotify(pWin, dx,dy)
815
ScreenPtr pScreen = pWin->drawable.pScreen;
816
mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
817
mbufWindowPtr pMBWindow;
820
UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify);
821
if (pScreen->ClipNotify)
822
(* pScreen->ClipNotify)(pWin, dx,dy);
823
REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify);
825
if (pMBWindow = MB_WINDOW_PRIV(pWin))
827
RegionPtr pOldClipList = (RegionPtr) pMBWindow->devPrivate.ptr;
829
if (! REGION_EQUAL(pScreen, pOldClipList, &pWin->clipList))
831
if (pMBWindow->displayedMultibuffer == BACK_BUFFER)
833
pMBPriv->rgnChanged = TRUE;
834
REGION_APPEND(pScreen, &pMBPriv->subtractRgn, pOldClipList);
835
REGION_APPEND(pScreen, &pMBPriv->unionRgn, &pWin->clipList);
838
REGION_COPY(pScreen, pOldClipList,&pWin->clipList);
841
/* Update buffer x,y,w,h, and clipList */
842
for (i=0; i<pMBWindow->numMultibuffer; i++)
844
mbufBufferPtr pMBBuffer = pMBWindow->buffers + i;
845
if (pMBBuffer->clobber != pWin->visibility)
847
pMBBuffer->clobber = pWin->visibility;
848
MultibufferClobber(pMBBuffer);
850
UpdateBufferFromWindow(pMBBuffer->pDrawable, pWin);
856
* Updates buffer's background fields when the window's changes.
857
* This is necessary because pScreen->PaintWindowBackground
858
* is used to paint the buffer.
860
* XXBS - Backingstore state will have be tracked too if it is supported.
864
bufChangeWindowAttributes(pWin, mask)
868
ScreenPtr pScreen = pWin->drawable.pScreen;
869
mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
870
mbufWindowPtr pMBWindow;
873
UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes);
874
ret = (* pScreen->ChangeWindowAttributes)(pWin, mask);
875
REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes);
877
if (pMBWindow = MB_WINDOW_PRIV(pWin))
879
if (mask & (CWBackPixmap | CWBackPixel))
884
for (i=0; i<pMBWindow->displayedMultibuffer; i++)
886
pBuffer = (BufferPtr) pMBWindow->buffers[i].pDrawable;
887
pBuffer->backgroundState = pWin->backgroundState;
888
pBuffer->background = pWin->background;
896
* Send exposures and clear the background for a buffer whenever
897
* its corresponding window is exposed, except when called by
902
bufWindowExposures(pWin, prgn, other_exposed)
904
register RegionPtr prgn, other_exposed;
906
ScreenPtr pScreen = pWin->drawable.pScreen;
907
mbufWindowPtr pMBWindow = MB_WINDOW_PRIV(pWin);
908
mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
913
handleBuffers = (!pMBPriv->inClearToBackground) &&
914
(pWin->drawable.type == DRAWABLE_WINDOW) &&
915
pMBWindow && (prgn && !REGION_NIL(prgn));
917
/* miWindowExposures munges prgn and other_exposed. */
920
REGION_NULL(pScreen, &tmp_rgn);
921
REGION_COPY(pScreen, &tmp_rgn, prgn);
924
UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures);
925
(* pScreen->WindowExposures) (pWin, prgn, other_exposed);
926
REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures);
932
* Send expose events to all clients. Paint the exposed region for all
933
* buffers except the displayed buffer since it is handled when the
936
* XXBS - Will have to be re-written to handle BackingStore on buffers.
939
for (i=0; i<pMBWindow->numMultibuffer; i++)
941
mbufBufferPtr pMBBuffer;
944
pMBBuffer = pMBWindow->buffers + i;
945
pBuffer = (BufferPtr) pMBBuffer->pDrawable;
947
if (i != pMBWindow->displayedMultibuffer)
948
(* pScreen->PaintWindowBackground)(pBuffer,&tmp_rgn,PW_BACKGROUND);
949
if ((pMBBuffer->otherEventMask | pMBBuffer->eventMask) & ExposureMask)
950
MultibufferExpose(pMBBuffer, &tmp_rgn);
953
REGION_UNINIT(pScreen, &tmp_rgn);
957
* Set ``inClearToBackground'' so that WindowExposures does not attempt
958
* to send expose events or clear the background on the buffers.
962
bufClearToBackground(pWin, x,y,w,h, sendExpose)
967
ScreenPtr pScreen = pWin->drawable.pScreen;
968
mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
970
pMBPriv->inClearToBackground = TRUE;
972
UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground);
973
(* pScreen->ClearToBackground)(pWin, x,y,w,h, sendExpose);
974
REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground);
976
pMBPriv->inClearToBackground = FALSE;
980
* Move bits in both buffers. It does this by calling pScreen->CopyWindow
981
* twice, once with the root window's devPrivate[frameWindowPrivateIndex]
982
* pointing to the frontbuffer pixmap and once with it pointed to the
983
* backbuffer pixmap. It does this if there are *any* existing multibuffered
984
* window... a possible optimization is to copy the backbuffer only if this
985
* window or its inferiors are multibuffered. May be faster, maybe not.
987
* XXX - Only works if your CopyWindow checks the root window's devPrivate
988
* to see which buffer to draw into. Works for cfbPaintWindow.
993
bufCopyWindow(pWin, ptOldOrg, prgnSrc)
995
DDXPointRec ptOldOrg;
998
ScreenPtr pScreen = pWin->drawable.pScreen;
999
mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
1003
UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow);
1005
pwinroot = WindowTable[pScreen->myNum];
1006
save = pwinroot->devPrivates[frameWindowPrivateIndex];
1012
pwinroot->devPrivates[frameWindowPrivateIndex] =
1013
pMBPriv->frameBuffer[FRONT_BUFFER];
1014
(* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
1020
/* CopyWindow translates prgnSrc... translate it back for 2nd call. */
1021
REGION_TRANSLATE(pScreen, prgnSrc,
1022
ptOldOrg.x - pWin->drawable.x,
1023
ptOldOrg.y - pWin->drawable.y);
1024
pwinroot->devPrivates[frameWindowPrivateIndex] =
1025
pMBPriv->frameBuffer[BACK_BUFFER];
1026
(* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
1028
pwinroot->devPrivates[frameWindowPrivateIndex] = save;
1029
REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow);