home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / extensions / server / multibuf.c.orig < prev    next >
Encoding:
Text File  |  1991-06-01  |  44.8 KB  |  1,662 lines

  1. /************************************************************
  2. Copyright 1989 by The Massachusetts Institute of Technology
  3.  
  4. Permission to use, copy, modify, and distribute this
  5. software and its documentation for any purpose and without
  6. fee is hereby granted, provided that the above copyright
  7. no- tice appear in all copies and that both that copyright
  8. no- tice and this permission notice appear in supporting
  9. docu- mentation, and that the name of MIT not be used in
  10. advertising or publicity pertaining to distribution of the
  11. software without specific prior written permission.
  12. M.I.T. makes no representation about the suitability of
  13. this software for any purpose. It is provided "as is"
  14. without any express or implied warranty.
  15.  
  16. MIT DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
  17. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
  18. NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MIT BE  LI-
  19. ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
  21. PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
  22. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
  23. THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  
  25. ********************************************************/
  26.  
  27. /* $XConsortium: multibuf.c,v 1.11 91/06/01 13:25:50 rws Exp $ */
  28. #define NEED_REPLIES
  29. #define NEED_EVENTS
  30. #include <stdio.h>
  31. #include "X.h"
  32. #include "Xproto.h"
  33. #include "misc.h"
  34. #include "os.h"
  35. #include "windowstr.h"
  36. #include "scrnintstr.h"
  37. #include "pixmapstr.h"
  38. #include "extnsionst.h"
  39. #include "dixstruct.h"
  40. #include "resource.h"
  41. #include "opaque.h"
  42. #define _MULTIBUF_SERVER_    /* don't want Xlib structures */
  43. #include "multibufst.h"
  44. #include "regionstr.h"
  45. #include "gcstruct.h"
  46. #include "inputstr.h"
  47. #include <sys/time.h>
  48.  
  49. /*
  50.  * per-Multibuffer data
  51.  */
  52.  
  53. typedef struct _Multibuffers    *MultibuffersPtr;
  54.  
  55. #define SameClient(obj,client) \
  56.     (CLIENT_BITS((obj)->resource) == (client)->clientAsMask)
  57. #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
  58. #define bClient(b)   (clients[CLIENT_ID(b->pPixmap->drawable.id)])
  59.  
  60. #define ValidEventMasks (ExposureMask|MultibufferClobberNotifyMask|MultibufferUpdateNotifyMask)
  61.  
  62. typedef struct _Multibuffer {
  63.     MultibuffersPtr pMultibuffers;  /* associated window data */
  64.     Mask        eventMask;        /* MultibufferClobberNotifyMask|ExposureMask|MultibufferUpdateNotifyMask */
  65.     Mask        otherEventMask; /* mask of all other clients event masks */
  66.     OtherClients    *otherClients;
  67.     int            number;        /* index into array */
  68.     int            side;        /* alwys Mono */
  69.     int            clobber;        /* Unclobbered, PartiallyClobbered, FullClobbered */
  70.     PixmapPtr        pPixmap;        /* associated pixmap */
  71. } MultibufferRec, *MultibufferPtr;
  72.  
  73. /*
  74.  * per-window data
  75.  */
  76.  
  77. typedef struct _Multibuffers {
  78.     WindowPtr    pWindow;        /* associated window */
  79.     int        numMultibuffer;        /* count of buffers */
  80.     int        displayedMultibuffer;    /* currently active buffer */
  81.     int        updateAction;        /* Undefined, Background, Untouched, Copied */
  82.     int        updateHint;        /* Frequent, Intermittent, Static */
  83.     int        windowMode;        /* always Mono */
  84.  
  85.     TimeStamp    lastUpdate;        /* time of last update */
  86.  
  87.     unsigned short    width, height;    /* last known window size */
  88.     short        x, y;        /* for static gravity */
  89.  
  90.     MultibufferPtr    buffers;
  91. } MultibuffersRec;
  92.  
  93. /*
  94.  * per-screen data
  95.  */
  96. typedef struct _MultibufferScreen {
  97.     Bool    (*PositionWindow)();
  98. } MultibufferScreenRec, *MultibufferScreenPtr;
  99.  
  100. /*
  101.  * per display-image-buffers request data.
  102.  */
  103.  
  104. typedef struct _DisplayRequest {
  105.     struct _DisplayRequest    *next;
  106.     TimeStamp            activateTime;
  107.     ClientPtr            pClient;
  108.     XID                id;
  109. } DisplayRequestRec, *DisplayRequestPtr;
  110.  
  111. static unsigned char    MultibufferReqCode;
  112. static int        MultibufferEventBase;
  113. static int        MultibufferErrorBase;
  114. static int        MultibufferScreenIndex = -1;
  115. static int        MultibufferWindowIndex = -1;
  116.  
  117. static int        BlockHandlerRegistered;
  118. static void        MultibufferBlockHandler(), MultibufferWakeupHandler();
  119.  
  120. static void        PerformDisplayRequest ();
  121. static void        DisposeDisplayRequest ();
  122. static Bool        QueueDisplayRequest ();
  123.  
  124. static void        BumpTimeStamp ();
  125.  
  126. static void        MultibufferExpose ();
  127. static void        MultibufferUpdate ();
  128. static void        AliasMultibuffer ();
  129. static void        DisposeMultibuffers ();
  130. static void        RecalculateMultibufferOtherEvents ();
  131. static int        EventSelectForMultibuffer();
  132.  
  133. /*
  134.  * The Pixmap associated with a buffer can be found as a resource
  135.  * with this type
  136.  */
  137. static RESTYPE        MultibufferDrawableResType;
  138. static void        MultibufferDrawableDelete ();
  139. /*
  140.  * The per-buffer data can be found as a resource with this type.
  141.  * the resource id of the per-buffer data is the same as the resource
  142.  * id of the pixmap
  143.  */
  144. static RESTYPE        MultibufferResType;
  145. static void        MultibufferDelete ();
  146. /*
  147.  * The per-window data can be found as a resource with this type,
  148.  * using the window resource id
  149.  */
  150. static RESTYPE        MultibuffersResType;
  151. static void        MultibuffersDelete ();
  152. /*
  153.  * Per display-buffers request is attached to a resource so that
  154.  * it will disappear if the client dies before the request should
  155.  * be processed
  156.  */
  157. static RESTYPE        DisplayRequestResType;
  158. static void        DisplayRequestDelete ();
  159. /*
  160.  * Clients other than the buffer creator attach event masks in
  161.  * OtherClient structures; each has a resource of this type.
  162.  */
  163. static RESTYPE        OtherClientResType;
  164. static void        OtherClientDelete ();
  165.  
  166. /****************
  167.  * MultibufferExtensionInit
  168.  *
  169.  * Called from InitExtensions in main()
  170.  *
  171.  ****************/
  172.  
  173. static int        ProcMultibufferDispatch(), SProcMultibufferDispatch();
  174. static void        MultibufferResetProc();
  175. static void        SClobberNotifyEvent(), SUpdateNotifyEvent();
  176. static Bool        MultibufferPositionWindow();
  177.  
  178. void
  179. MultibufferExtensionInit()
  180. {
  181.     ExtensionEntry        *extEntry;
  182.     int                i, j;
  183.     ScreenPtr            pScreen;
  184.     MultibufferScreenPtr    pMultibufferScreen;
  185.  
  186.     /*
  187.      * allocate private pointers in windows and screens.  Allocating
  188.      * window privates may seem like an unnecessary expense, but every
  189.      * PositionWindow call must check to see if the window is
  190.      * multi-buffered; a resource lookup is too expensive.
  191.      */
  192.     MultibufferScreenIndex = AllocateScreenPrivateIndex ();
  193.     if (MultibufferScreenIndex < 0)
  194.     return;
  195.     MultibufferWindowIndex = AllocateWindowPrivateIndex ();
  196.     for (i = 0; i < screenInfo.numScreens; i++)
  197.     {
  198.     pScreen = screenInfo.screens[i];
  199.     if (!AllocateWindowPrivate (pScreen, MultibufferWindowIndex, 0) ||
  200.         !(pMultibufferScreen = (MultibufferScreenPtr) xalloc (sizeof (MultibufferScreenRec))))
  201.     {
  202.         for (j = 0; j < i; j++)
  203.         xfree (screenInfo.screens[j]->devPrivates[MultibufferScreenIndex].ptr);
  204.         return;
  205.     }
  206.     pScreen->devPrivates[MultibufferScreenIndex].ptr = (pointer) pMultibufferScreen;
  207.     /*
  208.       * wrap PositionWindow to resize the pixmap when the window
  209.      * changes size
  210.       */
  211.     pMultibufferScreen->PositionWindow = pScreen->PositionWindow;
  212.     pScreen->PositionWindow = MultibufferPositionWindow;
  213.     }
  214.     /*
  215.      * create the resource types
  216.      */
  217.     MultibufferDrawableResType =
  218.     CreateNewResourceType(MultibufferDrawableDelete)|RC_CACHED|RC_DRAWABLE;
  219.     MultibufferResType = CreateNewResourceType(MultibufferDelete);
  220.     MultibuffersResType = CreateNewResourceType(MultibuffersDelete);
  221.     DisplayRequestResType = CreateNewResourceType(DisplayRequestDelete);
  222.     OtherClientResType = CreateNewResourceType(OtherClientDelete);
  223.     if (MultibufferDrawableResType && MultibufferResType &&
  224.     MultibuffersResType && DisplayRequestResType &&
  225.     OtherClientResType &&
  226.     (extEntry = AddExtension(MULTIBUFFER_PROTOCOL_NAME,
  227.                  MultibufferNumberEvents, 
  228.                  MultibufferNumberErrors,
  229.                  ProcMultibufferDispatch, SProcMultibufferDispatch,
  230.                  MultibufferResetProc, StandardMinorOpcode)))
  231.     {
  232.     MultibufferReqCode = (unsigned char)extEntry->base;
  233.     MultibufferEventBase = extEntry->eventBase;
  234.     MultibufferErrorBase = extEntry->errorBase;
  235.     EventSwapVector[MultibufferEventBase + MultibufferClobberNotify] = SClobberNotifyEvent;
  236.     EventSwapVector[MultibufferEventBase + MultibufferUpdateNotify] = SUpdateNotifyEvent;
  237.     }
  238. }
  239.  
  240. /*ARGSUSED*/
  241. static void
  242. MultibufferResetProc (extEntry)
  243. ExtensionEntry    *extEntry;
  244. {
  245.     int                i;
  246.     ScreenPtr            pScreen;
  247.     MultibufferScreenPtr    pMultibufferScreen;
  248.     
  249.     if (MultibufferScreenIndex < 0)
  250.     return;
  251.     for (i = 0; i < screenInfo.numScreens; i++)
  252.     {
  253.     pScreen = screenInfo.screens[i];
  254.     if (pScreen->devPrivates[MultibufferScreenIndex].ptr)
  255.     {
  256.         pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr;
  257.         pScreen->PositionWindow = pMultibufferScreen->PositionWindow;
  258.         xfree (pMultibufferScreen);
  259.     }
  260.     }
  261. }
  262.  
  263. static int
  264. ProcGetBufferVersion (client)
  265.     register ClientPtr    client;
  266. {
  267.     REQUEST(xMbufGetBufferVersionReq);
  268.     xMbufGetBufferVersionReply    rep;
  269.     register int        n;
  270.  
  271.     REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq);
  272.     rep.type = X_Reply;
  273.     rep.length = 0;
  274.     rep.sequenceNumber = client->sequence;
  275.     rep.majorVersion = MULTIBUFFER_MAJOR_VERSION;
  276.     rep.minorVersion = MULTIBUFFER_MINOR_VERSION;
  277.     if (client->swapped) {
  278.         swaps(&rep.sequenceNumber, n);
  279.         swapl(&rep.length, n);
  280.     }
  281.     WriteToClient(client, sizeof (xMbufGetBufferVersionReply), (char *)&rep);
  282.     return (client->noClientException);
  283. }
  284.  
  285. static int
  286. ProcCreateImageBuffers (client)
  287.     register ClientPtr    client;
  288. {
  289.     REQUEST(xMbufCreateImageBuffersReq);
  290.     xMbufCreateImageBuffersReply    rep;
  291.     register int        n;
  292.     WindowPtr            pWin;
  293.     XID                *ids;
  294.     int                len, nbuf;
  295.     int                i;
  296.     MultibuffersPtr            pMultibuffers;
  297.     MultibufferPtr            pMultibuffer;
  298.     ScreenPtr            pScreen;
  299.     int                width, height, depth;
  300.  
  301.     REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
  302.     len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2);
  303.     if (len == 0)
  304.     return BadLength;
  305.     if (!(pWin = LookupWindow (stuff->window, client)))
  306.     return BadWindow;
  307.     if (pWin->drawable.class == InputOnly)
  308.     return BadMatch;
  309.     switch (stuff->updateAction)
  310.     {
  311.     case MultibufferUpdateActionUndefined:
  312.     case MultibufferUpdateActionBackground:
  313.     case MultibufferUpdateActionUntouched:
  314.     case MultibufferUpdateActionCopied:
  315.     break;
  316.     default:
  317.     client->errorValue = stuff->updateAction;
  318.     return BadValue;
  319.     }
  320.     switch (stuff->updateHint)
  321.     {
  322.     case MultibufferUpdateHintFrequent:
  323.     case MultibufferUpdateHintIntermittent:
  324.     case MultibufferUpdateHintStatic:
  325.     break;
  326.     default:
  327.     client->errorValue = stuff->updateHint;
  328.     return BadValue;
  329.     }
  330.     nbuf = len;
  331.     ids = (XID *) &stuff[1];
  332.     for (i = 0; i < nbuf; i++)
  333.     {
  334.     LEGAL_NEW_RESOURCE(ids[i], client);
  335.     }
  336.     pMultibuffers = (MultibuffersPtr) xalloc (sizeof (MultibuffersRec));
  337.     if (!pMultibuffers)
  338.     return BadAlloc;
  339.     pMultibuffers->pWindow = pWin;
  340.     pMultibuffers->buffers = (MultibufferPtr) xalloc (nbuf * sizeof (MultibufferRec));
  341.     if (!pMultibuffers->buffers)
  342.     {
  343.     xfree (pMultibuffers);
  344.     return BadAlloc;
  345.     }
  346.     if (!AddResource (pWin->drawable.id, MultibuffersResType, (pointer) pMultibuffers))
  347.     {
  348.     xfree (pMultibuffers->buffers);
  349.     xfree (pMultibuffers);
  350.     return BadAlloc;
  351.     }
  352.     width = pWin->drawable.width;
  353.     height = pWin->drawable.height;
  354.     depth = pWin->drawable.depth;
  355.     pScreen = pWin->drawable.pScreen;
  356.     for (i = 0; i < nbuf; i++)
  357.     {
  358.     pMultibuffer = &pMultibuffers->buffers[i];
  359.     pMultibuffer->eventMask = 0L;
  360.     pMultibuffer->otherEventMask = 0L;
  361.     pMultibuffer->otherClients = (OtherClientsPtr) NULL;
  362.     pMultibuffer->number = i;
  363.     pMultibuffer->side = MultibufferSideMono;
  364.     pMultibuffer->clobber = MultibufferUnclobbered;
  365.     pMultibuffer->pMultibuffers = pMultibuffers;
  366.     if (!AddResource (ids[i], MultibufferResType, (pointer) pMultibuffer))
  367.         break;
  368.     pMultibuffer->pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth);
  369.     if (!pMultibuffer->pPixmap)
  370.         break;
  371.     if (!AddResource (ids[i], MultibufferDrawableResType, (pointer) pMultibuffer->pPixmap))
  372.     {
  373.         FreeResource (ids[i], MultibufferResType);
  374.         (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
  375.         break;
  376.     }
  377.     pMultibuffer->pPixmap->drawable.id = ids[i];
  378.     }
  379.     pMultibuffers->numMultibuffer = i;
  380.     pMultibuffers->displayedMultibuffer = -1;
  381.     if (i > 0)
  382.     AliasMultibuffer (pMultibuffers, 0);
  383.     pMultibuffers->updateAction = stuff->updateAction;
  384.     pMultibuffers->updateHint = stuff->updateHint;
  385.     pMultibuffers->windowMode = MultibufferModeMono;
  386.     pMultibuffers->lastUpdate.months = 0;
  387.     pMultibuffers->lastUpdate.milliseconds = 0;
  388.     pMultibuffers->width = width;
  389.     pMultibuffers->height = height;
  390.     pWin->devPrivates[MultibufferWindowIndex].ptr = (pointer) pMultibuffers;
  391.     rep.type = X_Reply;
  392.     rep.length = 0;
  393.     rep.sequenceNumber = client->sequence;
  394.     rep.numberBuffer = pMultibuffers->numMultibuffer;
  395.     if (client->swapped)
  396.     {
  397.         swaps(&rep.sequenceNumber, n);
  398.         swapl(&rep.length, n);
  399.     swaps(&rep.numberBuffer, n);
  400.     }
  401.     WriteToClient(client, sizeof (xMbufCreateImageBuffersReply), (char *)&rep);
  402.     return (client->noClientException);
  403. }
  404.  
  405. static int
  406. ProcDisplayImageBuffers (client)
  407.     register ClientPtr    client;
  408. {
  409.     REQUEST(xMbufDisplayImageBuffersReq);
  410.     MultibufferPtr        *pMultibuffer;
  411.     MultibuffersPtr        *ppMultibuffers;
  412.     int            nbuf;
  413.     XID            *ids;
  414.     int            i, j;
  415.     CARD32        minDelay, maxDelay;
  416.     TimeStamp        activateTime, bufferTime;
  417.     
  418.     REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
  419.     nbuf = stuff->length - (sizeof (xMbufDisplayImageBuffersReq) >> 2);
  420.     if (!nbuf)
  421.     return Success;
  422.     minDelay = stuff->minDelay;
  423.     maxDelay = stuff->maxDelay;
  424.     ids = (XID *) &stuff[1];
  425.     ppMultibuffers = (MultibuffersPtr *) xalloc (nbuf * sizeof (MultibuffersPtr));
  426.     pMultibuffer = (MultibufferPtr *) xalloc (nbuf * sizeof (MultibufferPtr));
  427.     if (!ppMultibuffers || !pMultibuffer)
  428.     {
  429.     xfree (ppMultibuffers);
  430.     xfree (pMultibuffer);
  431.     client->errorValue = 0;
  432.     return BadAlloc;
  433.     }
  434.     activateTime.months = 0;
  435.     activateTime.milliseconds = 0;
  436.     for (i = 0; i < nbuf; i++)
  437.     {
  438.     pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], MultibufferResType);
  439.     if (!pMultibuffer[i])
  440.     {
  441.         xfree (ppMultibuffers);
  442.         xfree (pMultibuffer);
  443.         client->errorValue = ids[i];
  444.         return MultibufferErrorBase + MultibufferBadBuffer;
  445.     }
  446.     ppMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
  447.     for (j = 0; j < i; j++)
  448.     {
  449.         if (ppMultibuffers[i] == ppMultibuffers[j])
  450.         {
  451.             xfree (ppMultibuffers);
  452.             xfree (pMultibuffer);
  453.         client->errorValue = ids[i];
  454.             return BadMatch;
  455.         }
  456.     }
  457.     bufferTime = ppMultibuffers[i]->lastUpdate;
  458.     BumpTimeStamp (&bufferTime, minDelay);
  459.     if (CompareTimeStamps (bufferTime, activateTime) == LATER)
  460.         activateTime = bufferTime;
  461.     }
  462.     UpdateCurrentTime ();
  463.     if (CompareTimeStamps (activateTime, currentTime) == LATER &&
  464.     QueueDisplayRequest (client, activateTime))
  465.     {
  466.     ;
  467.     }
  468.     else
  469.     PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf);
  470.     xfree (ppMultibuffers);
  471.     xfree (pMultibuffer);
  472.     return Success;
  473. }
  474.  
  475. static int
  476. ProcDestroyImageBuffers (client)
  477.     register ClientPtr    client;
  478. {
  479.     REQUEST (xMbufDestroyImageBuffersReq);
  480.     WindowPtr    pWin;
  481.  
  482.     REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
  483.     if (!(pWin = LookupWindow (stuff->window, client)))
  484.     return BadWindow;
  485.     DisposeMultibuffers (pWin);
  486.     return Success;
  487. }
  488.  
  489. static int
  490. ProcSetMBufferAttributes (client)
  491.     register ClientPtr    client;
  492. {
  493.     REQUEST (xMbufSetMBufferAttributesReq);
  494.     WindowPtr    pWin;
  495.     MultibuffersPtr    pMultibuffers;
  496.     int        len;
  497.     Mask    vmask;
  498.     Mask    index;
  499.     CARD32    updateHint;
  500.     XID        *vlist;
  501.  
  502.     REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq);
  503.     pWin = LookupWindow (stuff->window, client);
  504.     if (!pWin)
  505.     return BadWindow;
  506.     pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
  507.     if (!pMultibuffers)
  508.     return BadMatch;
  509.     len = stuff->length - (sizeof (xMbufSetMBufferAttributesReq) >> 2);
  510.     vmask = stuff->valueMask;
  511.     if (len != Ones (vmask))
  512.     return BadLength;
  513.     vlist = (XID *) &stuff[1];
  514.     while (vmask)
  515.     {
  516.     index = (Mask) lowbit (vmask);
  517.     vmask &= ~index;
  518.     switch (index)
  519.     {
  520.     case MultibufferWindowUpdateHint:
  521.         updateHint = (CARD32) *vlist;
  522.         switch (updateHint)
  523.         {
  524.         case MultibufferUpdateHintFrequent:
  525.         case MultibufferUpdateHintIntermittent:
  526.         case MultibufferUpdateHintStatic:
  527.         pMultibuffers->updateHint = updateHint;
  528.         break;
  529.         default:
  530.         client->errorValue = updateHint;
  531.         return BadValue;
  532.         }
  533.         vlist++;
  534.         break;
  535.     default:
  536.         client->errorValue = stuff->valueMask;
  537.         return BadValue;
  538.     }
  539.     }
  540.     return Success;
  541. }
  542.  
  543. static int
  544. ProcGetMBufferAttributes (client)
  545.     ClientPtr    client;
  546. {
  547.     REQUEST (xMbufGetMBufferAttributesReq);
  548.     WindowPtr    pWin;
  549.     MultibuffersPtr    pMultibuffers;
  550.     XID        *ids;
  551.     xMbufGetMBufferAttributesReply  rep;
  552.     int        i, n;
  553.  
  554.     REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq);
  555.     pWin = LookupWindow (stuff->window, client);
  556.     if (!pWin)
  557.     return BadWindow;
  558.     pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
  559.     if (!pMultibuffers)
  560.     return BadAccess;
  561.     ids = (XID *) ALLOCATE_LOCAL (pMultibuffers->numMultibuffer * sizeof (XID));
  562.     if (!ids)
  563.     return BadAlloc;
  564.     for (i = 0; i < pMultibuffers->numMultibuffer; i++)
  565.     ids[i] = pMultibuffers->buffers[i].pPixmap->drawable.id;
  566.     rep.type = X_Reply;
  567.     rep.sequenceNumber = client->sequence;
  568.     rep.length = pMultibuffers->numMultibuffer;
  569.     rep.displayedBuffer = pMultibuffers->displayedMultibuffer;
  570.     rep.updateAction = pMultibuffers->updateAction;
  571.     rep.updateHint = pMultibuffers->updateHint;
  572.     rep.windowMode = pMultibuffers->windowMode;
  573.     if (client->swapped)
  574.     {
  575.         swaps(&rep.sequenceNumber, n);
  576.         swapl(&rep.length, n);
  577.     swaps(&rep.displayedBuffer, n);
  578.     SwapLongs (ids, pMultibuffers->numMultibuffer);
  579.     }
  580.     WriteToClient (client, sizeof (xMbufGetMBufferAttributesReply), &rep);
  581.     WriteToClient (client, (int) (pMultibuffers->numMultibuffer * sizeof (XID)), ids);
  582.     DEALLOCATE_LOCAL((pointer) ids);
  583.     return client->noClientException;
  584. }
  585.  
  586. static int
  587. ProcSetBufferAttributes (client)
  588.     register ClientPtr    client;
  589. {
  590.     REQUEST(xMbufSetBufferAttributesReq);
  591.     MultibufferPtr    pMultibuffer;
  592.     int        len;
  593.     Mask    vmask, index;
  594.     XID        *vlist;
  595.     Mask    eventMask;
  596.     int        result;
  597.  
  598.     REQUEST_AT_LEAST_SIZE (xMbufSetBufferAttributesReq);
  599.     pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
  600.     if (!pMultibuffer)
  601.     return MultibufferErrorBase + MultibufferBadBuffer;
  602.     len = stuff->length - (sizeof (xMbufSetBufferAttributesReq) >> 2);
  603.     vmask = stuff->valueMask;
  604.     if (len != Ones (vmask))
  605.     return BadLength;
  606.     vlist = (XID *) &stuff[1];
  607.     while (vmask)
  608.     {
  609.     index = (Mask) lowbit (vmask);
  610.     vmask &= ~index;
  611.     switch (index)
  612.     {
  613.     case MultibufferBufferEventMask:
  614.         eventMask = (Mask) *vlist;
  615.         vlist++;
  616.         result = EventSelectForMultibuffer (pMultibuffer, client, eventMask);
  617.         if (result != Success)
  618.         return result;
  619.         break;
  620.     default:
  621.         client->errorValue = stuff->valueMask;
  622.         return BadValue;
  623.     }
  624.     }
  625.     return Success;
  626. }
  627.  
  628. ProcGetBufferAttributes (client)
  629.     register ClientPtr    client;
  630. {
  631.     REQUEST(xMbufGetBufferAttributesReq);
  632.     MultibufferPtr    pMultibuffer;
  633.     xMbufGetBufferAttributesReply    rep;
  634.     OtherClientsPtr        other;
  635.     int                n;
  636.  
  637.     REQUEST_SIZE_MATCH (xMbufGetBufferAttributesReq);
  638.     pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
  639.     if (!pMultibuffer)
  640.     return MultibufferErrorBase + MultibufferBadBuffer;
  641.     rep.type = X_Reply;
  642.     rep.sequenceNumber = client->sequence;
  643.     rep.length = 0;
  644.     rep.window = pMultibuffer->pMultibuffers->pWindow->drawable.id;
  645.     if (bClient (pMultibuffer) == client)
  646.     rep.eventMask = pMultibuffer->eventMask;
  647.     else
  648.     {
  649.     rep.eventMask = (Mask) 0L;
  650.     for (other = pMultibuffer->otherClients; other; other = other->next)
  651.         if (SameClient (other, client))
  652.         {
  653.         rep.eventMask = other->mask;
  654.         break;
  655.         }
  656.     }
  657.     rep.bufferIndex = pMultibuffer->number;
  658.     rep.side = pMultibuffer->side;
  659.     if (client->swapped)
  660.     {
  661.         swaps(&rep.sequenceNumber, n);
  662.         swapl(&rep.length, n);
  663.     swapl(&rep.window, n);
  664.     swapl(&rep.eventMask, n);
  665.     swaps(&rep.bufferIndex, n);
  666.     }
  667.     WriteToClient(client, sizeof (xMbufGetBufferAttributesReply), (char *)&rep);
  668.     return (client->noClientException);
  669. }
  670.  
  671. static int
  672. ProcGetBufferInfo (client)
  673.     register ClientPtr    client;
  674. {
  675.     REQUEST (xMbufGetBufferInfoReq);
  676.     DrawablePtr            pDrawable;
  677.     xMbufGetBufferInfoReply rep;
  678.     ScreenPtr            pScreen;
  679.     int                i, j, k;
  680.     int                n;
  681.     xMbufBufferInfo        *pInfo;
  682.     int                nInfo;
  683.     DepthPtr            pDepth;
  684.  
  685.     pDrawable = (DrawablePtr) LookupDrawable (stuff->drawable, client);
  686.     if (!pDrawable)
  687.     return BadDrawable;
  688.     pScreen = pDrawable->pScreen;
  689.     nInfo = 0;
  690.     for (i = 0; i < pScreen->numDepths; i++)
  691.     {
  692.     pDepth = &pScreen->allowedDepths[i];
  693.     nInfo += pDepth->numVids;
  694.     }
  695.     pInfo = (xMbufBufferInfo *)
  696.         ALLOCATE_LOCAL (pScreen->numVisuals * sizeof (xMbufBufferInfo));
  697.     if (!pInfo)
  698.     return BadAlloc;
  699.  
  700.     rep.type = X_Reply;
  701.     rep.sequenceNumber = client->sequence;
  702.     rep.length = nInfo * (sizeof (xMbufBufferInfo) >> 2);
  703.     rep.normalInfo = nInfo;
  704.     rep.stereoInfo = 0;
  705.     if (client->swapped)
  706.     {
  707.     swaps(&rep.sequenceNumber, n);
  708.     swapl(&rep.length, n);
  709.     swaps(&rep.normalInfo, n);
  710.     swaps(&rep.stereoInfo, n);
  711.     }
  712.  
  713.     k = 0;
  714.     for (i = 0; i < pScreen->numDepths; i++)
  715.     {
  716.     pDepth = &pScreen->allowedDepths[i];
  717.     for (j = 0; j < pDepth->numVids; j++)
  718.     {
  719.         pInfo[k].visualID = pDepth->vids[j];
  720.         pInfo[k].maxBuffers = 0;
  721.         pInfo[k].depth = pDepth->depth;
  722.         if (client->swapped)
  723.         {
  724.         swapl (&pInfo[k].visualID, n);
  725.         swaps (&pInfo[k].maxBuffers, n);
  726.         }
  727.         k++;
  728.     }
  729.     }
  730.     WriteToClient (client, sizeof (xMbufGetBufferInfoReply), (pointer) &rep);
  731.     WriteToClient (client, (int) nInfo * sizeof (xMbufBufferInfo), (pointer) pInfo);
  732.     DEALLOCATE_LOCAL ((pointer) pInfo);
  733.     return client->noClientException;
  734. }
  735.  
  736. static int
  737. ProcMultibufferDispatch (client)
  738.     register ClientPtr    client;
  739. {
  740.     REQUEST(xReq);
  741.     switch (stuff->data) {
  742.     case X_MbufGetBufferVersion:
  743.     return ProcGetBufferVersion (client);
  744.     case X_MbufCreateImageBuffers:
  745.     return ProcCreateImageBuffers (client);
  746.     case X_MbufDisplayImageBuffers:
  747.     return ProcDisplayImageBuffers (client);
  748.     case X_MbufDestroyImageBuffers:
  749.     return ProcDestroyImageBuffers (client);
  750.     case X_MbufSetMBufferAttributes:
  751.     return ProcSetMBufferAttributes (client);
  752.     case X_MbufGetMBufferAttributes:
  753.     return ProcGetMBufferAttributes (client);
  754.     case X_MbufSetBufferAttributes:
  755.     return ProcSetBufferAttributes (client);
  756.     case X_MbufGetBufferAttributes:
  757.     return ProcGetBufferAttributes (client);
  758.     case X_MbufGetBufferInfo:
  759.     return ProcGetBufferInfo (client);
  760.     default:
  761.     return BadRequest;
  762.     }
  763. }
  764.  
  765. static int
  766. SProcGetBufferVersion (client)
  767.     register ClientPtr    client;
  768. {
  769.     register int    n;
  770.     REQUEST (xMbufGetBufferVersionReq);
  771.  
  772.     swaps (&stuff->length, n);
  773.     return ProcGetBufferVersion (client);
  774. }
  775.  
  776. static int
  777. SProcCreateImageBuffers (client)
  778.     register ClientPtr    client;
  779. {
  780.     register int    n;
  781.     REQUEST (xMbufCreateImageBuffersReq);
  782.  
  783.     swaps (&stuff->length, n);
  784.     REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
  785.     swapl (&stuff->window, n);
  786.     SwapRestL(stuff);
  787.     return ProcCreateImageBuffers (client);
  788. }
  789.  
  790. static int
  791. SProcDisplayImageBuffers (client)
  792.     register ClientPtr    client;
  793. {
  794.     register int    n;
  795.     REQUEST (xMbufDisplayImageBuffersReq);
  796.     
  797.     swaps (&stuff->length, n);
  798.     REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
  799.     swaps (&stuff->minDelay, n);
  800.     swaps (&stuff->maxDelay, n);
  801.     SwapRestL(stuff);
  802.     return ProcDisplayImageBuffers (client);
  803. }
  804.  
  805. static int
  806. SProcDestroyImageBuffers (client)
  807.     register ClientPtr    client;
  808. {
  809.     register int    n;
  810.     REQUEST (xMbufDestroyImageBuffersReq);
  811.     
  812.     swaps (&stuff->length, n);
  813.     REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
  814.     swapl (&stuff->window, n);
  815.     return ProcDestroyImageBuffers (client);
  816. }
  817.  
  818. static int
  819. SProcSetMBufferAttributes (client)
  820.     register ClientPtr    client;
  821. {
  822.     register int    n;
  823.     REQUEST (xMbufSetMBufferAttributesReq);
  824.  
  825.     swaps (&stuff->length, n);
  826.     REQUEST_AT_LEAST_SIZE(xMbufSetMBufferAttributesReq);
  827.     swapl (&stuff->window, n);
  828.     swapl (&stuff->valueMask, n);
  829.     SwapRestL(stuff);
  830.     return ProcSetMBufferAttributes (client);
  831. }
  832.  
  833. static int
  834. SProcGetMBufferAttributes (client)
  835.     register ClientPtr    client;
  836. {
  837.     register int    n;
  838.     REQUEST (xMbufGetMBufferAttributesReq);
  839.  
  840.     swaps (&stuff->length, n);
  841.     REQUEST_AT_LEAST_SIZE(xMbufGetMBufferAttributesReq);
  842.     swapl (&stuff->window, n);
  843.     return ProcGetMBufferAttributes (client);
  844. }
  845.  
  846. static int
  847. SProcSetBufferAttributes (client)
  848.     register ClientPtr    client;
  849. {
  850.     register int    n;
  851.     REQUEST (xMbufSetBufferAttributesReq);
  852.  
  853.     swaps (&stuff->length, n);
  854.     REQUEST_AT_LEAST_SIZE(xMbufSetBufferAttributesReq);
  855.     swapl (&stuff->buffer, n);
  856.     swapl (&stuff->valueMask, n);
  857.     SwapRestL(stuff);
  858.     return ProcSetBufferAttributes (client);
  859. }
  860.  
  861. static int
  862. SProcGetBufferAttributes (client)
  863.     register ClientPtr    client;
  864. {
  865.     register int    n;
  866.     REQUEST (xMbufGetBufferAttributesReq);
  867.  
  868.     swaps (&stuff->length, n);
  869.     REQUEST_AT_LEAST_SIZE(xMbufGetBufferAttributesReq);
  870.     swapl (&stuff->buffer, n);
  871.     return ProcGetBufferAttributes (client);
  872. }
  873.  
  874. static int
  875. SProcGetBufferInfo (client)
  876.     register ClientPtr    client;
  877. {
  878.     register int    n;
  879.     REQUEST (xMbufGetBufferInfoReq);
  880.  
  881.     swaps (&stuff->length, n);
  882.     REQUEST_SIZE_MATCH (xMbufGetBufferInfoReq);
  883.     swapl (&stuff->drawable, n);
  884.     return ProcGetBufferInfo (client);
  885. }
  886.  
  887. static int
  888. SProcMultibufferDispatch (client)
  889.     register ClientPtr    client;
  890. {
  891.     REQUEST(xReq);
  892.     switch (stuff->data) {
  893.     case X_MbufGetBufferVersion:
  894.     return SProcGetBufferVersion (client);
  895.     case X_MbufCreateImageBuffers:
  896.     return SProcCreateImageBuffers (client);
  897.     case X_MbufDisplayImageBuffers:
  898.     return SProcDisplayImageBuffers (client);
  899.     case X_MbufDestroyImageBuffers:
  900.     return SProcDestroyImageBuffers (client);
  901.     case X_MbufSetMBufferAttributes:
  902.     return SProcSetMBufferAttributes (client);
  903.     case X_MbufGetMBufferAttributes:
  904.     return SProcGetMBufferAttributes (client);
  905.     case X_MbufSetBufferAttributes:
  906.     return SProcSetBufferAttributes (client);
  907.     case X_MbufGetBufferAttributes:
  908.     return SProcGetBufferAttributes (client);
  909.     case X_MbufGetBufferInfo:
  910.     return SProcGetBufferInfo (client);
  911.     default:
  912.     return BadRequest;
  913.     }
  914. }
  915.  
  916. static void
  917. SUpdateNotifyEvent (from, to)
  918.     xMbufUpdateNotifyEvent    *from, *to;
  919. {
  920.     to->type = from->type;
  921.     cpswaps (from->sequenceNumber, to->sequenceNumber);
  922.     cpswapl (from->buffer, to->buffer);
  923.     cpswapl (from->timeStamp, to->timeStamp);
  924. }
  925.  
  926. static void
  927. SClobberNotifyEvent (from, to)
  928.     xMbufClobberNotifyEvent    *from, *to;
  929. {
  930.     to->type = from->type;
  931.     cpswaps (from->sequenceNumber, to->sequenceNumber);
  932.     cpswapl (from->buffer, to->buffer);
  933.     to->state = from->state;
  934. }
  935.  
  936. static void
  937. SetupBackgroundPainter (pWin, pGC)
  938.     WindowPtr    pWin;
  939.     GCPtr    pGC;
  940. {
  941.     XID            gcvalues[4];
  942.     int            ts_x_origin, ts_y_origin;
  943.     PixUnion        background;
  944.     int            backgroundState;
  945.     Mask        gcmask;
  946.  
  947.     /*
  948.      * set up the gc to clear the pixmaps;
  949.      */
  950.     ts_x_origin = ts_y_origin = 0;
  951.  
  952.     backgroundState = pWin->backgroundState;
  953.     background = pWin->background;
  954.     if (backgroundState == ParentRelative) {
  955.     WindowPtr    pParent;
  956.  
  957.     pParent = pWin;
  958.     while (pParent->backgroundState == ParentRelative) {
  959.         ts_x_origin -= pParent->origin.x;
  960.         ts_y_origin -= pParent->origin.y;
  961.         pParent = pParent->parent;
  962.     }
  963.     backgroundState = pParent->backgroundState;
  964.     background = pParent->background;
  965.     }
  966.  
  967.     /*
  968.      * First take care of any ParentRelative stuff by altering the
  969.      * tile/stipple origin to match the coordinates of the upper-left
  970.      * corner of the first ancestor without a ParentRelative background.
  971.      * This coordinate is, of course, negative.
  972.      */
  973.  
  974.     if (backgroundState == BackgroundPixel)
  975.     {
  976.     gcvalues[0] = (XID) background.pixel;
  977.     gcvalues[1] = FillSolid;
  978.     gcmask = GCForeground|GCFillStyle;
  979.     }
  980.     else
  981.     {
  982.     gcvalues[0] = FillTiled;
  983.     gcvalues[1] = (XID) background.pixmap;
  984.     gcvalues[2] = ts_x_origin;
  985.     gcvalues[3] = ts_y_origin;
  986.     gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
  987.     }
  988.     DoChangeGC(pGC, gcmask, gcvalues, TRUE);
  989. }
  990.  
  991. static void
  992. PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf)
  993.     MultibufferPtr        *pMultibuffer;
  994.     MultibuffersPtr        *ppMultibuffers;
  995.     int            nbuf;
  996. {
  997.     GCPtr        pGC;
  998.     PixmapPtr        pPrevPixmap, pNewPixmap;
  999.     xRectangle        clearRect;
  1000.     WindowPtr        pWin;
  1001.     RegionPtr        pExposed;
  1002.     int            i;
  1003.     MultibufferPtr        pPrevMultibuffer;
  1004.     XID            bool;
  1005.  
  1006.     UpdateCurrentTime ();
  1007.     for (i = 0; i < nbuf; i++)
  1008.     {
  1009.     pWin = ppMultibuffers[i]->pWindow;
  1010.     pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
  1011.     pPrevMultibuffer = &ppMultibuffers[i]->buffers[ppMultibuffers[i]->displayedMultibuffer];
  1012.     pPrevPixmap = pPrevMultibuffer->pPixmap;
  1013.     pNewPixmap = pMultibuffer[i]->pPixmap;
  1014.     switch (ppMultibuffers[i]->updateAction)
  1015.     {
  1016.     case MultibufferUpdateActionUndefined:
  1017.         break;
  1018.     case MultibufferUpdateActionBackground:
  1019.         SetupBackgroundPainter (pWin, pGC);
  1020.         ValidateGC (pPrevPixmap, pGC);
  1021.         clearRect.x = 0;
  1022.         clearRect.y = 0;
  1023.         clearRect.width = pPrevPixmap->drawable.width;
  1024.         clearRect.height = pPrevPixmap->drawable.height;
  1025.         (*pGC->ops->PolyFillRect) (pPrevPixmap, pGC, 1, &clearRect);
  1026.         break;
  1027.     case MultibufferUpdateActionUntouched:
  1028.         if (pPrevMultibuffer->eventMask & ExposureMask)
  1029.         {
  1030.             bool = TRUE;
  1031.             DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE);
  1032.         }
  1033.         ValidateGC (pPrevPixmap, pGC);
  1034.         pExposed = (*pGC->ops->CopyArea)
  1035.                 ((DrawablePtr) pWin,
  1036.                  (DrawablePtr) pPrevPixmap,
  1037.                  pGC,
  1038.                  0, 0,
  1039.                  pWin->drawable.width, pWin->drawable.height,
  1040.                  0, 0);
  1041.         if (pPrevMultibuffer->eventMask & ExposureMask)
  1042.         {
  1043.             if (pExposed)
  1044.             {
  1045.             RegionPtr    pWinSize;
  1046.             extern RegionPtr    CreateUnclippedWinSize();
  1047.  
  1048.             pWinSize = CreateUnclippedWinSize (pWin);
  1049.             (*pWin->drawable.pScreen->Intersect) (pExposed,
  1050.                               pExposed, pWinSize);
  1051.             (*pWin->drawable.pScreen->RegionDestroy) (pWinSize);
  1052.                 MultibufferExpose (pPrevMultibuffer, pExposed);
  1053.                 (*pWin->drawable.pScreen->RegionDestroy) (pExposed);
  1054.             }
  1055.             bool = FALSE;
  1056.             DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE);
  1057.         }
  1058.         break;
  1059.     case MultibufferUpdateActionCopied:
  1060.         ValidateGC (pPrevPixmap, pGC);
  1061.         (*pGC->ops->CopyArea) (pNewPixmap, pPrevPixmap, pGC,
  1062.                    0, 0, pWin->drawable.width, pWin->drawable.height,
  1063.                    0, 0);
  1064.         break;
  1065.     }
  1066.     ValidateGC (pWin, pGC);
  1067.     (*pGC->ops->CopyArea) (pNewPixmap, pWin, pGC,
  1068.                    0, 0, pWin->drawable.width, pWin->drawable.height,
  1069.                    0, 0);
  1070.     ppMultibuffers[i]->lastUpdate = currentTime;
  1071.     MultibufferUpdate (pMultibuffer[i], ppMultibuffers[i]->lastUpdate.milliseconds);
  1072.     AliasMultibuffer (ppMultibuffers[i], pMultibuffer[i] - ppMultibuffers[i]->buffers);
  1073.     FreeScratchGC (pGC);
  1074.     }
  1075.     return;
  1076. }
  1077.  
  1078. static DisplayRequestPtr    pPendingRequests;
  1079.  
  1080. static void
  1081. DisposeDisplayRequest (pRequest)
  1082.     DisplayRequestPtr    pRequest;
  1083. {
  1084.     DisplayRequestPtr    pReq, pPrev;
  1085.  
  1086.     pPrev = 0;
  1087.     for (pReq = pPendingRequests; pReq; pReq = pReq->next)
  1088.     if (pReq == pRequest)
  1089.     {
  1090.         if (pPrev)
  1091.         pPrev->next = pReq->next;
  1092.         else
  1093.         pPendingRequests = pReq->next;
  1094.         xfree (pReq);
  1095.         break;
  1096.     }
  1097. }
  1098.  
  1099. static Bool
  1100. QueueDisplayRequest (client, activateTime)
  1101.     ClientPtr        client;
  1102.     TimeStamp        activateTime;
  1103. {
  1104.     DisplayRequestPtr    pRequest, pReq, pPrev;
  1105.  
  1106.     if (!BlockHandlerRegistered)
  1107.     {
  1108.     if (!RegisterBlockAndWakeupHandlers (MultibufferBlockHandler,
  1109.                          MultibufferWakeupHandler,
  1110.                          (pointer) 0))
  1111.     {
  1112.         return FALSE;
  1113.     }
  1114.     BlockHandlerRegistered = TRUE;
  1115.     }
  1116.     pRequest = (DisplayRequestPtr) xalloc (sizeof (DisplayRequestRec));
  1117.     if (!pRequest)
  1118.     return FALSE;
  1119.     pRequest->pClient = client;
  1120.     pRequest->activateTime = activateTime;
  1121.     pRequest->id = FakeClientID (client->index);
  1122.     if (!AddResource (pRequest->id, DisplayRequestResType, (pointer) pRequest))
  1123.     {
  1124.     xfree (pRequest);
  1125.     return FALSE;
  1126.     }
  1127.     pPrev = 0;
  1128.     for (pReq = pPendingRequests; pReq; pReq = pReq->next)
  1129.     {
  1130.     if (CompareTimeStamps (pReq->activateTime, activateTime) == LATER)
  1131.         break;
  1132.     pPrev = pReq;
  1133.     }
  1134.     if (pPrev)
  1135.     pPrev->next = pRequest;
  1136.     else
  1137.     pPendingRequests = pRequest;
  1138.     pRequest->next = pReq;
  1139.     if (client->swapped)
  1140.     {
  1141.         register int    n;
  1142.         REQUEST (xMbufDisplayImageBuffersReq);
  1143.         
  1144.         SwapRestL(stuff);
  1145.         swaps (&stuff->length, n);
  1146.         swaps (&stuff->minDelay, n);
  1147.         swaps (&stuff->maxDelay, n);
  1148.     }
  1149.     client->sequence--;
  1150.     ResetCurrentRequest (client);
  1151.     IgnoreClient (client);
  1152.     return TRUE;
  1153. }
  1154.  
  1155. static void
  1156. MultibufferBlockHandler (data, wt, LastSelectMask)
  1157.     pointer        data;        /* unused */
  1158.     struct timeval  **wt;        /* wait time */
  1159.     long        *LastSelectMask;
  1160. {
  1161.     DisplayRequestPtr        pReq, pNext;
  1162.     unsigned long        newdelay, olddelay;
  1163.     static struct timeval   delay_val;
  1164.  
  1165.     if (!pPendingRequests)
  1166.     return;
  1167.     UpdateCurrentTimeIf ();
  1168.     for (pReq = pPendingRequests; pReq; pReq = pNext)
  1169.     {
  1170.     pNext = pReq->next;
  1171.     if (CompareTimeStamps (pReq->activateTime, currentTime) == LATER)
  1172.         break;
  1173.     AttendClient (pReq->pClient);
  1174.     FreeResource (pReq->id, 0);
  1175.     }
  1176.     pReq = pPendingRequests;
  1177.     if (!pReq)
  1178.     return;
  1179.     newdelay = pReq->activateTime.milliseconds - currentTime.milliseconds;
  1180.     if (*wt == NULL)
  1181.     {
  1182.     delay_val.tv_sec = newdelay / 1000;
  1183.     delay_val.tv_usec = 1000 * (newdelay % 1000);
  1184.     *wt = &delay_val;
  1185.     }
  1186.     else
  1187.     {
  1188.     olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
  1189.     if (newdelay < olddelay)
  1190.     {
  1191.         (*wt)->tv_sec = newdelay / 1000;
  1192.         (*wt)->tv_usec = 1000 * (newdelay % 1000);
  1193.     }
  1194.     }
  1195. }
  1196.  
  1197. static void
  1198. MultibufferWakeupHandler (data, i, LastSelectMask)
  1199.     pointer        data;
  1200.     int            i;
  1201.     long        *LastSelectMask;
  1202. {
  1203.     DisplayRequestPtr    pReq, pNext;
  1204.  
  1205.     if (!pPendingRequests)
  1206.     {
  1207.     RemoveBlockAndWakeupHandlers (MultibufferBlockHandler,
  1208.                       MultibufferWakeupHandler,
  1209.                       (pointer) 0);
  1210.     BlockHandlerRegistered = 0;
  1211.     return;
  1212.     }
  1213.     UpdateCurrentTimeIf ();
  1214.     for (pReq = pPendingRequests; pReq; pReq = pNext)
  1215.     {
  1216.     pNext = pReq->next;
  1217.     if (CompareTimeStamps (pReq->activateTime, currentTime) == LATER)
  1218.         break;
  1219.     AttendClient (pReq->pClient);
  1220.     FreeResource (pReq->id, 0);
  1221.     }
  1222. }
  1223.  
  1224. /*
  1225.  * Deliver events to a buffer
  1226.  */
  1227.  
  1228. static int
  1229. DeliverEventsToMultibuffer (pMultibuffer, pEvents, count, filter)
  1230.     MultibufferPtr    pMultibuffer;
  1231.     xEvent    *pEvents;
  1232.     int        count;
  1233. {
  1234.     int deliveries = 0, nondeliveries = 0;
  1235.     int attempt;
  1236.     OtherClients *other;
  1237.  
  1238.     if (!((pMultibuffer->otherEventMask|pMultibuffer->eventMask) & filter))
  1239.     return 0;
  1240.     if (attempt = TryClientEvents(
  1241.     bClient(pMultibuffer), pEvents, count, pMultibuffer->eventMask, filter, (GrabPtr) 0))
  1242.     {
  1243.     if (attempt > 0)
  1244.         deliveries++;
  1245.     else
  1246.         nondeliveries--;
  1247.     }
  1248.     for (other = pMultibuffer->otherClients; other; other=other->next)
  1249.     {
  1250.     if (attempt = TryClientEvents(
  1251.           rClient(other), pEvents, count, other->mask, filter, (GrabPtr) 0))
  1252.     {
  1253.         if (attempt > 0)
  1254.         deliveries++;
  1255.         else
  1256.         nondeliveries--;
  1257.     }
  1258.     }
  1259.     if (deliveries)
  1260.     return deliveries;
  1261.     return nondeliveries;
  1262. }
  1263.  
  1264. /*
  1265.  * Send Expose events to interested clients
  1266.  */
  1267.  
  1268. static void
  1269. MultibufferExpose (pMultibuffer, pRegion)
  1270.     MultibufferPtr    pMultibuffer;
  1271.     RegionPtr    pRegion;
  1272. {
  1273.     if (pRegion && !REGION_NIL(pRegion))
  1274.     {
  1275.     xEvent *pEvent;
  1276.     PixmapPtr   pPixmap;
  1277.     register xEvent *pe;
  1278.     register BoxPtr pBox;
  1279.     register int i;
  1280.     int numRects;
  1281.  
  1282.     pPixmap = pMultibuffer->pPixmap;
  1283.     (* pPixmap->drawable.pScreen->TranslateRegion)(pRegion,
  1284.             -pPixmap->drawable.x, -pPixmap->drawable.y);
  1285.     /* XXX MultibufferExpose "knows" the region representation */
  1286.     numRects = REGION_NUM_RECTS(pRegion);
  1287.     pBox = REGION_RECTS(pRegion);
  1288.  
  1289.     pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent));
  1290.     if (pEvent) {
  1291.         pe = pEvent;
  1292.  
  1293.         for (i=1; i<=numRects; i++, pe++, pBox++)
  1294.         {
  1295.         pe->u.u.type = Expose;
  1296.         pe->u.expose.window = pPixmap->drawable.id;
  1297.         pe->u.expose.x = pBox->x1;
  1298.         pe->u.expose.y = pBox->y1;
  1299.         pe->u.expose.width = pBox->x2 - pBox->x1;
  1300.         pe->u.expose.height = pBox->y2 - pBox->y1;
  1301.         pe->u.expose.count = (numRects - i);
  1302.         }
  1303.         (void) DeliverEventsToMultibuffer (pMultibuffer, pEvent, numRects, ExposureMask);
  1304.         DEALLOCATE_LOCAL(pEvent);
  1305.     }
  1306.     }
  1307. }
  1308.  
  1309. static void
  1310. MultibufferUpdate (pMultibuffer, time)
  1311.     MultibufferPtr    pMultibuffer;
  1312.     CARD32    time;
  1313. {
  1314.     xMbufUpdateNotifyEvent    event;
  1315.  
  1316.     event.type = MultibufferEventBase + MultibufferUpdateNotify;
  1317.     event.buffer = pMultibuffer->pPixmap->drawable.id;
  1318.     event.timeStamp = time;
  1319.     (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event,
  1320.                        1, MultibufferUpdateNotifyMask);
  1321. }
  1322.  
  1323. /*
  1324.  * The sample implementation will never generate MultibufferClobberNotify
  1325.  * events
  1326.  */
  1327.  
  1328. static void
  1329. MultibufferClobber (pMultibuffer)
  1330.     MultibufferPtr    pMultibuffer;
  1331. {
  1332.     xMbufClobberNotifyEvent    event;
  1333.  
  1334.     event.type = MultibufferEventBase + MultibufferClobberNotify;
  1335.     event.buffer = pMultibuffer->pPixmap->drawable.id;
  1336.     event.state = pMultibuffer->clobber;
  1337.     (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event,
  1338.                        1, MultibufferClobberNotifyMask);
  1339. }
  1340.  
  1341. /*
  1342.  * make the resource id for buffer i refer to the window
  1343.  * drawable instead of the pixmap;
  1344.  */
  1345.  
  1346. static void
  1347. AliasMultibuffer (pMultibuffers, i)
  1348.     MultibuffersPtr    pMultibuffers;
  1349.     int        i;
  1350. {
  1351.     MultibufferPtr    pMultibuffer;
  1352.  
  1353.     if (i == pMultibuffers->displayedMultibuffer)
  1354.     return;
  1355.     /*
  1356.      * remove the old association
  1357.      */
  1358.     if (pMultibuffers->displayedMultibuffer >= 0)
  1359.     {
  1360.     pMultibuffer = &pMultibuffers->buffers[pMultibuffers->displayedMultibuffer];
  1361.     ChangeResourceValue (pMultibuffer->pPixmap->drawable.id,
  1362.                  MultibufferDrawableResType,
  1363.                   (pointer) pMultibuffer->pPixmap);
  1364.     }
  1365.     /*
  1366.      * make the new association
  1367.      */
  1368.     pMultibuffer = &pMultibuffers->buffers[i];
  1369.     ChangeResourceValue (pMultibuffer->pPixmap->drawable.id,
  1370.              MultibufferDrawableResType,
  1371.              (pointer) pMultibuffers->pWindow);
  1372.     pMultibuffers->displayedMultibuffer = i;
  1373. }
  1374.  
  1375. /*
  1376.  * free everything associated with multibuffering for this
  1377.  * window
  1378.  */
  1379.  
  1380. static void
  1381. DisposeMultibuffers (pWin)
  1382.     WindowPtr    pWin;
  1383. {
  1384.     FreeResourceByType (pWin->drawable.id, MultibuffersResType, FALSE);
  1385.     /* Zero out the window's pointer to the buffers so they won't be reused */
  1386.     pWin->devPrivates[MultibufferWindowIndex].ptr = NULL;
  1387. }
  1388.  
  1389. /*
  1390.  * resize the buffers when the window is resized
  1391.  */ 
  1392.  
  1393. static Bool
  1394. MultibufferPositionWindow (pWin, x, y)
  1395.     WindowPtr    pWin;
  1396.     int        x, y;
  1397. {
  1398.     ScreenPtr        pScreen;
  1399.     MultibufferScreenPtr pMultibufferScreen;
  1400.     MultibuffersPtr        pMultibuffers;
  1401.     MultibufferPtr        pMultibuffer;
  1402.     int            width, height;
  1403.     int            i;
  1404.     int            dx, dy, dw, dh;
  1405.     int            sourcex, sourcey;
  1406.     int            destx, desty;
  1407.     PixmapPtr        pPixmap;
  1408.     GCPtr        pGC;
  1409.     int            savewidth, saveheight;
  1410.     xRectangle        clearRect;
  1411.     Bool        clear;
  1412.  
  1413.     pScreen = pWin->drawable.pScreen;
  1414.     pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr;
  1415.     (*pMultibufferScreen->PositionWindow) (pWin, x, y);
  1416.     if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr))
  1417.     return TRUE;
  1418.     if (pMultibuffers->width == pWin->drawable.width &&
  1419.         pMultibuffers->height == pWin->drawable.height)
  1420.     return TRUE;
  1421.     width = pWin->drawable.width;
  1422.     height = pWin->drawable.height;
  1423.     dx = pWin->drawable.x - pMultibuffers->x;
  1424.     dy = pWin->drawable.x - pMultibuffers->y;
  1425.     dw = width - pMultibuffers->width;
  1426.     dh = height - pMultibuffers->height;
  1427.     GravityTranslate (0, 0, -dx, -dy, dw, dh,
  1428.               pWin->bitGravity, &destx, &desty);
  1429.     clear = pMultibuffers->width < width || pMultibuffers->height < height ||
  1430.         pWin->bitGravity == ForgetGravity;
  1431.  
  1432.     sourcex = 0;
  1433.     sourcey = 0;
  1434.     savewidth = pMultibuffers->width;
  1435.     saveheight = pMultibuffers->height;
  1436.     /* clip rectangle to source and destination */
  1437.     if (destx < 0)
  1438.     {
  1439.     savewidth += destx;
  1440.     sourcex -= destx;
  1441.     destx = 0;
  1442.     }
  1443.     if (destx + savewidth > width)
  1444.     savewidth = width - destx;
  1445.     if (desty < 0)
  1446.     {
  1447.     saveheight += desty;
  1448.     sourcey -= desty;
  1449.     desty = 0;
  1450.     }
  1451.     if (desty + saveheight > height)
  1452.     saveheight = height - desty;
  1453.  
  1454.     pMultibuffers->width = width;
  1455.     pMultibuffers->height = height;
  1456.     pMultibuffers->x = pWin->drawable.x;
  1457.     pMultibuffers->y = pWin->drawable.y;
  1458.  
  1459.     pGC = GetScratchGC (pWin->drawable.depth, pScreen);
  1460.     if (clear)
  1461.     {
  1462.     SetupBackgroundPainter (pWin, pGC);
  1463.     clearRect.x = 0;
  1464.     clearRect.y = 0;
  1465.     clearRect.width = width;
  1466.     clearRect.height = height;
  1467.     }
  1468.     for (i = 0; i < pMultibuffers->numMultibuffer; i++)
  1469.     {
  1470.     pMultibuffer = &pMultibuffers->buffers[i];
  1471.     pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, pWin->drawable.depth);
  1472.     if (!pPixmap)
  1473.     {
  1474.         DisposeMultibuffers (pWin);
  1475.         break;
  1476.     }
  1477.     ValidateGC (pPixmap, pGC);
  1478.     /*
  1479.      * I suppose this could avoid quite a bit of work if
  1480.      * it computed the minimal area required.
  1481.      */
  1482.     if (clear)
  1483.         (*pGC->ops->PolyFillRect) (pPixmap, pGC, 1, &clearRect);
  1484.     if (pWin->bitGravity != ForgetGravity)
  1485.     {
  1486.         (*pGC->ops->CopyArea) (pMultibuffer->pPixmap, pPixmap, pGC,
  1487.                     sourcex, sourcey, savewidth, saveheight,
  1488.                     destx, desty);
  1489.     }
  1490.     pPixmap->drawable.id = pMultibuffer->pPixmap->drawable.id;
  1491.     (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
  1492.     pMultibuffer->pPixmap = pPixmap;
  1493.     if (i != pMultibuffers->displayedMultibuffer)
  1494.     {
  1495.         ChangeResourceValue (pPixmap->drawable.id,
  1496.                  MultibufferDrawableResType,
  1497.                  (pointer) pPixmap);
  1498.     }
  1499.     }
  1500.     FreeScratchGC (pGC);
  1501.     return TRUE;
  1502. }
  1503.  
  1504. /* Resource delete func for MultibufferDrawableResType */
  1505. static void
  1506. MultibufferDrawableDelete (pDrawable, id)
  1507.     DrawablePtr    pDrawable;
  1508.     XID        id;
  1509. {
  1510.     WindowPtr    pWin;
  1511.     MultibuffersPtr    pMultibuffers;
  1512.     PixmapPtr    pPixmap;
  1513.  
  1514.     if (pDrawable->type == DRAWABLE_WINDOW)
  1515.     {
  1516.     pWin = (WindowPtr) pDrawable;
  1517.     pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr;
  1518.     pPixmap = pMultibuffers->buffers[pMultibuffers->displayedMultibuffer].pPixmap;
  1519.     }
  1520.     else
  1521.     {
  1522.     pPixmap = (PixmapPtr) pDrawable;
  1523.     }
  1524.     (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
  1525. }
  1526.  
  1527. /* Resource delete func for MultibufferResType */
  1528. static void
  1529. MultibufferDelete (pMultibuffer, id)
  1530.     MultibufferPtr    pMultibuffer;
  1531.     XID        id;
  1532. {
  1533.     return;
  1534. }
  1535.  
  1536. /* Resource delete func for MultibuffersResType */
  1537. static void
  1538. MultibuffersDelete (pMultibuffers, id)
  1539.     MultibuffersPtr    pMultibuffers;
  1540.     XID        id;
  1541. {
  1542.     int    i;
  1543.  
  1544.     for (i = 0; i < pMultibuffers->numMultibuffer; i++)
  1545.     FreeResource (pMultibuffers->buffers[i].pPixmap->drawable.id, 0);
  1546.     xfree (pMultibuffers->buffers);
  1547.     xfree (pMultibuffers);
  1548. }
  1549.  
  1550. /* Resource delete func for DisplayRequestResType */
  1551. static void
  1552. DisplayRequestDelete (pRequest, id)
  1553.     DisplayRequestPtr    pRequest;
  1554.     XID            id;
  1555. {
  1556.     DisposeDisplayRequest (pRequest);
  1557. }
  1558.  
  1559. /* Resource delete func for OtherClientResType */
  1560. static void
  1561. OtherClientDelete (pMultibuffer, id)
  1562.     MultibufferPtr    pMultibuffer;
  1563.     XID        id;
  1564. {
  1565.     register OtherClientsPtr    other, prev;
  1566.  
  1567.     prev = 0;
  1568.     for (other = pMultibuffer->otherClients; other; other = other->next)
  1569.     {
  1570.     if (other->resource == id)
  1571.     {
  1572.         if (prev)
  1573.         prev->next = other->next;
  1574.         else
  1575.         pMultibuffer->otherClients = other->next;
  1576.         xfree (other);
  1577.         RecalculateMultibufferOtherEvents (pMultibuffer);
  1578.         break;
  1579.     }
  1580.     prev = other;
  1581.     }
  1582. }
  1583.  
  1584. static int
  1585. EventSelectForMultibuffer (pMultibuffer, client, mask)
  1586.     MultibufferPtr    pMultibuffer;
  1587.     ClientPtr    client;
  1588.     Mask    mask;
  1589. {
  1590.     OtherClientsPtr    other;
  1591.  
  1592.     if (mask & ~ValidEventMasks)
  1593.     {
  1594.     client->errorValue = mask;
  1595.     return BadValue;
  1596.     }
  1597.     if (bClient (pMultibuffer) == client)
  1598.     {
  1599.     pMultibuffer->eventMask = mask;
  1600.     }
  1601.     else
  1602.     {
  1603.     for (other = pMultibuffer->otherClients; other; other = other->next)
  1604.     {
  1605.         if (SameClient (other, client))
  1606.         {
  1607.         if (mask == 0)
  1608.         {
  1609.             FreeResource (other->resource, RT_NONE);
  1610.             break;
  1611.         }
  1612.         other->mask = mask;
  1613.         break;
  1614.         }
  1615.     }
  1616.     if (!other)
  1617.     {
  1618.         other = (OtherClients *) xalloc (sizeof (OtherClients));
  1619.         if (!other)
  1620.         return BadAlloc;
  1621.         other->mask = mask;
  1622.         other->resource = FakeClientID (client->index);
  1623.         if (!AddResource (other->resource, OtherClientResType, (pointer) pMultibuffer))
  1624.         {
  1625.         xfree (other);
  1626.         return BadAlloc;
  1627.         }
  1628.         other->next = pMultibuffer->otherClients;
  1629.         pMultibuffer->otherClients = other;
  1630.     }
  1631.     RecalculateMultibufferOtherEvents (pMultibuffer);
  1632.     }
  1633.     return (client->noClientException);
  1634. }
  1635.  
  1636. static void
  1637. RecalculateMultibufferOtherEvents (pMultibuffer)
  1638.     MultibufferPtr    pMultibuffer;
  1639. {
  1640.     Mask        otherEventMask;
  1641.     OtherClients    *other;
  1642.  
  1643.     otherEventMask = 0L;
  1644.     for (other = pMultibuffer->otherClients; other; other = other->next)
  1645.     otherEventMask |= other->mask;
  1646.     pMultibuffer->otherEventMask = otherEventMask;
  1647. }
  1648.  
  1649. /* add milliseconds to a timestamp */
  1650. static void
  1651. BumpTimeStamp (ts, inc)
  1652. TimeStamp   *ts;
  1653. CARD32        inc;
  1654. {
  1655.     CARD32  newms;
  1656.  
  1657.     newms = ts->milliseconds + inc;
  1658.     if (newms < ts->milliseconds)
  1659.     ts->months++;
  1660.     ts->milliseconds = newms;
  1661. }
  1662.