First import
[xorg_rtime.git] / xorg-server-1.4 / Xext / mbuf.c
blobed352e21b78061815c5e894ce8e0883991284f78
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
9 documentation.
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 ********************************************************/
27 #define NEED_REPLIES
28 #define NEED_EVENTS
29 #ifdef HAVE_DIX_CONFIG_H
30 #include <dix-config.h>
31 #endif
33 #include <X11/X.h>
34 #include <X11/Xproto.h>
35 #include "window.h"
36 #include "os.h"
37 #include "windowstr.h"
38 #include "scrnintstr.h"
39 #include "pixmapstr.h"
40 #include "gcstruct.h"
41 #include "extnsionst.h"
42 #include "dixstruct.h"
43 #include "resource.h"
44 #include "opaque.h"
45 #include "sleepuntil.h"
46 #define _MULTIBUF_SERVER_ /* don't want Xlib structures */
47 #include <X11/extensions/multibufst.h>
49 #include <stdio.h>
50 #if !defined(WIN32) && !defined(Lynx)
51 #include <sys/time.h>
52 #endif
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)
62 #if 0
63 static unsigned char MultibufferReqCode;
64 #endif
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 */,
73 int /* nbuf */
75 static Bool QueueDisplayRequest (
76 ClientPtr /* client */,
77 TimeStamp /* activateTime */
80 static void BumpTimeStamp (
81 TimeStamp * /* ts */,
82 CARD32 /* inc */
85 static void AliasMultibuffer (
86 MultibuffersPtr /* pMultibuffers */,
87 int /* i */
89 static void RecalculateMultibufferOtherEvents (
90 MultibufferPtr /* pMultibuffer */
92 static int EventSelectForMultibuffer(
93 MultibufferPtr /* pMultibuffer */,
94 ClientPtr /* client */,
95 Mask /* mask */
99 * The Pixmap associated with a buffer can be found as a resource
100 * with this type
102 RESTYPE MultibufferDrawableResType;
103 static int MultibufferDrawableDelete (
104 pointer /* value */,
105 XID /* id */
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
110 * id of the pixmap
112 static RESTYPE MultibufferResType;
113 static int MultibufferDelete (
114 pointer /* value */,
115 XID /* id */
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 (
124 pointer /* value */,
125 XID /* id */
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 (
134 pointer /* value */,
135 XID /* id */
138 /****************
139 * MultibufferExtensionInit
141 * Called from InitExtensions in main()
143 ****************/
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 */,
182 int /* x */,
183 int /* y */
186 static void SetupBackgroundPainter (
187 WindowPtr /* pWin */,
188 GCPtr /* pGC */
191 static int DeliverEventsToMultibuffer (
192 MultibufferPtr /* pMultibuffer */,
193 xEvent * /* pEvents */,
194 int /* count */,
195 Mask /* filter */
198 void
199 MultibufferExtensionInit()
201 ExtensionEntry *extEntry;
202 int i, j;
203 ScreenPtr pScreen;
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)
214 return;
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);
224 return;
226 pScreen->devPrivates[MultibufferScreenIndex].ptr = (pointer) pMultibufferScreen;
228 * wrap PositionWindow to resize the pixmap when the window
229 * changes size
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)))
250 #if 0
251 MultibufferReqCode = (unsigned char)extEntry->base;
252 #endif
253 MultibufferEventBase = extEntry->eventBase;
254 MultibufferErrorBase = extEntry->errorBase;
255 EventSwapVector[MultibufferEventBase + MultibufferClobberNotify] = (EventSwapPtr) SClobberNotifyEvent;
256 EventSwapVector[MultibufferEventBase + MultibufferUpdateNotify] = (EventSwapPtr) SUpdateNotifyEvent;
260 /*ARGSUSED*/
261 static void
262 MultibufferResetProc (extEntry)
263 ExtensionEntry *extEntry;
265 int i;
266 ScreenPtr pScreen;
267 MultibufferScreenPtr pMultibufferScreen;
269 if (MultibufferScreenIndex < 0)
270 return;
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);
283 static int
284 ProcGetBufferVersion (client)
285 register ClientPtr client;
287 xMbufGetBufferVersionReply rep;
288 register int n;
290 REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq);
291 rep.type = X_Reply;
292 rep.length = 0;
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);
304 static void
305 SetupBackgroundPainter (pWin, pGC)
306 WindowPtr pWin;
307 GCPtr pGC;
309 pointer gcvalues[4];
310 int ts_x_origin, ts_y_origin;
311 PixUnion background;
312 int backgroundState;
313 Mask gcmask;
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;
326 pWin = pWin->parent;
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;
337 break;
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;
345 break;
347 default:
348 gcvalues[0] = (pointer) GXnoop;
349 gcmask = GCFunction;
351 DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE);
355 CreateImageBuffers (pWin, nbuf, ids, action, hint)
356 WindowPtr pWin;
357 int nbuf;
358 XID *ids;
359 int action;
360 int hint;
362 MultibuffersPtr pMultibuffers;
363 MultibufferPtr pMultibuffer;
364 ScreenPtr pScreen;
365 int width, height, depth;
366 int i;
367 GCPtr pClearGC = NULL;
368 xRectangle clearRect;
370 DestroyImageBuffers(pWin);
371 pMultibuffers = (MultibuffersPtr) xalloc (sizeof (MultibuffersRec) +
372 nbuf * sizeof (MultibufferRec));
373 if (!pMultibuffers)
374 return BadAlloc;
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))
379 return BadAlloc;
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))
405 break;
406 pMultibuffer->pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth);
407 if (!pMultibuffer->pPixmap)
408 break;
409 if (!AddResource (ids[i], MultibufferDrawableResType, (pointer) pMultibuffer->pPixmap))
411 FreeResource (ids[i], MultibufferResType);
412 (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
413 break;
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;
427 if (i > 0)
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);
438 return Success;
442 static int
443 ProcCreateImageBuffers (client)
444 register ClientPtr client;
446 REQUEST(xMbufCreateImageBuffersReq);
447 xMbufCreateImageBuffersReply rep;
448 register int n;
449 WindowPtr pWin;
450 XID *ids;
451 int len, nbuf, i, err, rc;
453 REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
454 len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2);
455 if (len == 0)
456 return BadLength;
457 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
458 if (rc != Success)
459 return rc;
460 if (pWin->drawable.class == InputOnly)
461 return BadMatch;
462 switch (stuff->updateAction)
464 case MultibufferUpdateActionUndefined:
465 case MultibufferUpdateActionBackground:
466 case MultibufferUpdateActionUntouched:
467 case MultibufferUpdateActionCopied:
468 break;
469 default:
470 client->errorValue = stuff->updateAction;
471 return BadValue;
473 switch (stuff->updateHint)
475 case MultibufferUpdateHintFrequent:
476 case MultibufferUpdateHintIntermittent:
477 case MultibufferUpdateHintStatic:
478 break;
479 default:
480 client->errorValue = stuff->updateHint;
481 return BadValue;
483 nbuf = len;
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);
491 if (err != Success)
492 return err;
493 rep.type = X_Reply;
494 rep.length = 0;
495 rep.sequenceNumber = client->sequence;
496 rep.numberBuffer = ((MultibuffersPtr) (pWin->devPrivates[MultibufferWindowIndex].ptr))->numMultibuffer;
497 if (client->swapped)
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);
507 static int
508 ProcDisplayImageBuffers (client)
509 register ClientPtr client;
511 REQUEST(xMbufDisplayImageBuffersReq);
512 MultibufferPtr *pMultibuffer;
513 MultibuffersPtr *ppMultibuffers;
514 int nbuf;
515 XID *ids;
516 int i, j;
517 CARD32 minDelay;
518 TimeStamp activateTime, bufferTime;
521 REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
522 nbuf = stuff->length - (sizeof (xMbufDisplayImageBuffersReq) >> 2);
523 if (!nbuf)
524 return Success;
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;
534 return BadAlloc;
536 activateTime.months = 0;
537 activateTime.milliseconds = 0;
538 for (i = 0; i < nbuf; i++)
540 pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i],
541 MultibufferResType);
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];
557 return BadMatch;
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))
571 else
572 PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf);
574 DEALLOCATE_LOCAL(ppMultibuffers);
575 DEALLOCATE_LOCAL(pMultibuffer);
576 return Success;
580 static int
581 ProcDestroyImageBuffers (client)
582 register ClientPtr client;
584 REQUEST (xMbufDestroyImageBuffersReq);
585 WindowPtr pWin;
586 int rc;
588 REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
589 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
590 if (rc != Success)
591 return rc;
592 DestroyImageBuffers (pWin);
593 return Success;
596 static int
597 ProcSetMBufferAttributes (client)
598 register ClientPtr client;
600 REQUEST (xMbufSetMBufferAttributesReq);
601 WindowPtr pWin;
602 MultibuffersPtr pMultibuffers;
603 int len, rc;
604 Mask vmask;
605 Mask index2;
606 CARD32 updateHint;
607 XID *vlist;
609 REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq);
610 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
611 if (rc != Success)
612 return rc;
613 pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
614 if (!pMultibuffers)
615 return BadMatch;
616 len = stuff->length - (sizeof (xMbufSetMBufferAttributesReq) >> 2);
617 vmask = stuff->valueMask;
618 if (len != Ones (vmask))
619 return BadLength;
620 vlist = (XID *) &stuff[1];
621 while (vmask)
623 index2 = (Mask) lowbit (vmask);
624 vmask &= ~index2;
625 switch (index2)
627 case MultibufferWindowUpdateHint:
628 updateHint = (CARD32) *vlist;
629 switch (updateHint)
631 case MultibufferUpdateHintFrequent:
632 case MultibufferUpdateHintIntermittent:
633 case MultibufferUpdateHintStatic:
634 pMultibuffers->updateHint = updateHint;
635 break;
636 default:
637 client->errorValue = updateHint;
638 return BadValue;
640 vlist++;
641 break;
642 default:
643 client->errorValue = stuff->valueMask;
644 return BadValue;
647 return Success;
650 static int
651 ProcGetMBufferAttributes (client)
652 ClientPtr client;
654 REQUEST (xMbufGetMBufferAttributesReq);
655 WindowPtr pWin;
656 MultibuffersPtr pMultibuffers;
657 XID *ids;
658 xMbufGetMBufferAttributesReply rep;
659 int i, n, rc;
661 REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq);
662 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
663 if (rc != Success)
664 return rc;
665 pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
666 if (!pMultibuffers)
667 return BadAccess;
668 ids = (XID *) ALLOCATE_LOCAL (pMultibuffers->numMultibuffer * sizeof (XID));
669 if (!ids)
670 return BadAlloc;
671 for (i = 0; i < pMultibuffers->numMultibuffer; i++)
672 ids[i] = pMultibuffers->buffers[i].pPixmap->drawable.id;
673 rep.type = X_Reply;
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;
680 if (client->swapped)
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),
688 (char *)&rep);
689 WriteToClient (client, (int)(pMultibuffers->numMultibuffer * sizeof (XID)),
690 (char *)ids);
691 DEALLOCATE_LOCAL((pointer) ids);
692 return client->noClientException;
695 static int
696 ProcSetBufferAttributes (client)
697 register ClientPtr client;
699 REQUEST(xMbufSetBufferAttributesReq);
700 MultibufferPtr pMultibuffer;
701 int len;
702 Mask vmask, index2;
703 XID *vlist;
704 Mask eventMask;
705 int result;
707 REQUEST_AT_LEAST_SIZE (xMbufSetBufferAttributesReq);
708 pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
709 if (!pMultibuffer)
710 return MultibufferErrorBase + MultibufferBadBuffer;
711 len = stuff->length - (sizeof (xMbufSetBufferAttributesReq) >> 2);
712 vmask = stuff->valueMask;
713 if (len != Ones (vmask))
714 return BadLength;
715 vlist = (XID *) &stuff[1];
716 while (vmask)
718 index2 = (Mask) lowbit (vmask);
719 vmask &= ~index2;
720 switch (index2)
722 case MultibufferBufferEventMask:
723 eventMask = (Mask) *vlist;
724 vlist++;
725 result = EventSelectForMultibuffer (pMultibuffer, client, eventMask);
726 if (result != Success)
727 return result;
728 break;
729 default:
730 client->errorValue = stuff->valueMask;
731 return BadValue;
734 return Success;
738 ProcGetBufferAttributes (client)
739 register ClientPtr client;
741 REQUEST(xMbufGetBufferAttributesReq);
742 MultibufferPtr pMultibuffer;
743 xMbufGetBufferAttributesReply rep;
744 OtherClientsPtr other;
745 int n;
747 REQUEST_SIZE_MATCH (xMbufGetBufferAttributesReq);
748 pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
749 if (!pMultibuffer)
750 return MultibufferErrorBase + MultibufferBadBuffer;
751 rep.type = X_Reply;
752 rep.sequenceNumber = client->sequence;
753 rep.length = 0;
754 rep.window = pMultibuffer->pMultibuffers->pWindow->drawable.id;
755 if (bClient (pMultibuffer) == client)
756 rep.eventMask = pMultibuffer->eventMask;
757 else
759 rep.eventMask = (Mask) 0L;
760 for (other = pMultibuffer->otherClients; other; other = other->next)
761 if (SameClient (other, client))
763 rep.eventMask = other->mask;
764 break;
767 rep.bufferIndex = pMultibuffer->number;
768 rep.side = pMultibuffer->side;
769 if (client->swapped)
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);
781 static int
782 ProcGetBufferInfo (client)
783 register ClientPtr client;
785 REQUEST (xMbufGetBufferInfoReq);
786 DrawablePtr pDrawable;
787 xMbufGetBufferInfoReply rep;
788 ScreenPtr pScreen;
789 int i, j, k, n, rc;
790 xMbufBufferInfo *pInfo;
791 int nInfo;
792 DepthPtr pDepth;
794 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
795 DixUnknownAccess);
796 if (rc != Success)
797 return rc;
798 pScreen = pDrawable->pScreen;
799 nInfo = 0;
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));
807 if (!pInfo)
808 return BadAlloc;
810 rep.type = X_Reply;
811 rep.sequenceNumber = client->sequence;
812 rep.length = nInfo * (sizeof (xMbufBufferInfo) >> 2);
813 rep.normalInfo = nInfo;
814 rep.stereoInfo = 0;
815 if (client->swapped)
817 swaps(&rep.sequenceNumber, n);
818 swapl(&rep.length, n);
819 swaps(&rep.normalInfo, n);
820 swaps(&rep.stereoInfo, n);
823 k = 0;
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;
832 if (client->swapped)
834 swapl (&pInfo[k].visualID, n);
835 swaps (&pInfo[k].maxBuffers, n);
837 k++;
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;
846 static int
847 ProcClearImageBufferArea (client)
848 register ClientPtr client;
850 REQUEST (xMbufClearImageBufferAreaReq);
851 MultibufferPtr pMultibuffer;
852 WindowPtr pWin;
853 xRectangle clearRect;
854 int width, height;
855 DrawablePtr pDrawable;
856 ScreenPtr pScreen;
858 REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq);
859 pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
860 if (!pMultibuffer)
861 return MultibufferErrorBase + MultibufferBadBuffer;
862 if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse))
864 client->errorValue = stuff->exposures;
865 return(BadValue);
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)
879 GCPtr pClearGC;
880 pClearGC = GetScratchGC (pWin->drawable.depth, pScreen);
881 SetupBackgroundPainter (pWin, pClearGC);
883 if (pMultibuffer->number == pMultibuffer->pMultibuffers->displayedMultibuffer)
884 pDrawable = (DrawablePtr)pWin;
885 else
886 pDrawable = (DrawablePtr)pMultibuffer->pPixmap;
888 ValidateGC(pDrawable, pClearGC);
889 (*pClearGC->ops->PolyFillRect) (pDrawable, pClearGC, 1, &clearRect);
890 FreeScratchGC(pClearGC);
893 if (stuff->exposures)
895 RegionRec region;
896 BoxRec box;
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, &region, &box, 1);
902 MultibufferExpose(pMultibuffer, &region);
903 REGION_UNINIT(pScreen, &region);
905 return Success;
908 static int
909 ProcMultibufferDispatch (client)
910 register ClientPtr client;
912 REQUEST(xReq);
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);
934 default:
935 return BadRequest;
939 static int
940 SProcGetBufferVersion (client)
941 register ClientPtr client;
943 register int n;
944 REQUEST (xMbufGetBufferVersionReq);
946 swaps (&stuff->length, n);
947 return ProcGetBufferVersion (client);
950 static int
951 SProcCreateImageBuffers (client)
952 register ClientPtr client;
954 register int n;
955 REQUEST (xMbufCreateImageBuffersReq);
957 swaps (&stuff->length, n);
958 REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
959 swapl (&stuff->window, n);
960 SwapRestL(stuff);
961 return ProcCreateImageBuffers (client);
964 static int
965 SProcDisplayImageBuffers (client)
966 register ClientPtr client;
968 register int n;
969 REQUEST (xMbufDisplayImageBuffersReq);
971 swaps (&stuff->length, n);
972 REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
973 swaps (&stuff->minDelay, n);
974 swaps (&stuff->maxDelay, n);
975 SwapRestL(stuff);
976 return ProcDisplayImageBuffers (client);
979 static int
980 SProcDestroyImageBuffers (client)
981 register ClientPtr client;
983 register int n;
984 REQUEST (xMbufDestroyImageBuffersReq);
986 swaps (&stuff->length, n);
987 REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
988 swapl (&stuff->window, n);
989 return ProcDestroyImageBuffers (client);
992 static int
993 SProcSetMBufferAttributes (client)
994 register ClientPtr client;
996 register int n;
997 REQUEST (xMbufSetMBufferAttributesReq);
999 swaps (&stuff->length, n);
1000 REQUEST_AT_LEAST_SIZE(xMbufSetMBufferAttributesReq);
1001 swapl (&stuff->window, n);
1002 swapl (&stuff->valueMask, n);
1003 SwapRestL(stuff);
1004 return ProcSetMBufferAttributes (client);
1007 static int
1008 SProcGetMBufferAttributes (client)
1009 register ClientPtr client;
1011 register int n;
1012 REQUEST (xMbufGetMBufferAttributesReq);
1014 swaps (&stuff->length, n);
1015 REQUEST_AT_LEAST_SIZE(xMbufGetMBufferAttributesReq);
1016 swapl (&stuff->window, n);
1017 return ProcGetMBufferAttributes (client);
1020 static int
1021 SProcSetBufferAttributes (client)
1022 register ClientPtr client;
1024 register int n;
1025 REQUEST (xMbufSetBufferAttributesReq);
1027 swaps (&stuff->length, n);
1028 REQUEST_AT_LEAST_SIZE(xMbufSetBufferAttributesReq);
1029 swapl (&stuff->buffer, n);
1030 swapl (&stuff->valueMask, n);
1031 SwapRestL(stuff);
1032 return ProcSetBufferAttributes (client);
1035 static int
1036 SProcGetBufferAttributes (client)
1037 register ClientPtr client;
1039 register int n;
1040 REQUEST (xMbufGetBufferAttributesReq);
1042 swaps (&stuff->length, n);
1043 REQUEST_AT_LEAST_SIZE(xMbufGetBufferAttributesReq);
1044 swapl (&stuff->buffer, n);
1045 return ProcGetBufferAttributes (client);
1048 static int
1049 SProcGetBufferInfo (client)
1050 register ClientPtr client;
1052 register int n;
1053 REQUEST (xMbufGetBufferInfoReq);
1055 swaps (&stuff->length, n);
1056 REQUEST_SIZE_MATCH (xMbufGetBufferInfoReq);
1057 swapl (&stuff->drawable, n);
1058 return ProcGetBufferInfo (client);
1061 static int
1062 SProcClearImageBufferArea(client)
1063 register ClientPtr client;
1065 register char n;
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);
1078 static int
1079 SProcMultibufferDispatch (client)
1080 register ClientPtr client;
1082 REQUEST(xReq);
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);
1104 default:
1105 return BadRequest;
1109 static void
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);
1119 static void
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;
1129 static void
1130 PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf)
1131 MultibufferPtr *pMultibuffer;
1132 MultibuffersPtr *ppMultibuffers;
1133 int nbuf;
1135 GCPtr pGC;
1136 PixmapPtr pPrevPixmap, pNewPixmap;
1137 xRectangle clearRect;
1138 WindowPtr pWin;
1139 RegionPtr pExposed;
1140 int i;
1141 MultibufferPtr pPrevMultibuffer;
1142 XID graphicsExpose;
1144 UpdateCurrentTime ();
1145 for (i = 0; i < nbuf; i++)
1147 pWin = ppMultibuffers[i]->pWindow;
1148 pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
1149 pPrevMultibuffer =
1150 &ppMultibuffers[i]->buffers[ppMultibuffers[i]->displayedMultibuffer];
1151 pPrevPixmap = pPrevMultibuffer->pPixmap;
1152 pNewPixmap = pMultibuffer[i]->pPixmap;
1153 switch (ppMultibuffers[i]->updateAction)
1155 case MultibufferUpdateActionUndefined:
1156 break;
1157 case MultibufferUpdateActionBackground:
1158 SetupBackgroundPainter (pWin, pGC);
1159 ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
1160 clearRect.x = 0;
1161 clearRect.y = 0;
1162 clearRect.width = pPrevPixmap->drawable.width;
1163 clearRect.height = pPrevPixmap->drawable.height;
1164 (*pGC->ops->PolyFillRect) ((DrawablePtr)pPrevPixmap, pGC,
1165 1, &clearRect);
1166 break;
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,
1180 pGC,
1181 0, 0,
1182 pWin->drawable.width, pWin->drawable.height,
1183 0, 0);
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 */
1190 if (pExposed)
1192 RegionPtr pWinSize;
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,
1217 0, 0,
1218 pWin->drawable.width, pWin->drawable.height,
1219 0, 0);
1220 break;
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,
1226 0, 0,
1227 pWin->drawable.width, pWin->drawable.height,
1228 0, 0);
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);
1238 DrawablePtr
1239 GetBufferPointer (pWin, i)
1240 WindowPtr pWin;
1241 int i;
1243 MultibuffersPtr pMultibuffers;
1245 if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr))
1246 return NULL;
1247 return (DrawablePtr) pMultibuffers->buffers[i].pPixmap;
1251 DisplayImageBuffers (ids, nbuf)
1252 XID *ids;
1253 int nbuf;
1255 MultibufferPtr *pMultibuffer;
1256 MultibuffersPtr *pMultibuffers;
1257 int i, j;
1259 pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL (nbuf * sizeof *pMultibuffer +
1260 nbuf * sizeof *pMultibuffers);
1261 if (!pMultibuffer)
1262 return BadAlloc;
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);
1277 return BadMatch;
1280 PerformDisplayRequest (pMultibuffers, pMultibuffer, nbuf);
1281 DEALLOCATE_LOCAL (pMultibuffer);
1282 return Success;
1286 static Bool
1287 QueueDisplayRequest (client, activateTime)
1288 ClientPtr client;
1289 TimeStamp activateTime;
1291 /* see xtest.c:ProcXTestFakeInput for code similar to this */
1293 if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
1295 return FALSE;
1297 /* swap the request back so we can simply re-execute it */
1298 if (client->swapped)
1300 register int n;
1301 REQUEST (xMbufDisplayImageBuffersReq);
1303 SwapRestL(stuff);
1304 swaps (&stuff->length, n);
1305 swaps (&stuff->minDelay, n);
1306 swaps (&stuff->maxDelay, n);
1308 ResetCurrentRequest (client);
1309 client->sequence--;
1310 return TRUE;
1315 * Deliver events to a buffer
1318 static int
1319 DeliverEventsToMultibuffer (pMultibuffer, pEvents, count, filter)
1320 MultibufferPtr pMultibuffer;
1321 xEvent *pEvents;
1322 int count;
1323 Mask filter;
1325 int deliveries = 0, nondeliveries = 0;
1326 int attempt;
1327 OtherClients *other;
1329 /* if nobody wants the event, we're done */
1330 if (!((pMultibuffer->otherEventMask|pMultibuffer->eventMask) & filter))
1331 return 0;
1333 /* maybe send event to owner */
1334 if ((attempt = TryClientEvents(
1335 bClient(pMultibuffer), pEvents, count, pMultibuffer->eventMask, filter, (GrabPtr) 0)) != 0)
1337 if (attempt > 0)
1338 deliveries++;
1339 else
1340 nondeliveries--;
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)
1349 if (attempt > 0)
1350 deliveries++;
1351 else
1352 nondeliveries--;
1355 if (deliveries)
1356 return deliveries;
1357 return nondeliveries;
1361 * Send Expose events to interested clients
1364 void
1365 MultibufferExpose (pMultibuffer, pRegion)
1366 MultibufferPtr pMultibuffer;
1367 RegionPtr pRegion;
1369 if (pRegion && !REGION_NIL(pRegion))
1371 xEvent *pEvent;
1372 PixmapPtr pPixmap;
1373 register xEvent *pe;
1374 register BoxPtr pBox;
1375 register int i;
1376 int numRects;
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));
1386 if (pEvent) {
1387 pe = pEvent;
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,
1400 ExposureMask);
1401 DEALLOCATE_LOCAL(pEvent);
1406 /* send UpdateNotify event */
1407 void
1408 MultibufferUpdate (pMultibuffer, time2)
1409 MultibufferPtr pMultibuffer;
1410 CARD32 time2;
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
1423 * events
1426 void
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;
1444 static void
1445 AliasMultibuffer (pMultibuffers, i)
1446 MultibuffersPtr pMultibuffers;
1447 int i;
1449 MultibufferPtr pMultibuffer;
1451 if (i == pMultibuffers->displayedMultibuffer)
1452 return;
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
1475 * window
1478 void
1479 DestroyImageBuffers (pWin)
1480 WindowPtr 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
1491 static Bool
1492 MultibufferPositionWindow (pWin, x, y)
1493 WindowPtr pWin;
1494 int x, y;
1496 ScreenPtr pScreen;
1497 MultibufferScreenPtr pMultibufferScreen;
1498 MultibuffersPtr pMultibuffers;
1499 MultibufferPtr pMultibuffer;
1500 int width, height;
1501 int i;
1502 int dx, dy, dw, dh;
1503 int sourcex, sourcey;
1504 int destx, desty;
1505 PixmapPtr pPixmap;
1506 GCPtr pGC;
1507 int savewidth, saveheight;
1508 xRectangle clearRect;
1509 Bool clear;
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))
1517 return TRUE;
1519 /* if new size is same as old, we're done */
1520 if (pMultibuffers->width == pWin->drawable.width &&
1521 pMultibuffers->height == pWin->drawable.height)
1522 return TRUE;
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;
1539 sourcex = 0;
1540 sourcey = 0;
1541 savewidth = pMultibuffers->width;
1542 saveheight = pMultibuffers->height;
1543 /* clip rectangle to source and destination */
1544 if (destx < 0)
1546 savewidth += destx;
1547 sourcex -= destx;
1548 destx = 0;
1550 if (destx + savewidth > width)
1551 savewidth = width - destx;
1552 if (desty < 0)
1554 saveheight += desty;
1555 sourcey -= desty;
1556 desty = 0;
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);
1567 if (clear)
1569 SetupBackgroundPainter (pWin, pGC);
1570 clearRect.x = 0;
1571 clearRect.y = 0;
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);
1580 if (!pPixmap)
1582 DestroyImageBuffers (pWin);
1583 break;
1585 ValidateGC ((DrawablePtr)pPixmap, pGC);
1587 * I suppose this could avoid quite a bit of work if
1588 * it computed the minimal area required.
1590 if (clear)
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,
1597 destx, desty);
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,
1606 (pointer) pPixmap);
1609 FreeScratchGC (pGC);
1610 return TRUE;
1613 /* Resource delete func for MultibufferDrawableResType */
1614 /*ARGSUSED*/
1615 static int
1616 MultibufferDrawableDelete (value, id)
1617 pointer value;
1618 XID id;
1620 DrawablePtr pDrawable = (DrawablePtr)value;
1621 WindowPtr pWin;
1622 MultibuffersPtr pMultibuffers;
1623 PixmapPtr pPixmap;
1625 if (pDrawable->type == DRAWABLE_WINDOW)
1627 pWin = (WindowPtr) pDrawable;
1628 pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr;
1629 pPixmap = pMultibuffers->buffers[pMultibuffers->displayedMultibuffer].pPixmap;
1631 else
1633 pPixmap = (PixmapPtr) pDrawable;
1635 (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
1636 return Success;
1639 /* Resource delete func for MultibufferResType */
1640 /*ARGSUSED*/
1641 static int
1642 MultibufferDelete (value, id)
1643 pointer value;
1644 XID 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);
1656 return Success;
1659 /* Resource delete func for MultibuffersResType */
1660 /*ARGSUSED*/
1661 static int
1662 MultibuffersDelete (value, id)
1663 pointer value;
1664 XID id;
1666 MultibuffersPtr pMultibuffers = (MultibuffersPtr)value;
1667 int i;
1669 if (pMultibuffers->refcnt == pMultibuffers->numMultibuffer)
1671 for (i = pMultibuffers->numMultibuffer; --i >= 0; )
1672 FreeResource (pMultibuffers->buffers[i].pPixmap->drawable.id, 0);
1674 return Success;
1677 /* Resource delete func for OtherClientResType */
1678 static int
1679 OtherClientDelete (value, id)
1680 pointer value;
1681 XID id;
1683 MultibufferPtr pMultibuffer = (MultibufferPtr)value;
1684 register OtherClientsPtr other, prev;
1686 prev = 0;
1687 for (other = pMultibuffer->otherClients; other; other = other->next)
1689 if (other->resource == id)
1691 if (prev)
1692 prev->next = other->next;
1693 else
1694 pMultibuffer->otherClients = other->next;
1695 xfree (other);
1696 RecalculateMultibufferOtherEvents (pMultibuffer);
1697 break;
1699 prev = other;
1701 return Success;
1704 static int
1705 EventSelectForMultibuffer (pMultibuffer, client, mask)
1706 MultibufferPtr pMultibuffer;
1707 ClientPtr client;
1708 Mask mask;
1710 OtherClientsPtr other;
1712 if (mask & ~ValidEventMasks)
1714 client->errorValue = mask;
1715 return BadValue;
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))
1727 if (mask == 0)
1729 FreeResource (other->resource, RT_NONE);
1730 break;
1732 other->mask = mask;
1733 break;
1736 if (!other)
1737 { /* new client that never selected events on this buffer before */
1738 other = (OtherClients *) xalloc (sizeof (OtherClients));
1739 if (!other)
1740 return BadAlloc;
1741 other->mask = mask;
1742 other->resource = FakeClientID (client->index);
1743 if (!AddResource (other->resource, OtherClientResType, (pointer) pMultibuffer))
1745 xfree (other);
1746 return BadAlloc;
1748 other->next = pMultibuffer->otherClients;
1749 pMultibuffer->otherClients = other;
1751 RecalculateMultibufferOtherEvents (pMultibuffer);
1753 return (client->noClientException);
1756 /* or together all the otherClients event masks */
1757 static void
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 */
1771 static void
1772 BumpTimeStamp (ts, inc)
1773 TimeStamp *ts;
1774 CARD32 inc;
1776 CARD32 newms;
1778 newms = ts->milliseconds + inc;
1779 if (newms < ts->milliseconds)
1780 ts->months++;
1781 ts->milliseconds = newms;