1 /************************************************************
3 Copyright (c) 1989 X Consortium
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
26 ********************************************************/
28 /* $XConsortium: mbuf.c /main/25 1996/12/02 10:19:23 lehors $ */
29 /* $XFree86: xc/programs/Xserver/Xext/mbuf.c,v 3.3 1997/01/18 06:52:58 dawes Exp $ */
37 #include "windowstr.h"
38 #include "scrnintstr.h"
39 #include "pixmapstr.h"
40 #include "extnsionst.h"
41 #include "dixstruct.h"
44 #define _MULTIBUF_SERVER_ /* don't want Xlib structures */
45 #include "regionstr.h"
48 #include "multibufst.h"
49 #if !defined(WIN32) && !defined(MINIX) && !defined(Lynx)
53 /* given an OtherClientPtr obj, get the ClientPtr */
54 #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
56 /* given a MultibufferPtr b, get the ClientPtr */
57 #define bClient(b) (clients[CLIENT_ID(b->pPixmap->drawable.id)])
59 #define ValidEventMasks (ExposureMask|MultibufferClobberNotifyMask|MultibufferUpdateNotifyMask)
61 static unsigned char MultibufferReqCode;
62 static int MultibufferEventBase;
63 static int MultibufferErrorBase;
64 int MultibufferScreenIndex = -1;
65 int MultibufferWindowIndex = -1;
67 static void PerformDisplayRequest (
68 #if NeedFunctionPrototypes
69 MultibuffersPtr * /* ppMultibuffers */,
70 MultibufferPtr * /* pMultibuffer */,
74 static Bool QueueDisplayRequest (
75 #if NeedFunctionPrototypes
76 ClientPtr /* client */,
77 TimeStamp /* activateTime */
81 static void BumpTimeStamp (
82 #if NeedFunctionPrototypes
88 static void AliasMultibuffer (
89 #if NeedFunctionPrototypes
90 MultibuffersPtr /* pMultibuffers */,
94 static void RecalculateMultibufferOtherEvents (
95 #if NeedFunctionPrototypes
96 MultibufferPtr /* pMultibuffer */
99 static int EventSelectForMultibuffer(
100 #if NeedFunctionPrototypes
101 MultibufferPtr /* pMultibuffer */,
102 ClientPtr /* client */,
108 * The Pixmap associated with a buffer can be found as a resource
111 RESTYPE MultibufferDrawableResType;
112 static int MultibufferDrawableDelete (
113 #if NeedFunctionPrototypes
119 * The per-buffer data can be found as a resource with this type.
120 * the resource id of the per-buffer data is the same as the resource
123 static RESTYPE MultibufferResType;
124 static int MultibufferDelete (
125 #if NeedFunctionPrototypes
132 * The per-window data can be found as a resource with this type,
133 * using the window resource id
135 static RESTYPE MultibuffersResType;
136 static int MultibuffersDelete (
137 #if NeedFunctionPrototypes
144 * Clients other than the buffer creator attach event masks in
145 * OtherClient structures; each has a resource of this type.
147 static RESTYPE OtherClientResType;
148 static int OtherClientDelete (
149 #if NeedFunctionPrototypes
156 * MultibufferExtensionInit
158 * Called from InitExtensions in main()
162 extern DISPATCH_PROC(ProcGetBufferAttributes);
164 static DISPATCH_PROC(ProcClearImageBufferArea);
165 static DISPATCH_PROC(ProcCreateImageBuffers);
166 static DISPATCH_PROC(ProcDestroyImageBuffers);
167 static DISPATCH_PROC(ProcDisplayImageBuffers);
168 static DISPATCH_PROC(ProcGetBufferInfo);
169 static DISPATCH_PROC(ProcGetBufferVersion);
170 static DISPATCH_PROC(ProcGetMBufferAttributes);
171 static DISPATCH_PROC(ProcMultibufferDispatch);
172 static DISPATCH_PROC(ProcSetBufferAttributes);
173 static DISPATCH_PROC(ProcSetMBufferAttributes);
174 static DISPATCH_PROC(SProcClearImageBufferArea);
175 static DISPATCH_PROC(SProcCreateImageBuffers);
176 static DISPATCH_PROC(SProcDestroyImageBuffers);
177 static DISPATCH_PROC(SProcDisplayImageBuffers);
178 static DISPATCH_PROC(SProcGetBufferAttributes);
179 static DISPATCH_PROC(SProcGetBufferInfo);
180 static DISPATCH_PROC(SProcGetBufferVersion);
181 static DISPATCH_PROC(SProcGetMBufferAttributes);
182 static DISPATCH_PROC(SProcMultibufferDispatch);
183 static DISPATCH_PROC(SProcSetBufferAttributes);
184 static DISPATCH_PROC(SProcSetMBufferAttributes);
186 static void MultibufferResetProc(
187 #if NeedFunctionPrototypes
188 ExtensionEntry * /* extEntry */
191 static void SClobberNotifyEvent(
192 #if NeedFunctionPrototypes
193 xMbufClobberNotifyEvent * /* from */,
194 xMbufClobberNotifyEvent * /* to */
197 static void SUpdateNotifyEvent(
198 #if NeedFunctionPrototypes
199 xMbufUpdateNotifyEvent * /* from */,
200 xMbufUpdateNotifyEvent * /* to */
203 static Bool MultibufferPositionWindow(
204 #if NeedFunctionPrototypes
205 WindowPtr /* pWin */,
211 static void SetupBackgroundPainter (
212 #if NeedFunctionPrototypes
213 WindowPtr /* pWin */,
218 static int DeliverEventsToMultibuffer (
219 #if NeedFunctionPrototypes
220 MultibufferPtr /* pMultibuffer */,
221 xEvent * /* pEvents */,
228 MultibufferExtensionInit()
230 ExtensionEntry *extEntry;
233 MultibufferScreenPtr pMultibufferScreen;
236 * allocate private pointers in windows and screens. Allocating
237 * window privates may seem like an unnecessary expense, but every
238 * PositionWindow call must check to see if the window is
239 * multi-buffered; a resource lookup is too expensive.
241 MultibufferScreenIndex = AllocateScreenPrivateIndex ();
242 if (MultibufferScreenIndex < 0)
244 MultibufferWindowIndex = AllocateWindowPrivateIndex ();
245 for (i = 0; i < screenInfo.numScreens; i++)
247 pScreen = screenInfo.screens[i];
248 if (!AllocateWindowPrivate (pScreen, MultibufferWindowIndex, 0) ||
249 !(pMultibufferScreen = (MultibufferScreenPtr) xalloc (sizeof (MultibufferScreenRec))))
251 for (j = 0; j < i; j++)
252 xfree (screenInfo.screens[j]->devPrivates[MultibufferScreenIndex].ptr);
255 pScreen->devPrivates[MultibufferScreenIndex].ptr = (pointer) pMultibufferScreen;
257 * wrap PositionWindow to resize the pixmap when the window
260 pMultibufferScreen->PositionWindow = pScreen->PositionWindow;
261 pScreen->PositionWindow = MultibufferPositionWindow;
264 * create the resource types
266 MultibufferDrawableResType =
267 CreateNewResourceType(MultibufferDrawableDelete)|RC_CACHED|RC_DRAWABLE;
268 MultibufferResType = CreateNewResourceType(MultibufferDelete);
269 MultibuffersResType = CreateNewResourceType(MultibuffersDelete);
270 OtherClientResType = CreateNewResourceType(OtherClientDelete);
271 if (MultibufferDrawableResType && MultibufferResType &&
272 MultibuffersResType && OtherClientResType &&
273 (extEntry = AddExtension(MULTIBUFFER_PROTOCOL_NAME,
274 MultibufferNumberEvents,
275 MultibufferNumberErrors,
276 ProcMultibufferDispatch, SProcMultibufferDispatch,
277 MultibufferResetProc, StandardMinorOpcode)))
279 MultibufferReqCode = (unsigned char)extEntry->base;
280 MultibufferEventBase = extEntry->eventBase;
281 MultibufferErrorBase = extEntry->errorBase;
282 EventSwapVector[MultibufferEventBase + MultibufferClobberNotify] = (EventSwapPtr) SClobberNotifyEvent;
283 EventSwapVector[MultibufferEventBase + MultibufferUpdateNotify] = (EventSwapPtr) SUpdateNotifyEvent;
289 MultibufferResetProc (extEntry)
290 ExtensionEntry *extEntry;
294 MultibufferScreenPtr pMultibufferScreen;
296 if (MultibufferScreenIndex < 0)
298 for (i = 0; i < screenInfo.numScreens; i++)
300 pScreen = screenInfo.screens[i];
301 if (pScreen->devPrivates[MultibufferScreenIndex].ptr)
303 pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr;
304 pScreen->PositionWindow = pMultibufferScreen->PositionWindow;
305 xfree (pMultibufferScreen);
311 ProcGetBufferVersion (client)
312 register ClientPtr client;
314 xMbufGetBufferVersionReply rep;
317 REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq);
320 rep.sequenceNumber = client->sequence;
321 rep.majorVersion = MULTIBUFFER_MAJOR_VERSION;
322 rep.minorVersion = MULTIBUFFER_MINOR_VERSION;
323 if (client->swapped) {
324 swaps(&rep.sequenceNumber, n);
325 swapl(&rep.length, n);
327 WriteToClient(client, sizeof (xMbufGetBufferVersionReply), (char *)&rep);
328 return (client->noClientException);
332 SetupBackgroundPainter (pWin, pGC)
337 int ts_x_origin, ts_y_origin;
343 * First take care of any ParentRelative stuff by altering the
344 * tile/stipple origin to match the coordinates of the upper-left
345 * corner of the first ancestor without a ParentRelative background.
346 * This coordinate is, of course, negative.
349 ts_x_origin = ts_y_origin = 0;
350 while (pWin->backgroundState == ParentRelative) {
351 ts_x_origin -= pWin->origin.x;
352 ts_y_origin -= pWin->origin.y;
355 backgroundState = pWin->backgroundState;
356 background = pWin->background;
358 switch (backgroundState)
360 case BackgroundPixel:
361 gcvalues[0] = (pointer) background.pixel;
362 gcvalues[1] = (pointer) FillSolid;
363 gcmask = GCForeground|GCFillStyle;
366 case BackgroundPixmap:
367 gcvalues[0] = (pointer) FillTiled;
368 gcvalues[1] = (pointer) background.pixmap;
369 gcvalues[2] = (pointer) ts_x_origin;
370 gcvalues[3] = (pointer) ts_y_origin;
371 gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
375 gcvalues[0] = (pointer) GXnoop;
378 DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE);
382 CreateImageBuffers (pWin, nbuf, ids, action, hint)
389 MultibuffersPtr pMultibuffers;
390 MultibufferPtr pMultibuffer;
392 int width, height, depth;
394 GCPtr pClearGC = NULL;
395 xRectangle clearRect;
397 DestroyImageBuffers(pWin);
398 pMultibuffers = (MultibuffersPtr) xalloc (sizeof (MultibuffersRec) +
399 nbuf * sizeof (MultibufferRec));
402 pMultibuffers->pWindow = pWin;
403 pMultibuffers->buffers = (MultibufferPtr) (pMultibuffers + 1);
404 pMultibuffers->refcnt = pMultibuffers->numMultibuffer = 0;
405 if (!AddResource (pWin->drawable.id, MultibuffersResType, (pointer) pMultibuffers))
407 width = pWin->drawable.width;
408 height = pWin->drawable.height;
409 depth = pWin->drawable.depth;
410 pScreen = pWin->drawable.pScreen;
412 if (pWin->backgroundState != None)
414 pClearGC = GetScratchGC (pWin->drawable.depth, pScreen);
415 SetupBackgroundPainter (pWin, pClearGC);
416 clearRect.x = clearRect.y = 0;
417 clearRect.width = width;
418 clearRect.height = height;
421 for (i = 0; i < nbuf; i++)
423 pMultibuffer = &pMultibuffers->buffers[i];
424 pMultibuffer->eventMask = 0L;
425 pMultibuffer->otherEventMask = 0L;
426 pMultibuffer->otherClients = (OtherClientsPtr) NULL;
427 pMultibuffer->number = i;
428 pMultibuffer->side = MultibufferSideMono;
429 pMultibuffer->clobber = MultibufferUnclobbered;
430 pMultibuffer->pMultibuffers = pMultibuffers;
431 if (!AddResource (ids[i], MultibufferResType, (pointer) pMultibuffer))
433 pMultibuffer->pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth);
434 if (!pMultibuffer->pPixmap)
436 if (!AddResource (ids[i], MultibufferDrawableResType, (pointer) pMultibuffer->pPixmap))
438 FreeResource (ids[i], MultibufferResType);
439 (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
442 pMultibuffer->pPixmap->drawable.id = ids[i];
444 if (i > 0 && pClearGC)
446 ValidateGC((DrawablePtr)pMultibuffer->pPixmap, pClearGC);
447 (*pClearGC->ops->PolyFillRect)((DrawablePtr)pMultibuffer->pPixmap,
448 pClearGC, 1, &clearRect);
451 pMultibuffers->numMultibuffer = i;
452 pMultibuffers->refcnt = i;
453 pMultibuffers->displayedMultibuffer = -1;
455 AliasMultibuffer (pMultibuffers, 0);
456 pMultibuffers->updateAction = action;
457 pMultibuffers->updateHint = hint;
458 pMultibuffers->windowMode = MultibufferModeMono;
459 pMultibuffers->lastUpdate.months = 0;
460 pMultibuffers->lastUpdate.milliseconds = 0;
461 pMultibuffers->width = width;
462 pMultibuffers->height = height;
463 pWin->devPrivates[MultibufferWindowIndex].ptr = (pointer) pMultibuffers;
464 if (pClearGC) FreeScratchGC(pClearGC);
469 ProcCreateImageBuffers (client)
470 register ClientPtr client;
472 REQUEST(xMbufCreateImageBuffersReq);
473 xMbufCreateImageBuffersReply rep;
481 REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
482 len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2);
485 if (!(pWin = LookupWindow (stuff->window, client)))
487 if (pWin->drawable.class == InputOnly)
489 switch (stuff->updateAction)
491 case MultibufferUpdateActionUndefined:
492 case MultibufferUpdateActionBackground:
493 case MultibufferUpdateActionUntouched:
494 case MultibufferUpdateActionCopied:
497 client->errorValue = stuff->updateAction;
500 switch (stuff->updateHint)
502 case MultibufferUpdateHintFrequent:
503 case MultibufferUpdateHintIntermittent:
504 case MultibufferUpdateHintStatic:
507 client->errorValue = stuff->updateHint;
511 ids = (XID *) &stuff[1];
512 for (i = 0; i < nbuf; i++)
514 LEGAL_NEW_RESOURCE(ids[i], client);
516 err = CreateImageBuffers (pWin, nbuf, ids,
517 stuff->updateAction, stuff->updateHint);
522 rep.sequenceNumber = client->sequence;
523 rep.numberBuffer = ((MultibuffersPtr) (pWin->devPrivates[MultibufferWindowIndex].ptr))->numMultibuffer;
526 swaps(&rep.sequenceNumber, n);
527 swapl(&rep.length, n);
528 swaps(&rep.numberBuffer, n);
530 WriteToClient(client, sizeof (xMbufCreateImageBuffersReply), (char *)&rep);
531 return (client->noClientException);
535 ProcDisplayImageBuffers (client)
536 register ClientPtr client;
538 REQUEST(xMbufDisplayImageBuffersReq);
539 MultibufferPtr *pMultibuffer;
540 MultibuffersPtr *ppMultibuffers;
545 TimeStamp activateTime, bufferTime;
547 REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
548 nbuf = stuff->length - (sizeof (xMbufDisplayImageBuffersReq) >> 2);
551 minDelay = stuff->minDelay;
552 ids = (XID *) &stuff[1];
553 ppMultibuffers = (MultibuffersPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibuffersPtr));
554 pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibufferPtr));
555 if (!ppMultibuffers || !pMultibuffer)
557 if (ppMultibuffers) DEALLOCATE_LOCAL(ppMultibuffers);
558 if (pMultibuffer) DEALLOCATE_LOCAL(pMultibuffer);
559 client->errorValue = 0;
562 activateTime.months = 0;
563 activateTime.milliseconds = 0;
564 for (i = 0; i < nbuf; i++)
566 pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], MultibufferResType);
567 if (!pMultibuffer[i])
569 DEALLOCATE_LOCAL(ppMultibuffers);
570 DEALLOCATE_LOCAL(pMultibuffer);
571 client->errorValue = ids[i];
572 return MultibufferErrorBase + MultibufferBadBuffer;
574 ppMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
575 for (j = 0; j < i; j++)
577 if (ppMultibuffers[i] == ppMultibuffers[j])
579 DEALLOCATE_LOCAL(ppMultibuffers);
580 DEALLOCATE_LOCAL(pMultibuffer);
581 client->errorValue = ids[i];
585 bufferTime = ppMultibuffers[i]->lastUpdate;
586 BumpTimeStamp (&bufferTime, minDelay);
587 if (CompareTimeStamps (bufferTime, activateTime) == LATER)
588 activateTime = bufferTime;
590 UpdateCurrentTime ();
591 if (CompareTimeStamps (activateTime, currentTime) == LATER &&
592 QueueDisplayRequest (client, activateTime))
597 PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf);
598 DEALLOCATE_LOCAL(ppMultibuffers);
599 DEALLOCATE_LOCAL(pMultibuffer);
604 ProcDestroyImageBuffers (client)
605 register ClientPtr client;
607 REQUEST (xMbufDestroyImageBuffersReq);
610 REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
611 if (!(pWin = LookupWindow (stuff->window, client)))
613 DestroyImageBuffers (pWin);
618 ProcSetMBufferAttributes (client)
619 register ClientPtr client;
621 REQUEST (xMbufSetMBufferAttributesReq);
623 MultibuffersPtr pMultibuffers;
630 REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq);
631 pWin = LookupWindow (stuff->window, client);
634 pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
637 len = stuff->length - (sizeof (xMbufSetMBufferAttributesReq) >> 2);
638 vmask = stuff->valueMask;
639 if (len != Ones (vmask))
641 vlist = (XID *) &stuff[1];
644 index2 = (Mask) lowbit (vmask);
648 case MultibufferWindowUpdateHint:
649 updateHint = (CARD32) *vlist;
652 case MultibufferUpdateHintFrequent:
653 case MultibufferUpdateHintIntermittent:
654 case MultibufferUpdateHintStatic:
655 pMultibuffers->updateHint = updateHint;
658 client->errorValue = updateHint;
664 client->errorValue = stuff->valueMask;
672 ProcGetMBufferAttributes (client)
675 REQUEST (xMbufGetMBufferAttributesReq);
677 MultibuffersPtr pMultibuffers;
679 xMbufGetMBufferAttributesReply rep;
682 REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq);
683 pWin = LookupWindow (stuff->window, client);
686 pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
689 ids = (XID *) ALLOCATE_LOCAL (pMultibuffers->numMultibuffer * sizeof (XID));
692 for (i = 0; i < pMultibuffers->numMultibuffer; i++)
693 ids[i] = pMultibuffers->buffers[i].pPixmap->drawable.id;
695 rep.sequenceNumber = client->sequence;
696 rep.length = pMultibuffers->numMultibuffer;
697 rep.displayedBuffer = pMultibuffers->displayedMultibuffer;
698 rep.updateAction = pMultibuffers->updateAction;
699 rep.updateHint = pMultibuffers->updateHint;
700 rep.windowMode = pMultibuffers->windowMode;
703 swaps(&rep.sequenceNumber, n);
704 swapl(&rep.length, n);
705 swaps(&rep.displayedBuffer, n);
706 SwapLongs (ids, pMultibuffers->numMultibuffer);
708 WriteToClient (client, sizeof(xMbufGetMBufferAttributesReply),
710 WriteToClient (client, (int)(pMultibuffers->numMultibuffer * sizeof (XID)),
712 DEALLOCATE_LOCAL((pointer) ids);
713 return client->noClientException;
717 ProcSetBufferAttributes (client)
718 register ClientPtr client;
720 REQUEST(xMbufSetBufferAttributesReq);
721 MultibufferPtr pMultibuffer;
728 REQUEST_AT_LEAST_SIZE (xMbufSetBufferAttributesReq);
729 pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
731 return MultibufferErrorBase + MultibufferBadBuffer;
732 len = stuff->length - (sizeof (xMbufSetBufferAttributesReq) >> 2);
733 vmask = stuff->valueMask;
734 if (len != Ones (vmask))
736 vlist = (XID *) &stuff[1];
739 index2 = (Mask) lowbit (vmask);
743 case MultibufferBufferEventMask:
744 eventMask = (Mask) *vlist;
746 result = EventSelectForMultibuffer (pMultibuffer, client, eventMask);
747 if (result != Success)
751 client->errorValue = stuff->valueMask;
759 ProcGetBufferAttributes (client)
760 register ClientPtr client;
762 REQUEST(xMbufGetBufferAttributesReq);
763 MultibufferPtr pMultibuffer;
764 xMbufGetBufferAttributesReply rep;
765 OtherClientsPtr other;
768 REQUEST_SIZE_MATCH (xMbufGetBufferAttributesReq);
769 pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
771 return MultibufferErrorBase + MultibufferBadBuffer;
773 rep.sequenceNumber = client->sequence;
775 rep.window = pMultibuffer->pMultibuffers->pWindow->drawable.id;
776 if (bClient (pMultibuffer) == client)
777 rep.eventMask = pMultibuffer->eventMask;
780 rep.eventMask = (Mask) 0L;
781 for (other = pMultibuffer->otherClients; other; other = other->next)
782 if (SameClient (other, client))
784 rep.eventMask = other->mask;
788 rep.bufferIndex = pMultibuffer->number;
789 rep.side = pMultibuffer->side;
792 swaps(&rep.sequenceNumber, n);
793 swapl(&rep.length, n);
794 swapl(&rep.window, n);
795 swapl(&rep.eventMask, n);
796 swaps(&rep.bufferIndex, n);
798 WriteToClient(client, sizeof (xMbufGetBufferAttributesReply), (char *)&rep);
799 return (client->noClientException);
803 ProcGetBufferInfo (client)
804 register ClientPtr client;
806 REQUEST (xMbufGetBufferInfoReq);
807 DrawablePtr pDrawable;
808 xMbufGetBufferInfoReply rep;
812 xMbufBufferInfo *pInfo;
816 pDrawable = (DrawablePtr) LookupDrawable (stuff->drawable, client);
819 pScreen = pDrawable->pScreen;
821 for (i = 0; i < pScreen->numDepths; i++)
823 pDepth = &pScreen->allowedDepths[i];
824 nInfo += pDepth->numVids;
826 pInfo = (xMbufBufferInfo *)
827 ALLOCATE_LOCAL (nInfo * sizeof (xMbufBufferInfo));
832 rep.sequenceNumber = client->sequence;
833 rep.length = nInfo * (sizeof (xMbufBufferInfo) >> 2);
834 rep.normalInfo = nInfo;
838 swaps(&rep.sequenceNumber, n);
839 swapl(&rep.length, n);
840 swaps(&rep.normalInfo, n);
841 swaps(&rep.stereoInfo, n);
845 for (i = 0; i < pScreen->numDepths; i++)
847 pDepth = &pScreen->allowedDepths[i];
848 for (j = 0; j < pDepth->numVids; j++)
850 pInfo[k].visualID = pDepth->vids[j];
851 pInfo[k].maxBuffers = 0;
852 pInfo[k].depth = pDepth->depth;
855 swapl (&pInfo[k].visualID, n);
856 swaps (&pInfo[k].maxBuffers, n);
861 WriteToClient (client, sizeof (xMbufGetBufferInfoReply), (pointer) &rep);
862 WriteToClient (client, (int) nInfo * sizeof (xMbufBufferInfo), (pointer) pInfo);
863 DEALLOCATE_LOCAL ((pointer) pInfo);
864 return client->noClientException;
868 ProcClearImageBufferArea (client)
869 register ClientPtr client;
871 REQUEST (xMbufClearImageBufferAreaReq);
872 MultibufferPtr pMultibuffer;
874 xRectangle clearRect;
876 DrawablePtr pDrawable;
879 REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq);
880 pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
882 return MultibufferErrorBase + MultibufferBadBuffer;
883 if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse))
885 client->errorValue = stuff->exposures;
888 pWin = pMultibuffer->pMultibuffers->pWindow;
889 width = pWin->drawable.width;
890 height = pWin->drawable.height;
891 pScreen = pWin->drawable.pScreen;
893 clearRect.x = stuff->x;
894 clearRect.y = stuff->y;
895 clearRect.width = stuff->width ? stuff->width : width;
896 clearRect.height = stuff->height ? stuff->height : height;
898 if (pWin->backgroundState != None)
901 pClearGC = GetScratchGC (pWin->drawable.depth, pScreen);
902 SetupBackgroundPainter (pWin, pClearGC);
904 if (pMultibuffer->number == pMultibuffer->pMultibuffers->displayedMultibuffer)
905 pDrawable = (DrawablePtr)pWin;
907 pDrawable = (DrawablePtr)pMultibuffer->pPixmap;
909 ValidateGC(pDrawable, pClearGC);
910 (*pClearGC->ops->PolyFillRect) (pDrawable, pClearGC, 1, &clearRect);
911 FreeScratchGC(pClearGC);
914 if (stuff->exposures)
918 box.x1 = clearRect.x;
919 box.y1 = clearRect.y;
920 box.x2 = clearRect.x + clearRect.width;
921 box.y2 = clearRect.y + clearRect.height;
922 REGION_INIT(pScreen, ®ion, &box, 1);
923 MultibufferExpose(pMultibuffer, ®ion);
924 REGION_UNINIT(pScreen, ®ion);
930 ProcMultibufferDispatch (client)
931 register ClientPtr client;
934 switch (stuff->data) {
935 case X_MbufGetBufferVersion:
936 return ProcGetBufferVersion (client);
937 case X_MbufCreateImageBuffers:
938 return ProcCreateImageBuffers (client);
939 case X_MbufDisplayImageBuffers:
940 return ProcDisplayImageBuffers (client);
941 case X_MbufDestroyImageBuffers:
942 return ProcDestroyImageBuffers (client);
943 case X_MbufSetMBufferAttributes:
944 return ProcSetMBufferAttributes (client);
945 case X_MbufGetMBufferAttributes:
946 return ProcGetMBufferAttributes (client);
947 case X_MbufSetBufferAttributes:
948 return ProcSetBufferAttributes (client);
949 case X_MbufGetBufferAttributes:
950 return ProcGetBufferAttributes (client);
951 case X_MbufGetBufferInfo:
952 return ProcGetBufferInfo (client);
953 case X_MbufClearImageBufferArea:
954 return ProcClearImageBufferArea (client);
961 SProcGetBufferVersion (client)
962 register ClientPtr client;
965 REQUEST (xMbufGetBufferVersionReq);
967 swaps (&stuff->length, n);
968 return ProcGetBufferVersion (client);
972 SProcCreateImageBuffers (client)
973 register ClientPtr client;
976 REQUEST (xMbufCreateImageBuffersReq);
978 swaps (&stuff->length, n);
979 REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
980 swapl (&stuff->window, n);
982 return ProcCreateImageBuffers (client);
986 SProcDisplayImageBuffers (client)
987 register ClientPtr client;
990 REQUEST (xMbufDisplayImageBuffersReq);
992 swaps (&stuff->length, n);
993 REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
994 swaps (&stuff->minDelay, n);
995 swaps (&stuff->maxDelay, n);
997 return ProcDisplayImageBuffers (client);
1001 SProcDestroyImageBuffers (client)
1002 register ClientPtr client;
1005 REQUEST (xMbufDestroyImageBuffersReq);
1007 swaps (&stuff->length, n);
1008 REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
1009 swapl (&stuff->window, n);
1010 return ProcDestroyImageBuffers (client);
1014 SProcSetMBufferAttributes (client)
1015 register ClientPtr client;
1018 REQUEST (xMbufSetMBufferAttributesReq);
1020 swaps (&stuff->length, n);
1021 REQUEST_AT_LEAST_SIZE(xMbufSetMBufferAttributesReq);
1022 swapl (&stuff->window, n);
1023 swapl (&stuff->valueMask, n);
1025 return ProcSetMBufferAttributes (client);
1029 SProcGetMBufferAttributes (client)
1030 register ClientPtr client;
1033 REQUEST (xMbufGetMBufferAttributesReq);
1035 swaps (&stuff->length, n);
1036 REQUEST_AT_LEAST_SIZE(xMbufGetMBufferAttributesReq);
1037 swapl (&stuff->window, n);
1038 return ProcGetMBufferAttributes (client);
1042 SProcSetBufferAttributes (client)
1043 register ClientPtr client;
1046 REQUEST (xMbufSetBufferAttributesReq);
1048 swaps (&stuff->length, n);
1049 REQUEST_AT_LEAST_SIZE(xMbufSetBufferAttributesReq);
1050 swapl (&stuff->buffer, n);
1051 swapl (&stuff->valueMask, n);
1053 return ProcSetBufferAttributes (client);
1057 SProcGetBufferAttributes (client)
1058 register ClientPtr client;
1061 REQUEST (xMbufGetBufferAttributesReq);
1063 swaps (&stuff->length, n);
1064 REQUEST_AT_LEAST_SIZE(xMbufGetBufferAttributesReq);
1065 swapl (&stuff->buffer, n);
1066 return ProcGetBufferAttributes (client);
1070 SProcGetBufferInfo (client)
1071 register ClientPtr client;
1074 REQUEST (xMbufGetBufferInfoReq);
1076 swaps (&stuff->length, n);
1077 REQUEST_SIZE_MATCH (xMbufGetBufferInfoReq);
1078 swapl (&stuff->drawable, n);
1079 return ProcGetBufferInfo (client);
1083 SProcClearImageBufferArea(client)
1084 register ClientPtr client;
1087 REQUEST(xMbufClearImageBufferAreaReq);
1089 swaps(&stuff->length, n);
1090 REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq);
1091 swapl(&stuff->buffer, n);
1092 swaps(&stuff->x, n);
1093 swaps(&stuff->y, n);
1094 swaps(&stuff->width, n);
1095 swaps(&stuff->height, n);
1096 return ProcClearImageBufferArea(client);
1100 SProcMultibufferDispatch (client)
1101 register ClientPtr client;
1104 switch (stuff->data) {
1105 case X_MbufGetBufferVersion:
1106 return SProcGetBufferVersion (client);
1107 case X_MbufCreateImageBuffers:
1108 return SProcCreateImageBuffers (client);
1109 case X_MbufDisplayImageBuffers:
1110 return SProcDisplayImageBuffers (client);
1111 case X_MbufDestroyImageBuffers:
1112 return SProcDestroyImageBuffers (client);
1113 case X_MbufSetMBufferAttributes:
1114 return SProcSetMBufferAttributes (client);
1115 case X_MbufGetMBufferAttributes:
1116 return SProcGetMBufferAttributes (client);
1117 case X_MbufSetBufferAttributes:
1118 return SProcSetBufferAttributes (client);
1119 case X_MbufGetBufferAttributes:
1120 return SProcGetBufferAttributes (client);
1121 case X_MbufGetBufferInfo:
1122 return SProcGetBufferInfo (client);
1123 case X_MbufClearImageBufferArea:
1124 return SProcClearImageBufferArea (client);
1131 SUpdateNotifyEvent (from, to)
1132 xMbufUpdateNotifyEvent *from, *to;
1134 to->type = from->type;
1135 cpswaps (from->sequenceNumber, to->sequenceNumber);
1136 cpswapl (from->buffer, to->buffer);
1137 cpswapl (from->timeStamp, to->timeStamp);
1141 SClobberNotifyEvent (from, to)
1142 xMbufClobberNotifyEvent *from, *to;
1144 to->type = from->type;
1145 cpswaps (from->sequenceNumber, to->sequenceNumber);
1146 cpswapl (from->buffer, to->buffer);
1147 to->state = from->state;
1151 PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf)
1152 MultibufferPtr *pMultibuffer;
1153 MultibuffersPtr *ppMultibuffers;
1157 PixmapPtr pPrevPixmap, pNewPixmap;
1158 xRectangle clearRect;
1162 MultibufferPtr pPrevMultibuffer;
1165 UpdateCurrentTime ();
1166 for (i = 0; i < nbuf; i++)
1168 pWin = ppMultibuffers[i]->pWindow;
1169 pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
1171 &ppMultibuffers[i]->buffers[ppMultibuffers[i]->displayedMultibuffer];
1172 pPrevPixmap = pPrevMultibuffer->pPixmap;
1173 pNewPixmap = pMultibuffer[i]->pPixmap;
1174 switch (ppMultibuffers[i]->updateAction)
1176 case MultibufferUpdateActionUndefined:
1178 case MultibufferUpdateActionBackground:
1179 SetupBackgroundPainter (pWin, pGC);
1180 ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
1183 clearRect.width = pPrevPixmap->drawable.width;
1184 clearRect.height = pPrevPixmap->drawable.height;
1185 (*pGC->ops->PolyFillRect) ((DrawablePtr)pPrevPixmap, pGC,
1188 case MultibufferUpdateActionUntouched:
1189 /* copy the window to the pixmap that represents the
1190 * currently displayed buffer
1192 if (pPrevMultibuffer->eventMask & ExposureMask)
1194 graphicsExpose = TRUE;
1195 DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE);
1197 ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
1198 pExposed = (*pGC->ops->CopyArea)
1199 ((DrawablePtr) pWin,
1200 (DrawablePtr) pPrevPixmap,
1203 pWin->drawable.width, pWin->drawable.height,
1206 /* if we couldn't copy the whole window to the buffer,
1207 * send expose events (if any client wants them)
1209 if (pPrevMultibuffer->eventMask & ExposureMask)
1210 { /* some client wants expose events */
1214 ScreenPtr pScreen = pWin->drawable.pScreen;
1216 pWinSize = CreateUnclippedWinSize (pWin);
1217 /* pExposed is window-relative, but at this point
1218 * pWinSize is screen-relative. Make pWinSize be
1219 * window-relative so that region ops involving
1220 * pExposed and pWinSize behave sensibly.
1222 REGION_TRANSLATE(pScreen, pWinSize,
1225 REGION_INTERSECT(pScreen, pExposed, pExposed, pWinSize);
1226 REGION_DESTROY(pScreen, pWinSize);
1227 MultibufferExpose (pPrevMultibuffer, pExposed);
1228 REGION_DESTROY(pScreen, pExposed);
1230 graphicsExpose = FALSE;
1231 DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE);
1233 break; /* end case MultibufferUpdateActionUntouched */
1235 case MultibufferUpdateActionCopied:
1236 ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
1237 (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap,
1238 (DrawablePtr)pPrevPixmap, pGC,
1240 pWin->drawable.width, pWin->drawable.height,
1243 } /* end switch on update action */
1245 /* display the new buffer */
1246 ValidateGC ((DrawablePtr)pWin, pGC);
1247 (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin, pGC,
1249 pWin->drawable.width, pWin->drawable.height,
1251 ppMultibuffers[i]->lastUpdate = currentTime;
1252 MultibufferUpdate (pMultibuffer[i],
1253 ppMultibuffers[i]->lastUpdate.milliseconds);
1254 AliasMultibuffer (ppMultibuffers[i],
1255 pMultibuffer[i] - ppMultibuffers[i]->buffers);
1256 FreeScratchGC (pGC);
1261 GetBufferPointer (pWin, i)
1265 MultibuffersPtr pMultibuffers;
1267 if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr))
1269 return (DrawablePtr) pMultibuffers->buffers[i].pPixmap;
1273 DisplayImageBuffers (ids, nbuf)
1277 MultibufferPtr *pMultibuffer;
1278 MultibuffersPtr *pMultibuffers;
1281 pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL (nbuf * sizeof *pMultibuffer +
1282 nbuf * sizeof *pMultibuffers);
1285 pMultibuffers = (MultibuffersPtr *) (pMultibuffer + nbuf);
1286 for (i = 0; i < nbuf; i++)
1288 pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], MultibufferResType);
1289 if (!pMultibuffer[i])
1291 DEALLOCATE_LOCAL (pMultibuffer);
1292 return MultibufferErrorBase + MultibufferBadBuffer;
1294 pMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
1295 for (j = 0; j < i; j++)
1296 if (pMultibuffers[i] == pMultibuffers[j])
1298 DEALLOCATE_LOCAL (pMultibuffer);
1302 PerformDisplayRequest (pMultibuffers, pMultibuffer, nbuf);
1303 DEALLOCATE_LOCAL (pMultibuffer);
1309 QueueDisplayRequest (client, activateTime)
1311 TimeStamp activateTime;
1313 /* see xtest.c:ProcXTestFakeInput for code similar to this */
1315 if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
1319 /* swap the request back so we can simply re-execute it */
1320 if (client->swapped)
1323 REQUEST (xMbufDisplayImageBuffersReq);
1326 swaps (&stuff->length, n);
1327 swaps (&stuff->minDelay, n);
1328 swaps (&stuff->maxDelay, n);
1330 ResetCurrentRequest (client);
1337 * Deliver events to a buffer
1341 DeliverEventsToMultibuffer (pMultibuffer, pEvents, count, filter)
1342 MultibufferPtr pMultibuffer;
1347 int deliveries = 0, nondeliveries = 0;
1349 OtherClients *other;
1351 /* if nobody wants the event, we're done */
1352 if (!((pMultibuffer->otherEventMask|pMultibuffer->eventMask) & filter))
1355 /* maybe send event to owner */
1356 if ((attempt = TryClientEvents(
1357 bClient(pMultibuffer), pEvents, count, pMultibuffer->eventMask, filter, (GrabPtr) 0)) != 0)
1365 /* maybe send event to other clients */
1366 for (other = pMultibuffer->otherClients; other; other=other->next)
1368 if ((attempt = TryClientEvents(
1369 rClient(other), pEvents, count, other->mask, filter, (GrabPtr) 0)) != 0)
1379 return nondeliveries;
1383 * Send Expose events to interested clients
1387 MultibufferExpose (pMultibuffer, pRegion)
1388 MultibufferPtr pMultibuffer;
1391 if (pRegion && !REGION_NIL(pRegion))
1395 register xEvent *pe;
1396 register BoxPtr pBox;
1400 pPixmap = pMultibuffer->pPixmap;
1401 REGION_TRANSLATE(pPixmap->drawable.pScreen, pRegion,
1402 -pPixmap->drawable.x, -pPixmap->drawable.y);
1403 /* XXX MultibufferExpose "knows" the region representation */
1404 numRects = REGION_NUM_RECTS(pRegion);
1405 pBox = REGION_RECTS(pRegion);
1407 pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent));
1411 for (i=1; i<=numRects; i++, pe++, pBox++)
1413 pe->u.u.type = Expose;
1414 pe->u.expose.window = pPixmap->drawable.id;
1415 pe->u.expose.x = pBox->x1;
1416 pe->u.expose.y = pBox->y1;
1417 pe->u.expose.width = pBox->x2 - pBox->x1;
1418 pe->u.expose.height = pBox->y2 - pBox->y1;
1419 pe->u.expose.count = (numRects - i);
1421 (void) DeliverEventsToMultibuffer (pMultibuffer, pEvent, numRects,
1423 DEALLOCATE_LOCAL(pEvent);
1428 /* send UpdateNotify event */
1430 MultibufferUpdate (pMultibuffer, time2)
1431 MultibufferPtr pMultibuffer;
1434 xMbufUpdateNotifyEvent event;
1436 event.type = MultibufferEventBase + MultibufferUpdateNotify;
1437 event.buffer = pMultibuffer->pPixmap->drawable.id;
1438 event.timeStamp = time2;
1439 (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event,
1440 1, (Mask)MultibufferUpdateNotifyMask);
1444 * The sample implementation will never generate MultibufferClobberNotify
1449 MultibufferClobber (pMultibuffer)
1450 MultibufferPtr pMultibuffer;
1452 xMbufClobberNotifyEvent event;
1454 event.type = MultibufferEventBase + MultibufferClobberNotify;
1455 event.buffer = pMultibuffer->pPixmap->drawable.id;
1456 event.state = pMultibuffer->clobber;
1457 (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event,
1458 1, (Mask)MultibufferClobberNotifyMask);
1462 * make the resource id for buffer i refer to the window
1463 * drawable instead of the pixmap;
1467 AliasMultibuffer (pMultibuffers, i)
1468 MultibuffersPtr pMultibuffers;
1471 MultibufferPtr pMultibuffer;
1473 if (i == pMultibuffers->displayedMultibuffer)
1476 * remove the old association
1478 if (pMultibuffers->displayedMultibuffer >= 0)
1480 pMultibuffer = &pMultibuffers->buffers[pMultibuffers->displayedMultibuffer];
1481 ChangeResourceValue (pMultibuffer->pPixmap->drawable.id,
1482 MultibufferDrawableResType,
1483 (pointer) pMultibuffer->pPixmap);
1486 * make the new association
1488 pMultibuffer = &pMultibuffers->buffers[i];
1489 ChangeResourceValue (pMultibuffer->pPixmap->drawable.id,
1490 MultibufferDrawableResType,
1491 (pointer) pMultibuffers->pWindow);
1492 pMultibuffers->displayedMultibuffer = i;
1496 * free everything associated with multibuffering for this
1501 DestroyImageBuffers (pWin)
1504 FreeResourceByType (pWin->drawable.id, MultibuffersResType, FALSE);
1505 /* Zero out the window's pointer to the buffers so they won't be reused */
1506 pWin->devPrivates[MultibufferWindowIndex].ptr = NULL;
1510 * resize the buffers when the window is resized
1514 MultibufferPositionWindow (pWin, x, y)
1519 MultibufferScreenPtr pMultibufferScreen;
1520 MultibuffersPtr pMultibuffers;
1521 MultibufferPtr pMultibuffer;
1525 int sourcex, sourcey;
1529 int savewidth, saveheight;
1530 xRectangle clearRect;
1533 pScreen = pWin->drawable.pScreen;
1534 pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr;
1535 (*pMultibufferScreen->PositionWindow) (pWin, x, y);
1537 /* if this window is not multibuffered, we're done */
1538 if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr))
1541 /* if new size is same as old, we're done */
1542 if (pMultibuffers->width == pWin->drawable.width &&
1543 pMultibuffers->height == pWin->drawable.height)
1546 width = pWin->drawable.width;
1547 height = pWin->drawable.height;
1548 dx = pWin->drawable.x - pMultibuffers->x;
1549 dy = pWin->drawable.x - pMultibuffers->y;
1550 dw = width - pMultibuffers->width;
1551 dh = height - pMultibuffers->height;
1552 GravityTranslate (0, 0, -dx, -dy, dw, dh,
1553 pWin->bitGravity, &destx, &desty);
1555 /* if the window grew, remember to paint the window background,
1556 * and maybe send expose events, for the new areas of the buffers
1558 clear = pMultibuffers->width < width || pMultibuffers->height < height ||
1559 pWin->bitGravity == ForgetGravity;
1563 savewidth = pMultibuffers->width;
1564 saveheight = pMultibuffers->height;
1565 /* clip rectangle to source and destination */
1572 if (destx + savewidth > width)
1573 savewidth = width - destx;
1576 saveheight += desty;
1580 if (desty + saveheight > height)
1581 saveheight = height - desty;
1583 pMultibuffers->width = width;
1584 pMultibuffers->height = height;
1585 pMultibuffers->x = pWin->drawable.x;
1586 pMultibuffers->y = pWin->drawable.y;
1588 pGC = GetScratchGC (pWin->drawable.depth, pScreen);
1591 SetupBackgroundPainter (pWin, pGC);
1594 clearRect.width = width;
1595 clearRect.height = height;
1597 for (i = 0; i < pMultibuffers->numMultibuffer; i++)
1599 pMultibuffer = &pMultibuffers->buffers[i];
1600 pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1601 pWin->drawable.depth);
1604 DestroyImageBuffers (pWin);
1607 ValidateGC ((DrawablePtr)pPixmap, pGC);
1609 * I suppose this could avoid quite a bit of work if
1610 * it computed the minimal area required.
1613 (*pGC->ops->PolyFillRect) ((DrawablePtr)pPixmap, pGC, 1, &clearRect);
1614 if (pWin->bitGravity != ForgetGravity)
1616 (*pGC->ops->CopyArea) ((DrawablePtr)pMultibuffer->pPixmap,
1617 (DrawablePtr)pPixmap, pGC,
1618 sourcex, sourcey, savewidth, saveheight,
1621 pPixmap->drawable.id = pMultibuffer->pPixmap->drawable.id;
1622 (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
1623 pMultibuffer->pPixmap = pPixmap;
1624 if (i != pMultibuffers->displayedMultibuffer)
1626 ChangeResourceValue (pPixmap->drawable.id,
1627 MultibufferDrawableResType,
1631 FreeScratchGC (pGC);
1635 /* Resource delete func for MultibufferDrawableResType */
1638 MultibufferDrawableDelete (value, id)
1642 DrawablePtr pDrawable = (DrawablePtr)value;
1644 MultibuffersPtr pMultibuffers;
1647 if (pDrawable->type == DRAWABLE_WINDOW)
1649 pWin = (WindowPtr) pDrawable;
1650 pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr;
1651 pPixmap = pMultibuffers->buffers[pMultibuffers->displayedMultibuffer].pPixmap;
1655 pPixmap = (PixmapPtr) pDrawable;
1657 (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
1661 /* Resource delete func for MultibufferResType */
1664 MultibufferDelete (value, id)
1668 MultibufferPtr pMultibuffer = (MultibufferPtr)value;
1669 MultibuffersPtr pMultibuffers;
1671 pMultibuffers = pMultibuffer->pMultibuffers;
1672 if (--pMultibuffers->refcnt == 0)
1674 FreeResourceByType (pMultibuffers->pWindow->drawable.id,
1675 MultibuffersResType, TRUE);
1676 xfree (pMultibuffers);
1681 /* Resource delete func for MultibuffersResType */
1684 MultibuffersDelete (value, id)
1688 MultibuffersPtr pMultibuffers = (MultibuffersPtr)value;
1691 if (pMultibuffers->refcnt == pMultibuffers->numMultibuffer)
1693 for (i = pMultibuffers->numMultibuffer; --i >= 0; )
1694 FreeResource (pMultibuffers->buffers[i].pPixmap->drawable.id, 0);
1699 /* Resource delete func for OtherClientResType */
1701 OtherClientDelete (value, id)
1705 MultibufferPtr pMultibuffer = (MultibufferPtr)value;
1706 register OtherClientsPtr other, prev;
1709 for (other = pMultibuffer->otherClients; other; other = other->next)
1711 if (other->resource == id)
1714 prev->next = other->next;
1716 pMultibuffer->otherClients = other->next;
1718 RecalculateMultibufferOtherEvents (pMultibuffer);
1727 EventSelectForMultibuffer (pMultibuffer, client, mask)
1728 MultibufferPtr pMultibuffer;
1732 OtherClientsPtr other;
1734 if (mask & ~ValidEventMasks)
1736 client->errorValue = mask;
1739 if (bClient (pMultibuffer) == client)
1741 pMultibuffer->eventMask = mask;
1743 else /* some other client besides the creator wants events */
1745 for (other = pMultibuffer->otherClients; other; other = other->next)
1747 if (SameClient (other, client))
1751 FreeResource (other->resource, RT_NONE);
1759 { /* new client that never selected events on this buffer before */
1760 other = (OtherClients *) xalloc (sizeof (OtherClients));
1764 other->resource = FakeClientID (client->index);
1765 if (!AddResource (other->resource, OtherClientResType, (pointer) pMultibuffer))
1770 other->next = pMultibuffer->otherClients;
1771 pMultibuffer->otherClients = other;
1773 RecalculateMultibufferOtherEvents (pMultibuffer);
1775 return (client->noClientException);
1778 /* or together all the otherClients event masks */
1780 RecalculateMultibufferOtherEvents (pMultibuffer)
1781 MultibufferPtr pMultibuffer;
1783 Mask otherEventMask;
1784 OtherClients *other;
1786 otherEventMask = 0L;
1787 for (other = pMultibuffer->otherClients; other; other = other->next)
1788 otherEventMask |= other->mask;
1789 pMultibuffer->otherEventMask = otherEventMask;
1792 /* add milliseconds to a timestamp, handling overflow */
1794 BumpTimeStamp (ts, inc)
1800 newms = ts->milliseconds + inc;
1801 if (newms < ts->milliseconds)
1803 ts->milliseconds = newms;