1 /************************************************************
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.
25 ********************************************************/
29 #ifdef HAVE_DIX_CONFIG_H
30 #include <dix-config.h>
34 #include <X11/Xproto.h>
37 #include "windowstr.h"
38 #include "scrnintstr.h"
39 #include "pixmapstr.h"
41 #include "extnsionst.h"
42 #include "dixstruct.h"
45 #include "sleepuntil.h"
46 #define _MULTIBUF_SERVER_ /* don't want Xlib structures */
47 #include <X11/extensions/multibufst.h>
50 #if !defined(WIN32) && !defined(Lynx)
54 /* given an OtherClientPtr obj, get the ClientPtr */
55 #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
57 /* given a MultibufferPtr b, get the ClientPtr */
58 #define bClient(b) (clients[CLIENT_ID(b->pPixmap->drawable.id)])
60 #define ValidEventMasks (ExposureMask|MultibufferClobberNotifyMask|MultibufferUpdateNotifyMask)
63 static unsigned char MultibufferReqCode
;
65 static int MultibufferEventBase
;
66 static int MultibufferErrorBase
;
67 int MultibufferScreenIndex
= -1;
68 int MultibufferWindowIndex
= -1;
70 static void PerformDisplayRequest (
71 MultibuffersPtr
* /* ppMultibuffers */,
72 MultibufferPtr
* /* pMultibuffer */,
75 static Bool
QueueDisplayRequest (
76 ClientPtr
/* client */,
77 TimeStamp
/* activateTime */
80 static void BumpTimeStamp (
85 static void AliasMultibuffer (
86 MultibuffersPtr
/* pMultibuffers */,
89 static void RecalculateMultibufferOtherEvents (
90 MultibufferPtr
/* pMultibuffer */
92 static int EventSelectForMultibuffer(
93 MultibufferPtr
/* pMultibuffer */,
94 ClientPtr
/* client */,
99 * The Pixmap associated with a buffer can be found as a resource
102 RESTYPE MultibufferDrawableResType
;
103 static int MultibufferDrawableDelete (
108 * The per-buffer data can be found as a resource with this type.
109 * the resource id of the per-buffer data is the same as the resource
112 static RESTYPE MultibufferResType
;
113 static int MultibufferDelete (
119 * The per-window data can be found as a resource with this type,
120 * using the window resource id
122 static RESTYPE MultibuffersResType
;
123 static int MultibuffersDelete (
129 * Clients other than the buffer creator attach event masks in
130 * OtherClient structures; each has a resource of this type.
132 static RESTYPE OtherClientResType
;
133 static int OtherClientDelete (
139 * MultibufferExtensionInit
141 * Called from InitExtensions in main()
145 extern DISPATCH_PROC(ProcGetBufferAttributes
);
147 static DISPATCH_PROC(ProcClearImageBufferArea
);
148 static DISPATCH_PROC(ProcCreateImageBuffers
);
149 static DISPATCH_PROC(ProcDestroyImageBuffers
);
150 static DISPATCH_PROC(ProcDisplayImageBuffers
);
151 static DISPATCH_PROC(ProcGetBufferInfo
);
152 static DISPATCH_PROC(ProcGetBufferVersion
);
153 static DISPATCH_PROC(ProcGetMBufferAttributes
);
154 static DISPATCH_PROC(ProcMultibufferDispatch
);
155 static DISPATCH_PROC(ProcSetBufferAttributes
);
156 static DISPATCH_PROC(ProcSetMBufferAttributes
);
157 static DISPATCH_PROC(SProcClearImageBufferArea
);
158 static DISPATCH_PROC(SProcCreateImageBuffers
);
159 static DISPATCH_PROC(SProcDestroyImageBuffers
);
160 static DISPATCH_PROC(SProcDisplayImageBuffers
);
161 static DISPATCH_PROC(SProcGetBufferAttributes
);
162 static DISPATCH_PROC(SProcGetBufferInfo
);
163 static DISPATCH_PROC(SProcGetBufferVersion
);
164 static DISPATCH_PROC(SProcGetMBufferAttributes
);
165 static DISPATCH_PROC(SProcMultibufferDispatch
);
166 static DISPATCH_PROC(SProcSetBufferAttributes
);
167 static DISPATCH_PROC(SProcSetMBufferAttributes
);
169 static void MultibufferResetProc(
170 ExtensionEntry
* /* extEntry */
172 static void SClobberNotifyEvent(
173 xMbufClobberNotifyEvent
* /* from */,
174 xMbufClobberNotifyEvent
* /* to */
176 static void SUpdateNotifyEvent(
177 xMbufUpdateNotifyEvent
* /* from */,
178 xMbufUpdateNotifyEvent
* /* to */
180 static Bool
MultibufferPositionWindow(
181 WindowPtr
/* pWin */,
186 static void SetupBackgroundPainter (
187 WindowPtr
/* pWin */,
191 static int DeliverEventsToMultibuffer (
192 MultibufferPtr
/* pMultibuffer */,
193 xEvent
* /* pEvents */,
199 MultibufferExtensionInit()
201 ExtensionEntry
*extEntry
;
204 MultibufferScreenPtr pMultibufferScreen
;
207 * allocate private pointers in windows and screens. Allocating
208 * window privates may seem like an unnecessary expense, but every
209 * PositionWindow call must check to see if the window is
210 * multi-buffered; a resource lookup is too expensive.
212 MultibufferScreenIndex
= AllocateScreenPrivateIndex ();
213 if (MultibufferScreenIndex
< 0)
215 MultibufferWindowIndex
= AllocateWindowPrivateIndex ();
216 for (i
= 0; i
< screenInfo
.numScreens
; i
++)
218 pScreen
= screenInfo
.screens
[i
];
219 if (!AllocateWindowPrivate (pScreen
, MultibufferWindowIndex
, 0) ||
220 !(pMultibufferScreen
= (MultibufferScreenPtr
) xalloc (sizeof (MultibufferScreenRec
))))
222 for (j
= 0; j
< i
; j
++)
223 xfree (screenInfo
.screens
[j
]->devPrivates
[MultibufferScreenIndex
].ptr
);
226 pScreen
->devPrivates
[MultibufferScreenIndex
].ptr
= (pointer
) pMultibufferScreen
;
228 * wrap PositionWindow to resize the pixmap when the window
231 pMultibufferScreen
->PositionWindow
= pScreen
->PositionWindow
;
232 pScreen
->PositionWindow
= MultibufferPositionWindow
;
235 * create the resource types
237 MultibufferDrawableResType
=
238 CreateNewResourceType(MultibufferDrawableDelete
)|RC_CACHED
|RC_DRAWABLE
;
239 MultibufferResType
= CreateNewResourceType(MultibufferDelete
);
240 MultibuffersResType
= CreateNewResourceType(MultibuffersDelete
);
241 OtherClientResType
= CreateNewResourceType(OtherClientDelete
);
242 if (MultibufferDrawableResType
&& MultibufferResType
&&
243 MultibuffersResType
&& OtherClientResType
&&
244 (extEntry
= AddExtension(MULTIBUFFER_PROTOCOL_NAME
,
245 MultibufferNumberEvents
,
246 MultibufferNumberErrors
,
247 ProcMultibufferDispatch
, SProcMultibufferDispatch
,
248 MultibufferResetProc
, StandardMinorOpcode
)))
251 MultibufferReqCode
= (unsigned char)extEntry
->base
;
253 MultibufferEventBase
= extEntry
->eventBase
;
254 MultibufferErrorBase
= extEntry
->errorBase
;
255 EventSwapVector
[MultibufferEventBase
+ MultibufferClobberNotify
] = (EventSwapPtr
) SClobberNotifyEvent
;
256 EventSwapVector
[MultibufferEventBase
+ MultibufferUpdateNotify
] = (EventSwapPtr
) SUpdateNotifyEvent
;
262 MultibufferResetProc (extEntry
)
263 ExtensionEntry
*extEntry
;
267 MultibufferScreenPtr pMultibufferScreen
;
269 if (MultibufferScreenIndex
< 0)
271 for (i
= 0; i
< screenInfo
.numScreens
; i
++)
273 pScreen
= screenInfo
.screens
[i
];
274 if (pScreen
->devPrivates
[MultibufferScreenIndex
].ptr
)
276 pMultibufferScreen
= (MultibufferScreenPtr
) pScreen
->devPrivates
[MultibufferScreenIndex
].ptr
;
277 pScreen
->PositionWindow
= pMultibufferScreen
->PositionWindow
;
278 xfree (pMultibufferScreen
);
284 ProcGetBufferVersion (client
)
285 register ClientPtr client
;
287 xMbufGetBufferVersionReply rep
;
290 REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq
);
293 rep
.sequenceNumber
= client
->sequence
;
294 rep
.majorVersion
= MULTIBUFFER_MAJOR_VERSION
;
295 rep
.minorVersion
= MULTIBUFFER_MINOR_VERSION
;
296 if (client
->swapped
) {
297 swaps(&rep
.sequenceNumber
, n
);
298 swapl(&rep
.length
, n
);
300 WriteToClient(client
, sizeof (xMbufGetBufferVersionReply
), (char *)&rep
);
301 return (client
->noClientException
);
305 SetupBackgroundPainter (pWin
, pGC
)
310 int ts_x_origin
, ts_y_origin
;
316 * First take care of any ParentRelative stuff by altering the
317 * tile/stipple origin to match the coordinates of the upper-left
318 * corner of the first ancestor without a ParentRelative background.
319 * This coordinate is, of course, negative.
322 ts_x_origin
= ts_y_origin
= 0;
323 while (pWin
->backgroundState
== ParentRelative
) {
324 ts_x_origin
-= pWin
->origin
.x
;
325 ts_y_origin
-= pWin
->origin
.y
;
328 backgroundState
= pWin
->backgroundState
;
329 background
= pWin
->background
;
331 switch (backgroundState
)
333 case BackgroundPixel
:
334 gcvalues
[0] = (pointer
) background
.pixel
;
335 gcvalues
[1] = (pointer
) FillSolid
;
336 gcmask
= GCForeground
|GCFillStyle
;
339 case BackgroundPixmap
:
340 gcvalues
[0] = (pointer
) FillTiled
;
341 gcvalues
[1] = (pointer
) background
.pixmap
;
342 gcvalues
[2] = (pointer
)(long) ts_x_origin
;
343 gcvalues
[3] = (pointer
)(long) ts_y_origin
;
344 gcmask
= GCFillStyle
|GCTile
|GCTileStipXOrigin
|GCTileStipYOrigin
;
348 gcvalues
[0] = (pointer
) GXnoop
;
351 DoChangeGC(pGC
, gcmask
, (XID
*)gcvalues
, TRUE
);
355 CreateImageBuffers (pWin
, nbuf
, ids
, action
, hint
)
362 MultibuffersPtr pMultibuffers
;
363 MultibufferPtr pMultibuffer
;
365 int width
, height
, depth
;
367 GCPtr pClearGC
= NULL
;
368 xRectangle clearRect
;
370 DestroyImageBuffers(pWin
);
371 pMultibuffers
= (MultibuffersPtr
) xalloc (sizeof (MultibuffersRec
) +
372 nbuf
* sizeof (MultibufferRec
));
375 pMultibuffers
->pWindow
= pWin
;
376 pMultibuffers
->buffers
= (MultibufferPtr
) (pMultibuffers
+ 1);
377 pMultibuffers
->refcnt
= pMultibuffers
->numMultibuffer
= 0;
378 if (!AddResource (pWin
->drawable
.id
, MultibuffersResType
, (pointer
) pMultibuffers
))
380 width
= pWin
->drawable
.width
;
381 height
= pWin
->drawable
.height
;
382 depth
= pWin
->drawable
.depth
;
383 pScreen
= pWin
->drawable
.pScreen
;
385 if (pWin
->backgroundState
!= None
)
387 pClearGC
= GetScratchGC (pWin
->drawable
.depth
, pScreen
);
388 SetupBackgroundPainter (pWin
, pClearGC
);
389 clearRect
.x
= clearRect
.y
= 0;
390 clearRect
.width
= width
;
391 clearRect
.height
= height
;
394 for (i
= 0; i
< nbuf
; i
++)
396 pMultibuffer
= &pMultibuffers
->buffers
[i
];
397 pMultibuffer
->eventMask
= 0L;
398 pMultibuffer
->otherEventMask
= 0L;
399 pMultibuffer
->otherClients
= (OtherClientsPtr
) NULL
;
400 pMultibuffer
->number
= i
;
401 pMultibuffer
->side
= MultibufferSideMono
;
402 pMultibuffer
->clobber
= MultibufferUnclobbered
;
403 pMultibuffer
->pMultibuffers
= pMultibuffers
;
404 if (!AddResource (ids
[i
], MultibufferResType
, (pointer
) pMultibuffer
))
406 pMultibuffer
->pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
, depth
);
407 if (!pMultibuffer
->pPixmap
)
409 if (!AddResource (ids
[i
], MultibufferDrawableResType
, (pointer
) pMultibuffer
->pPixmap
))
411 FreeResource (ids
[i
], MultibufferResType
);
412 (*pScreen
->DestroyPixmap
) (pMultibuffer
->pPixmap
);
415 pMultibuffer
->pPixmap
->drawable
.id
= ids
[i
];
417 if (i
> 0 && pClearGC
)
419 ValidateGC((DrawablePtr
)pMultibuffer
->pPixmap
, pClearGC
);
420 (*pClearGC
->ops
->PolyFillRect
)((DrawablePtr
)pMultibuffer
->pPixmap
,
421 pClearGC
, 1, &clearRect
);
424 pMultibuffers
->numMultibuffer
= i
;
425 pMultibuffers
->refcnt
= i
;
426 pMultibuffers
->displayedMultibuffer
= -1;
428 AliasMultibuffer (pMultibuffers
, 0);
429 pMultibuffers
->updateAction
= action
;
430 pMultibuffers
->updateHint
= hint
;
431 pMultibuffers
->windowMode
= MultibufferModeMono
;
432 pMultibuffers
->lastUpdate
.months
= 0;
433 pMultibuffers
->lastUpdate
.milliseconds
= 0;
434 pMultibuffers
->width
= width
;
435 pMultibuffers
->height
= height
;
436 pWin
->devPrivates
[MultibufferWindowIndex
].ptr
= (pointer
) pMultibuffers
;
437 if (pClearGC
) FreeScratchGC(pClearGC
);
443 ProcCreateImageBuffers (client
)
444 register ClientPtr client
;
446 REQUEST(xMbufCreateImageBuffersReq
);
447 xMbufCreateImageBuffersReply rep
;
451 int len
, nbuf
, i
, err
, rc
;
453 REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq
);
454 len
= stuff
->length
- (sizeof(xMbufCreateImageBuffersReq
) >> 2);
457 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
460 if (pWin
->drawable
.class == InputOnly
)
462 switch (stuff
->updateAction
)
464 case MultibufferUpdateActionUndefined
:
465 case MultibufferUpdateActionBackground
:
466 case MultibufferUpdateActionUntouched
:
467 case MultibufferUpdateActionCopied
:
470 client
->errorValue
= stuff
->updateAction
;
473 switch (stuff
->updateHint
)
475 case MultibufferUpdateHintFrequent
:
476 case MultibufferUpdateHintIntermittent
:
477 case MultibufferUpdateHintStatic
:
480 client
->errorValue
= stuff
->updateHint
;
484 ids
= (XID
*) &stuff
[1];
485 for (i
= 0; i
< nbuf
; i
++)
487 LEGAL_NEW_RESOURCE(ids
[i
], client
);
489 err
= CreateImageBuffers (pWin
, nbuf
, ids
,
490 stuff
->updateAction
, stuff
->updateHint
);
495 rep
.sequenceNumber
= client
->sequence
;
496 rep
.numberBuffer
= ((MultibuffersPtr
) (pWin
->devPrivates
[MultibufferWindowIndex
].ptr
))->numMultibuffer
;
499 swaps(&rep
.sequenceNumber
, n
);
500 swapl(&rep
.length
, n
);
501 swaps(&rep
.numberBuffer
, n
);
503 WriteToClient(client
, sizeof (xMbufCreateImageBuffersReply
), (char*)&rep
);
504 return (client
->noClientException
);
508 ProcDisplayImageBuffers (client
)
509 register ClientPtr client
;
511 REQUEST(xMbufDisplayImageBuffersReq
);
512 MultibufferPtr
*pMultibuffer
;
513 MultibuffersPtr
*ppMultibuffers
;
518 TimeStamp activateTime
, bufferTime
;
521 REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq
);
522 nbuf
= stuff
->length
- (sizeof (xMbufDisplayImageBuffersReq
) >> 2);
525 minDelay
= stuff
->minDelay
;
526 ids
= (XID
*) &stuff
[1];
527 ppMultibuffers
= (MultibuffersPtr
*) ALLOCATE_LOCAL(nbuf
* sizeof (MultibuffersPtr
));
528 pMultibuffer
= (MultibufferPtr
*) ALLOCATE_LOCAL(nbuf
* sizeof (MultibufferPtr
));
529 if (!ppMultibuffers
|| !pMultibuffer
)
531 if (ppMultibuffers
) DEALLOCATE_LOCAL(ppMultibuffers
);
532 if (pMultibuffer
) DEALLOCATE_LOCAL(pMultibuffer
);
533 client
->errorValue
= 0;
536 activateTime
.months
= 0;
537 activateTime
.milliseconds
= 0;
538 for (i
= 0; i
< nbuf
; i
++)
540 pMultibuffer
[i
] = (MultibufferPtr
) LookupIDByType (ids
[i
],
542 if (!pMultibuffer
[i
])
544 DEALLOCATE_LOCAL(ppMultibuffers
);
545 DEALLOCATE_LOCAL(pMultibuffer
);
546 client
->errorValue
= ids
[i
];
547 return MultibufferErrorBase
+ MultibufferBadBuffer
;
549 ppMultibuffers
[i
] = pMultibuffer
[i
]->pMultibuffers
;
550 for (j
= 0; j
< i
; j
++)
552 if (ppMultibuffers
[i
] == ppMultibuffers
[j
])
554 DEALLOCATE_LOCAL(ppMultibuffers
);
555 DEALLOCATE_LOCAL(pMultibuffer
);
556 client
->errorValue
= ids
[i
];
560 bufferTime
= ppMultibuffers
[i
]->lastUpdate
;
561 BumpTimeStamp (&bufferTime
, minDelay
);
562 if (CompareTimeStamps (bufferTime
, activateTime
) == LATER
)
563 activateTime
= bufferTime
;
565 UpdateCurrentTime ();
566 if (CompareTimeStamps (activateTime
, currentTime
) == LATER
&&
567 QueueDisplayRequest (client
, activateTime
))
572 PerformDisplayRequest (ppMultibuffers
, pMultibuffer
, nbuf
);
574 DEALLOCATE_LOCAL(ppMultibuffers
);
575 DEALLOCATE_LOCAL(pMultibuffer
);
581 ProcDestroyImageBuffers (client
)
582 register ClientPtr client
;
584 REQUEST (xMbufDestroyImageBuffersReq
);
588 REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq
);
589 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
592 DestroyImageBuffers (pWin
);
597 ProcSetMBufferAttributes (client
)
598 register ClientPtr client
;
600 REQUEST (xMbufSetMBufferAttributesReq
);
602 MultibuffersPtr pMultibuffers
;
609 REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq
);
610 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
613 pMultibuffers
= (MultibuffersPtr
)LookupIDByType (pWin
->drawable
.id
, MultibuffersResType
);
616 len
= stuff
->length
- (sizeof (xMbufSetMBufferAttributesReq
) >> 2);
617 vmask
= stuff
->valueMask
;
618 if (len
!= Ones (vmask
))
620 vlist
= (XID
*) &stuff
[1];
623 index2
= (Mask
) lowbit (vmask
);
627 case MultibufferWindowUpdateHint
:
628 updateHint
= (CARD32
) *vlist
;
631 case MultibufferUpdateHintFrequent
:
632 case MultibufferUpdateHintIntermittent
:
633 case MultibufferUpdateHintStatic
:
634 pMultibuffers
->updateHint
= updateHint
;
637 client
->errorValue
= updateHint
;
643 client
->errorValue
= stuff
->valueMask
;
651 ProcGetMBufferAttributes (client
)
654 REQUEST (xMbufGetMBufferAttributesReq
);
656 MultibuffersPtr pMultibuffers
;
658 xMbufGetMBufferAttributesReply rep
;
661 REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq
);
662 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
665 pMultibuffers
= (MultibuffersPtr
)LookupIDByType (pWin
->drawable
.id
, MultibuffersResType
);
668 ids
= (XID
*) ALLOCATE_LOCAL (pMultibuffers
->numMultibuffer
* sizeof (XID
));
671 for (i
= 0; i
< pMultibuffers
->numMultibuffer
; i
++)
672 ids
[i
] = pMultibuffers
->buffers
[i
].pPixmap
->drawable
.id
;
674 rep
.sequenceNumber
= client
->sequence
;
675 rep
.length
= pMultibuffers
->numMultibuffer
;
676 rep
.displayedBuffer
= pMultibuffers
->displayedMultibuffer
;
677 rep
.updateAction
= pMultibuffers
->updateAction
;
678 rep
.updateHint
= pMultibuffers
->updateHint
;
679 rep
.windowMode
= pMultibuffers
->windowMode
;
682 swaps(&rep
.sequenceNumber
, n
);
683 swapl(&rep
.length
, n
);
684 swaps(&rep
.displayedBuffer
, n
);
685 SwapLongs (ids
, pMultibuffers
->numMultibuffer
);
687 WriteToClient (client
, sizeof(xMbufGetMBufferAttributesReply
),
689 WriteToClient (client
, (int)(pMultibuffers
->numMultibuffer
* sizeof (XID
)),
691 DEALLOCATE_LOCAL((pointer
) ids
);
692 return client
->noClientException
;
696 ProcSetBufferAttributes (client
)
697 register ClientPtr client
;
699 REQUEST(xMbufSetBufferAttributesReq
);
700 MultibufferPtr pMultibuffer
;
707 REQUEST_AT_LEAST_SIZE (xMbufSetBufferAttributesReq
);
708 pMultibuffer
= (MultibufferPtr
) LookupIDByType (stuff
->buffer
, MultibufferResType
);
710 return MultibufferErrorBase
+ MultibufferBadBuffer
;
711 len
= stuff
->length
- (sizeof (xMbufSetBufferAttributesReq
) >> 2);
712 vmask
= stuff
->valueMask
;
713 if (len
!= Ones (vmask
))
715 vlist
= (XID
*) &stuff
[1];
718 index2
= (Mask
) lowbit (vmask
);
722 case MultibufferBufferEventMask
:
723 eventMask
= (Mask
) *vlist
;
725 result
= EventSelectForMultibuffer (pMultibuffer
, client
, eventMask
);
726 if (result
!= Success
)
730 client
->errorValue
= stuff
->valueMask
;
738 ProcGetBufferAttributes (client
)
739 register ClientPtr client
;
741 REQUEST(xMbufGetBufferAttributesReq
);
742 MultibufferPtr pMultibuffer
;
743 xMbufGetBufferAttributesReply rep
;
744 OtherClientsPtr other
;
747 REQUEST_SIZE_MATCH (xMbufGetBufferAttributesReq
);
748 pMultibuffer
= (MultibufferPtr
) LookupIDByType (stuff
->buffer
, MultibufferResType
);
750 return MultibufferErrorBase
+ MultibufferBadBuffer
;
752 rep
.sequenceNumber
= client
->sequence
;
754 rep
.window
= pMultibuffer
->pMultibuffers
->pWindow
->drawable
.id
;
755 if (bClient (pMultibuffer
) == client
)
756 rep
.eventMask
= pMultibuffer
->eventMask
;
759 rep
.eventMask
= (Mask
) 0L;
760 for (other
= pMultibuffer
->otherClients
; other
; other
= other
->next
)
761 if (SameClient (other
, client
))
763 rep
.eventMask
= other
->mask
;
767 rep
.bufferIndex
= pMultibuffer
->number
;
768 rep
.side
= pMultibuffer
->side
;
771 swaps(&rep
.sequenceNumber
, n
);
772 swapl(&rep
.length
, n
);
773 swapl(&rep
.window
, n
);
774 swapl(&rep
.eventMask
, n
);
775 swaps(&rep
.bufferIndex
, n
);
777 WriteToClient(client
, sizeof (xMbufGetBufferAttributesReply
), (char *)&rep
);
778 return (client
->noClientException
);
782 ProcGetBufferInfo (client
)
783 register ClientPtr client
;
785 REQUEST (xMbufGetBufferInfoReq
);
786 DrawablePtr pDrawable
;
787 xMbufGetBufferInfoReply rep
;
790 xMbufBufferInfo
*pInfo
;
794 rc
= dixLookupDrawable(&pDrawable
, stuff
->drawable
, client
, 0,
798 pScreen
= pDrawable
->pScreen
;
800 for (i
= 0; i
< pScreen
->numDepths
; i
++)
802 pDepth
= &pScreen
->allowedDepths
[i
];
803 nInfo
+= pDepth
->numVids
;
805 pInfo
= (xMbufBufferInfo
*)
806 ALLOCATE_LOCAL (nInfo
* sizeof (xMbufBufferInfo
));
811 rep
.sequenceNumber
= client
->sequence
;
812 rep
.length
= nInfo
* (sizeof (xMbufBufferInfo
) >> 2);
813 rep
.normalInfo
= nInfo
;
817 swaps(&rep
.sequenceNumber
, n
);
818 swapl(&rep
.length
, n
);
819 swaps(&rep
.normalInfo
, n
);
820 swaps(&rep
.stereoInfo
, n
);
824 for (i
= 0; i
< pScreen
->numDepths
; i
++)
826 pDepth
= &pScreen
->allowedDepths
[i
];
827 for (j
= 0; j
< pDepth
->numVids
; j
++)
829 pInfo
[k
].visualID
= pDepth
->vids
[j
];
830 pInfo
[k
].maxBuffers
= 0;
831 pInfo
[k
].depth
= pDepth
->depth
;
834 swapl (&pInfo
[k
].visualID
, n
);
835 swaps (&pInfo
[k
].maxBuffers
, n
);
840 WriteToClient (client
, sizeof (xMbufGetBufferInfoReply
), (pointer
) &rep
);
841 WriteToClient (client
, (int) nInfo
* sizeof (xMbufBufferInfo
), (pointer
) pInfo
);
842 DEALLOCATE_LOCAL ((pointer
) pInfo
);
843 return client
->noClientException
;
847 ProcClearImageBufferArea (client
)
848 register ClientPtr client
;
850 REQUEST (xMbufClearImageBufferAreaReq
);
851 MultibufferPtr pMultibuffer
;
853 xRectangle clearRect
;
855 DrawablePtr pDrawable
;
858 REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq
);
859 pMultibuffer
= (MultibufferPtr
) LookupIDByType (stuff
->buffer
, MultibufferResType
);
861 return MultibufferErrorBase
+ MultibufferBadBuffer
;
862 if ((stuff
->exposures
!= xTrue
) && (stuff
->exposures
!= xFalse
))
864 client
->errorValue
= stuff
->exposures
;
867 pWin
= pMultibuffer
->pMultibuffers
->pWindow
;
868 width
= pWin
->drawable
.width
;
869 height
= pWin
->drawable
.height
;
870 pScreen
= pWin
->drawable
.pScreen
;
872 clearRect
.x
= stuff
->x
;
873 clearRect
.y
= stuff
->y
;
874 clearRect
.width
= stuff
->width
? stuff
->width
: width
;
875 clearRect
.height
= stuff
->height
? stuff
->height
: height
;
877 if (pWin
->backgroundState
!= None
)
880 pClearGC
= GetScratchGC (pWin
->drawable
.depth
, pScreen
);
881 SetupBackgroundPainter (pWin
, pClearGC
);
883 if (pMultibuffer
->number
== pMultibuffer
->pMultibuffers
->displayedMultibuffer
)
884 pDrawable
= (DrawablePtr
)pWin
;
886 pDrawable
= (DrawablePtr
)pMultibuffer
->pPixmap
;
888 ValidateGC(pDrawable
, pClearGC
);
889 (*pClearGC
->ops
->PolyFillRect
) (pDrawable
, pClearGC
, 1, &clearRect
);
890 FreeScratchGC(pClearGC
);
893 if (stuff
->exposures
)
897 box
.x1
= clearRect
.x
;
898 box
.y1
= clearRect
.y
;
899 box
.x2
= clearRect
.x
+ clearRect
.width
;
900 box
.y2
= clearRect
.y
+ clearRect
.height
;
901 REGION_INIT(pScreen
, ®ion
, &box
, 1);
902 MultibufferExpose(pMultibuffer
, ®ion
);
903 REGION_UNINIT(pScreen
, ®ion
);
909 ProcMultibufferDispatch (client
)
910 register ClientPtr client
;
913 switch (stuff
->data
) {
914 case X_MbufGetBufferVersion
:
915 return ProcGetBufferVersion (client
);
916 case X_MbufCreateImageBuffers
:
917 return ProcCreateImageBuffers (client
);
918 case X_MbufDisplayImageBuffers
:
919 return ProcDisplayImageBuffers (client
);
920 case X_MbufDestroyImageBuffers
:
921 return ProcDestroyImageBuffers (client
);
922 case X_MbufSetMBufferAttributes
:
923 return ProcSetMBufferAttributes (client
);
924 case X_MbufGetMBufferAttributes
:
925 return ProcGetMBufferAttributes (client
);
926 case X_MbufSetBufferAttributes
:
927 return ProcSetBufferAttributes (client
);
928 case X_MbufGetBufferAttributes
:
929 return ProcGetBufferAttributes (client
);
930 case X_MbufGetBufferInfo
:
931 return ProcGetBufferInfo (client
);
932 case X_MbufClearImageBufferArea
:
933 return ProcClearImageBufferArea (client
);
940 SProcGetBufferVersion (client
)
941 register ClientPtr client
;
944 REQUEST (xMbufGetBufferVersionReq
);
946 swaps (&stuff
->length
, n
);
947 return ProcGetBufferVersion (client
);
951 SProcCreateImageBuffers (client
)
952 register ClientPtr client
;
955 REQUEST (xMbufCreateImageBuffersReq
);
957 swaps (&stuff
->length
, n
);
958 REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq
);
959 swapl (&stuff
->window
, n
);
961 return ProcCreateImageBuffers (client
);
965 SProcDisplayImageBuffers (client
)
966 register ClientPtr client
;
969 REQUEST (xMbufDisplayImageBuffersReq
);
971 swaps (&stuff
->length
, n
);
972 REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq
);
973 swaps (&stuff
->minDelay
, n
);
974 swaps (&stuff
->maxDelay
, n
);
976 return ProcDisplayImageBuffers (client
);
980 SProcDestroyImageBuffers (client
)
981 register ClientPtr client
;
984 REQUEST (xMbufDestroyImageBuffersReq
);
986 swaps (&stuff
->length
, n
);
987 REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq
);
988 swapl (&stuff
->window
, n
);
989 return ProcDestroyImageBuffers (client
);
993 SProcSetMBufferAttributes (client
)
994 register ClientPtr client
;
997 REQUEST (xMbufSetMBufferAttributesReq
);
999 swaps (&stuff
->length
, n
);
1000 REQUEST_AT_LEAST_SIZE(xMbufSetMBufferAttributesReq
);
1001 swapl (&stuff
->window
, n
);
1002 swapl (&stuff
->valueMask
, n
);
1004 return ProcSetMBufferAttributes (client
);
1008 SProcGetMBufferAttributes (client
)
1009 register ClientPtr client
;
1012 REQUEST (xMbufGetMBufferAttributesReq
);
1014 swaps (&stuff
->length
, n
);
1015 REQUEST_AT_LEAST_SIZE(xMbufGetMBufferAttributesReq
);
1016 swapl (&stuff
->window
, n
);
1017 return ProcGetMBufferAttributes (client
);
1021 SProcSetBufferAttributes (client
)
1022 register ClientPtr client
;
1025 REQUEST (xMbufSetBufferAttributesReq
);
1027 swaps (&stuff
->length
, n
);
1028 REQUEST_AT_LEAST_SIZE(xMbufSetBufferAttributesReq
);
1029 swapl (&stuff
->buffer
, n
);
1030 swapl (&stuff
->valueMask
, n
);
1032 return ProcSetBufferAttributes (client
);
1036 SProcGetBufferAttributes (client
)
1037 register ClientPtr client
;
1040 REQUEST (xMbufGetBufferAttributesReq
);
1042 swaps (&stuff
->length
, n
);
1043 REQUEST_AT_LEAST_SIZE(xMbufGetBufferAttributesReq
);
1044 swapl (&stuff
->buffer
, n
);
1045 return ProcGetBufferAttributes (client
);
1049 SProcGetBufferInfo (client
)
1050 register ClientPtr client
;
1053 REQUEST (xMbufGetBufferInfoReq
);
1055 swaps (&stuff
->length
, n
);
1056 REQUEST_SIZE_MATCH (xMbufGetBufferInfoReq
);
1057 swapl (&stuff
->drawable
, n
);
1058 return ProcGetBufferInfo (client
);
1062 SProcClearImageBufferArea(client
)
1063 register ClientPtr client
;
1066 REQUEST(xMbufClearImageBufferAreaReq
);
1068 swaps(&stuff
->length
, n
);
1069 REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq
);
1070 swapl(&stuff
->buffer
, n
);
1071 swaps(&stuff
->x
, n
);
1072 swaps(&stuff
->y
, n
);
1073 swaps(&stuff
->width
, n
);
1074 swaps(&stuff
->height
, n
);
1075 return ProcClearImageBufferArea(client
);
1079 SProcMultibufferDispatch (client
)
1080 register ClientPtr client
;
1083 switch (stuff
->data
) {
1084 case X_MbufGetBufferVersion
:
1085 return SProcGetBufferVersion (client
);
1086 case X_MbufCreateImageBuffers
:
1087 return SProcCreateImageBuffers (client
);
1088 case X_MbufDisplayImageBuffers
:
1089 return SProcDisplayImageBuffers (client
);
1090 case X_MbufDestroyImageBuffers
:
1091 return SProcDestroyImageBuffers (client
);
1092 case X_MbufSetMBufferAttributes
:
1093 return SProcSetMBufferAttributes (client
);
1094 case X_MbufGetMBufferAttributes
:
1095 return SProcGetMBufferAttributes (client
);
1096 case X_MbufSetBufferAttributes
:
1097 return SProcSetBufferAttributes (client
);
1098 case X_MbufGetBufferAttributes
:
1099 return SProcGetBufferAttributes (client
);
1100 case X_MbufGetBufferInfo
:
1101 return SProcGetBufferInfo (client
);
1102 case X_MbufClearImageBufferArea
:
1103 return SProcClearImageBufferArea (client
);
1110 SUpdateNotifyEvent (from
, to
)
1111 xMbufUpdateNotifyEvent
*from
, *to
;
1113 to
->type
= from
->type
;
1114 cpswaps (from
->sequenceNumber
, to
->sequenceNumber
);
1115 cpswapl (from
->buffer
, to
->buffer
);
1116 cpswapl (from
->timeStamp
, to
->timeStamp
);
1120 SClobberNotifyEvent (from
, to
)
1121 xMbufClobberNotifyEvent
*from
, *to
;
1123 to
->type
= from
->type
;
1124 cpswaps (from
->sequenceNumber
, to
->sequenceNumber
);
1125 cpswapl (from
->buffer
, to
->buffer
);
1126 to
->state
= from
->state
;
1130 PerformDisplayRequest (ppMultibuffers
, pMultibuffer
, nbuf
)
1131 MultibufferPtr
*pMultibuffer
;
1132 MultibuffersPtr
*ppMultibuffers
;
1136 PixmapPtr pPrevPixmap
, pNewPixmap
;
1137 xRectangle clearRect
;
1141 MultibufferPtr pPrevMultibuffer
;
1144 UpdateCurrentTime ();
1145 for (i
= 0; i
< nbuf
; i
++)
1147 pWin
= ppMultibuffers
[i
]->pWindow
;
1148 pGC
= GetScratchGC (pWin
->drawable
.depth
, pWin
->drawable
.pScreen
);
1150 &ppMultibuffers
[i
]->buffers
[ppMultibuffers
[i
]->displayedMultibuffer
];
1151 pPrevPixmap
= pPrevMultibuffer
->pPixmap
;
1152 pNewPixmap
= pMultibuffer
[i
]->pPixmap
;
1153 switch (ppMultibuffers
[i
]->updateAction
)
1155 case MultibufferUpdateActionUndefined
:
1157 case MultibufferUpdateActionBackground
:
1158 SetupBackgroundPainter (pWin
, pGC
);
1159 ValidateGC ((DrawablePtr
)pPrevPixmap
, pGC
);
1162 clearRect
.width
= pPrevPixmap
->drawable
.width
;
1163 clearRect
.height
= pPrevPixmap
->drawable
.height
;
1164 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
)pPrevPixmap
, pGC
,
1167 case MultibufferUpdateActionUntouched
:
1168 /* copy the window to the pixmap that represents the
1169 * currently displayed buffer
1171 if (pPrevMultibuffer
->eventMask
& ExposureMask
)
1173 graphicsExpose
= TRUE
;
1174 DoChangeGC (pGC
, GCGraphicsExposures
, &graphicsExpose
, FALSE
);
1176 ValidateGC ((DrawablePtr
)pPrevPixmap
, pGC
);
1177 pExposed
= (*pGC
->ops
->CopyArea
)
1178 ((DrawablePtr
) pWin
,
1179 (DrawablePtr
) pPrevPixmap
,
1182 pWin
->drawable
.width
, pWin
->drawable
.height
,
1185 /* if we couldn't copy the whole window to the buffer,
1186 * send expose events (if any client wants them)
1188 if (pPrevMultibuffer
->eventMask
& ExposureMask
)
1189 { /* some client wants expose events */
1194 pWinSize
= CreateUnclippedWinSize (pWin
);
1195 /* pExposed is window-relative, but at this point
1196 * pWinSize is screen-relative. Make pWinSize be
1197 * window-relative so that region ops involving
1198 * pExposed and pWinSize behave sensibly.
1200 REGION_TRANSLATE(pWin
->drawable
.pScreen
, pWinSize
,
1201 -pWin
->drawable
.x
, -pWin
->drawable
.y
);
1202 REGION_INTERSECT(pWin
->drawable
.pScreen
, pExposed
,
1203 pExposed
, pWinSize
);
1204 REGION_DESTROY(pWin
->drawable
.pScreen
, pWinSize
);
1205 MultibufferExpose (pPrevMultibuffer
, pExposed
);
1206 REGION_DESTROY(pWin
->drawable
.pScreen
, pExposed
);
1208 graphicsExpose
= FALSE
;
1209 DoChangeGC (pGC
, GCGraphicsExposures
, &graphicsExpose
, FALSE
);
1211 break; /* end case MultibufferUpdateActionUntouched */
1213 case MultibufferUpdateActionCopied
:
1214 ValidateGC ((DrawablePtr
)pPrevPixmap
, pGC
);
1215 (*pGC
->ops
->CopyArea
) ((DrawablePtr
)pNewPixmap
,
1216 (DrawablePtr
)pPrevPixmap
, pGC
,
1218 pWin
->drawable
.width
, pWin
->drawable
.height
,
1221 } /* end switch on update action */
1223 /* display the new buffer */
1224 ValidateGC ((DrawablePtr
)pWin
, pGC
);
1225 (*pGC
->ops
->CopyArea
) ((DrawablePtr
)pNewPixmap
, (DrawablePtr
)pWin
, pGC
,
1227 pWin
->drawable
.width
, pWin
->drawable
.height
,
1229 ppMultibuffers
[i
]->lastUpdate
= currentTime
;
1230 MultibufferUpdate (pMultibuffer
[i
],
1231 ppMultibuffers
[i
]->lastUpdate
.milliseconds
);
1232 AliasMultibuffer (ppMultibuffers
[i
],
1233 pMultibuffer
[i
] - ppMultibuffers
[i
]->buffers
);
1234 FreeScratchGC (pGC
);
1239 GetBufferPointer (pWin
, i
)
1243 MultibuffersPtr pMultibuffers
;
1245 if (!(pMultibuffers
= (MultibuffersPtr
) pWin
->devPrivates
[MultibufferWindowIndex
].ptr
))
1247 return (DrawablePtr
) pMultibuffers
->buffers
[i
].pPixmap
;
1251 DisplayImageBuffers (ids
, nbuf
)
1255 MultibufferPtr
*pMultibuffer
;
1256 MultibuffersPtr
*pMultibuffers
;
1259 pMultibuffer
= (MultibufferPtr
*) ALLOCATE_LOCAL (nbuf
* sizeof *pMultibuffer
+
1260 nbuf
* sizeof *pMultibuffers
);
1263 pMultibuffers
= (MultibuffersPtr
*) (pMultibuffer
+ nbuf
);
1264 for (i
= 0; i
< nbuf
; i
++)
1266 pMultibuffer
[i
] = (MultibufferPtr
) LookupIDByType (ids
[i
], MultibufferResType
);
1267 if (!pMultibuffer
[i
])
1269 DEALLOCATE_LOCAL (pMultibuffer
);
1270 return MultibufferErrorBase
+ MultibufferBadBuffer
;
1272 pMultibuffers
[i
] = pMultibuffer
[i
]->pMultibuffers
;
1273 for (j
= 0; j
< i
; j
++)
1274 if (pMultibuffers
[i
] == pMultibuffers
[j
])
1276 DEALLOCATE_LOCAL (pMultibuffer
);
1280 PerformDisplayRequest (pMultibuffers
, pMultibuffer
, nbuf
);
1281 DEALLOCATE_LOCAL (pMultibuffer
);
1287 QueueDisplayRequest (client
, activateTime
)
1289 TimeStamp activateTime
;
1291 /* see xtest.c:ProcXTestFakeInput for code similar to this */
1293 if (!ClientSleepUntil(client
, &activateTime
, NULL
, NULL
))
1297 /* swap the request back so we can simply re-execute it */
1298 if (client
->swapped
)
1301 REQUEST (xMbufDisplayImageBuffersReq
);
1304 swaps (&stuff
->length
, n
);
1305 swaps (&stuff
->minDelay
, n
);
1306 swaps (&stuff
->maxDelay
, n
);
1308 ResetCurrentRequest (client
);
1315 * Deliver events to a buffer
1319 DeliverEventsToMultibuffer (pMultibuffer
, pEvents
, count
, filter
)
1320 MultibufferPtr pMultibuffer
;
1325 int deliveries
= 0, nondeliveries
= 0;
1327 OtherClients
*other
;
1329 /* if nobody wants the event, we're done */
1330 if (!((pMultibuffer
->otherEventMask
|pMultibuffer
->eventMask
) & filter
))
1333 /* maybe send event to owner */
1334 if ((attempt
= TryClientEvents(
1335 bClient(pMultibuffer
), pEvents
, count
, pMultibuffer
->eventMask
, filter
, (GrabPtr
) 0)) != 0)
1343 /* maybe send event to other clients */
1344 for (other
= pMultibuffer
->otherClients
; other
; other
=other
->next
)
1346 if ((attempt
= TryClientEvents(
1347 rClient(other
), pEvents
, count
, other
->mask
, filter
, (GrabPtr
) 0)) != 0)
1357 return nondeliveries
;
1361 * Send Expose events to interested clients
1365 MultibufferExpose (pMultibuffer
, pRegion
)
1366 MultibufferPtr pMultibuffer
;
1369 if (pRegion
&& !REGION_NIL(pRegion
))
1373 register xEvent
*pe
;
1374 register BoxPtr pBox
;
1378 pPixmap
= pMultibuffer
->pPixmap
;
1379 REGION_TRANSLATE(pPixmap
->drawable
.pScreen
, pRegion
,
1380 -pPixmap
->drawable
.x
, -pPixmap
->drawable
.y
);
1381 /* XXX MultibufferExpose "knows" the region representation */
1382 numRects
= REGION_NUM_RECTS(pRegion
);
1383 pBox
= REGION_RECTS(pRegion
);
1385 pEvent
= (xEvent
*) ALLOCATE_LOCAL(numRects
* sizeof(xEvent
));
1389 for (i
=1; i
<=numRects
; i
++, pe
++, pBox
++)
1391 pe
->u
.u
.type
= Expose
;
1392 pe
->u
.expose
.window
= pPixmap
->drawable
.id
;
1393 pe
->u
.expose
.x
= pBox
->x1
;
1394 pe
->u
.expose
.y
= pBox
->y1
;
1395 pe
->u
.expose
.width
= pBox
->x2
- pBox
->x1
;
1396 pe
->u
.expose
.height
= pBox
->y2
- pBox
->y1
;
1397 pe
->u
.expose
.count
= (numRects
- i
);
1399 (void) DeliverEventsToMultibuffer (pMultibuffer
, pEvent
, numRects
,
1401 DEALLOCATE_LOCAL(pEvent
);
1406 /* send UpdateNotify event */
1408 MultibufferUpdate (pMultibuffer
, time2
)
1409 MultibufferPtr pMultibuffer
;
1412 xMbufUpdateNotifyEvent event
;
1414 event
.type
= MultibufferEventBase
+ MultibufferUpdateNotify
;
1415 event
.buffer
= pMultibuffer
->pPixmap
->drawable
.id
;
1416 event
.timeStamp
= time2
;
1417 (void) DeliverEventsToMultibuffer (pMultibuffer
, (xEvent
*)&event
,
1418 1, (Mask
)MultibufferUpdateNotifyMask
);
1422 * The sample implementation will never generate MultibufferClobberNotify
1427 MultibufferClobber (pMultibuffer
)
1428 MultibufferPtr pMultibuffer
;
1430 xMbufClobberNotifyEvent event
;
1432 event
.type
= MultibufferEventBase
+ MultibufferClobberNotify
;
1433 event
.buffer
= pMultibuffer
->pPixmap
->drawable
.id
;
1434 event
.state
= pMultibuffer
->clobber
;
1435 (void) DeliverEventsToMultibuffer (pMultibuffer
, (xEvent
*)&event
,
1436 1, (Mask
)MultibufferClobberNotifyMask
);
1440 * make the resource id for buffer i refer to the window
1441 * drawable instead of the pixmap;
1445 AliasMultibuffer (pMultibuffers
, i
)
1446 MultibuffersPtr pMultibuffers
;
1449 MultibufferPtr pMultibuffer
;
1451 if (i
== pMultibuffers
->displayedMultibuffer
)
1454 * remove the old association
1456 if (pMultibuffers
->displayedMultibuffer
>= 0)
1458 pMultibuffer
= &pMultibuffers
->buffers
[pMultibuffers
->displayedMultibuffer
];
1459 ChangeResourceValue (pMultibuffer
->pPixmap
->drawable
.id
,
1460 MultibufferDrawableResType
,
1461 (pointer
) pMultibuffer
->pPixmap
);
1464 * make the new association
1466 pMultibuffer
= &pMultibuffers
->buffers
[i
];
1467 ChangeResourceValue (pMultibuffer
->pPixmap
->drawable
.id
,
1468 MultibufferDrawableResType
,
1469 (pointer
) pMultibuffers
->pWindow
);
1470 pMultibuffers
->displayedMultibuffer
= i
;
1474 * free everything associated with multibuffering for this
1479 DestroyImageBuffers (pWin
)
1482 FreeResourceByType (pWin
->drawable
.id
, MultibuffersResType
, FALSE
);
1483 /* Zero out the window's pointer to the buffers so they won't be reused */
1484 pWin
->devPrivates
[MultibufferWindowIndex
].ptr
= NULL
;
1488 * resize the buffers when the window is resized
1492 MultibufferPositionWindow (pWin
, x
, y
)
1497 MultibufferScreenPtr pMultibufferScreen
;
1498 MultibuffersPtr pMultibuffers
;
1499 MultibufferPtr pMultibuffer
;
1503 int sourcex
, sourcey
;
1507 int savewidth
, saveheight
;
1508 xRectangle clearRect
;
1511 pScreen
= pWin
->drawable
.pScreen
;
1512 pMultibufferScreen
= (MultibufferScreenPtr
) pScreen
->devPrivates
[MultibufferScreenIndex
].ptr
;
1513 (*pMultibufferScreen
->PositionWindow
) (pWin
, x
, y
);
1515 /* if this window is not multibuffered, we're done */
1516 if (!(pMultibuffers
= (MultibuffersPtr
) pWin
->devPrivates
[MultibufferWindowIndex
].ptr
))
1519 /* if new size is same as old, we're done */
1520 if (pMultibuffers
->width
== pWin
->drawable
.width
&&
1521 pMultibuffers
->height
== pWin
->drawable
.height
)
1524 width
= pWin
->drawable
.width
;
1525 height
= pWin
->drawable
.height
;
1526 dx
= pWin
->drawable
.x
- pMultibuffers
->x
;
1527 dy
= pWin
->drawable
.x
- pMultibuffers
->y
;
1528 dw
= width
- pMultibuffers
->width
;
1529 dh
= height
- pMultibuffers
->height
;
1530 GravityTranslate (0, 0, -dx
, -dy
, dw
, dh
,
1531 pWin
->bitGravity
, &destx
, &desty
);
1533 /* if the window grew, remember to paint the window background,
1534 * and maybe send expose events, for the new areas of the buffers
1536 clear
= pMultibuffers
->width
< width
|| pMultibuffers
->height
< height
||
1537 pWin
->bitGravity
== ForgetGravity
;
1541 savewidth
= pMultibuffers
->width
;
1542 saveheight
= pMultibuffers
->height
;
1543 /* clip rectangle to source and destination */
1550 if (destx
+ savewidth
> width
)
1551 savewidth
= width
- destx
;
1554 saveheight
+= desty
;
1558 if (desty
+ saveheight
> height
)
1559 saveheight
= height
- desty
;
1561 pMultibuffers
->width
= width
;
1562 pMultibuffers
->height
= height
;
1563 pMultibuffers
->x
= pWin
->drawable
.x
;
1564 pMultibuffers
->y
= pWin
->drawable
.y
;
1566 pGC
= GetScratchGC (pWin
->drawable
.depth
, pScreen
);
1569 SetupBackgroundPainter (pWin
, pGC
);
1572 clearRect
.width
= width
;
1573 clearRect
.height
= height
;
1575 for (i
= 0; i
< pMultibuffers
->numMultibuffer
; i
++)
1577 pMultibuffer
= &pMultibuffers
->buffers
[i
];
1578 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
,
1579 pWin
->drawable
.depth
);
1582 DestroyImageBuffers (pWin
);
1585 ValidateGC ((DrawablePtr
)pPixmap
, pGC
);
1587 * I suppose this could avoid quite a bit of work if
1588 * it computed the minimal area required.
1591 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
)pPixmap
, pGC
, 1, &clearRect
);
1592 if (pWin
->bitGravity
!= ForgetGravity
)
1594 (*pGC
->ops
->CopyArea
) ((DrawablePtr
)pMultibuffer
->pPixmap
,
1595 (DrawablePtr
)pPixmap
, pGC
,
1596 sourcex
, sourcey
, savewidth
, saveheight
,
1599 pPixmap
->drawable
.id
= pMultibuffer
->pPixmap
->drawable
.id
;
1600 (*pScreen
->DestroyPixmap
) (pMultibuffer
->pPixmap
);
1601 pMultibuffer
->pPixmap
= pPixmap
;
1602 if (i
!= pMultibuffers
->displayedMultibuffer
)
1604 ChangeResourceValue (pPixmap
->drawable
.id
,
1605 MultibufferDrawableResType
,
1609 FreeScratchGC (pGC
);
1613 /* Resource delete func for MultibufferDrawableResType */
1616 MultibufferDrawableDelete (value
, id
)
1620 DrawablePtr pDrawable
= (DrawablePtr
)value
;
1622 MultibuffersPtr pMultibuffers
;
1625 if (pDrawable
->type
== DRAWABLE_WINDOW
)
1627 pWin
= (WindowPtr
) pDrawable
;
1628 pMultibuffers
= (MultibuffersPtr
) pWin
->devPrivates
[MultibufferWindowIndex
].ptr
;
1629 pPixmap
= pMultibuffers
->buffers
[pMultibuffers
->displayedMultibuffer
].pPixmap
;
1633 pPixmap
= (PixmapPtr
) pDrawable
;
1635 (*pPixmap
->drawable
.pScreen
->DestroyPixmap
) (pPixmap
);
1639 /* Resource delete func for MultibufferResType */
1642 MultibufferDelete (value
, id
)
1646 MultibufferPtr pMultibuffer
= (MultibufferPtr
)value
;
1647 MultibuffersPtr pMultibuffers
;
1649 pMultibuffers
= pMultibuffer
->pMultibuffers
;
1650 if (--pMultibuffers
->refcnt
== 0)
1652 FreeResourceByType (pMultibuffers
->pWindow
->drawable
.id
,
1653 MultibuffersResType
, TRUE
);
1654 xfree (pMultibuffers
);
1659 /* Resource delete func for MultibuffersResType */
1662 MultibuffersDelete (value
, id
)
1666 MultibuffersPtr pMultibuffers
= (MultibuffersPtr
)value
;
1669 if (pMultibuffers
->refcnt
== pMultibuffers
->numMultibuffer
)
1671 for (i
= pMultibuffers
->numMultibuffer
; --i
>= 0; )
1672 FreeResource (pMultibuffers
->buffers
[i
].pPixmap
->drawable
.id
, 0);
1677 /* Resource delete func for OtherClientResType */
1679 OtherClientDelete (value
, id
)
1683 MultibufferPtr pMultibuffer
= (MultibufferPtr
)value
;
1684 register OtherClientsPtr other
, prev
;
1687 for (other
= pMultibuffer
->otherClients
; other
; other
= other
->next
)
1689 if (other
->resource
== id
)
1692 prev
->next
= other
->next
;
1694 pMultibuffer
->otherClients
= other
->next
;
1696 RecalculateMultibufferOtherEvents (pMultibuffer
);
1705 EventSelectForMultibuffer (pMultibuffer
, client
, mask
)
1706 MultibufferPtr pMultibuffer
;
1710 OtherClientsPtr other
;
1712 if (mask
& ~ValidEventMasks
)
1714 client
->errorValue
= mask
;
1717 if (bClient (pMultibuffer
) == client
)
1719 pMultibuffer
->eventMask
= mask
;
1721 else /* some other client besides the creator wants events */
1723 for (other
= pMultibuffer
->otherClients
; other
; other
= other
->next
)
1725 if (SameClient (other
, client
))
1729 FreeResource (other
->resource
, RT_NONE
);
1737 { /* new client that never selected events on this buffer before */
1738 other
= (OtherClients
*) xalloc (sizeof (OtherClients
));
1742 other
->resource
= FakeClientID (client
->index
);
1743 if (!AddResource (other
->resource
, OtherClientResType
, (pointer
) pMultibuffer
))
1748 other
->next
= pMultibuffer
->otherClients
;
1749 pMultibuffer
->otherClients
= other
;
1751 RecalculateMultibufferOtherEvents (pMultibuffer
);
1753 return (client
->noClientException
);
1756 /* or together all the otherClients event masks */
1758 RecalculateMultibufferOtherEvents (pMultibuffer
)
1759 MultibufferPtr pMultibuffer
;
1761 Mask otherEventMask
;
1762 OtherClients
*other
;
1764 otherEventMask
= 0L;
1765 for (other
= pMultibuffer
->otherClients
; other
; other
= other
->next
)
1766 otherEventMask
|= other
->mask
;
1767 pMultibuffer
->otherEventMask
= otherEventMask
;
1770 /* add milliseconds to a timestamp, handling overflow */
1772 BumpTimeStamp (ts
, inc
)
1778 newms
= ts
->milliseconds
+ inc
;
1779 if (newms
< ts
->milliseconds
)
1781 ts
->milliseconds
= newms
;