xref: /OK3568_Linux_fs/external/xserver/hw/dmx/glxProxy/glxswap.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2003 Red Hat Inc., Raleigh, North Carolina.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * All Rights Reserved.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining
7*4882a593Smuzhiyun  * a copy of this software and associated documentation files (the
8*4882a593Smuzhiyun  * "Software"), to deal in the Software without restriction, including
9*4882a593Smuzhiyun  * without limitation on the rights to use, copy, modify, merge,
10*4882a593Smuzhiyun  * publish, distribute, sublicense, and/or sell copies of the Software,
11*4882a593Smuzhiyun  * and to permit persons to whom the Software is furnished to do so,
12*4882a593Smuzhiyun  * subject to the following conditions:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the
15*4882a593Smuzhiyun  * next paragraph) shall be included in all copies or substantial
16*4882a593Smuzhiyun  * portions of the Software.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*4882a593Smuzhiyun  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22*4882a593Smuzhiyun  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23*4882a593Smuzhiyun  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25*4882a593Smuzhiyun  * SOFTWARE.
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun  * Authors:
30*4882a593Smuzhiyun  *   Kevin E. Martin <kem@redhat.com>
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #ifdef HAVE_DMX_CONFIG_H
35*4882a593Smuzhiyun #include <dmx-config.h>
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #include "dmx.h"
39*4882a593Smuzhiyun #include "dmxwindow.h"
40*4882a593Smuzhiyun #include "glxserver.h"
41*4882a593Smuzhiyun #include "glxswap.h"
42*4882a593Smuzhiyun #include "glxcmds.h"
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun typedef struct _SwapGroup *SwapGroupPtr;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun static Bool SwapBarrierIsReadyToSwap(GLuint barrier);
47*4882a593Smuzhiyun static void SwapSwapBarrier(GLuint barrier);
48*4882a593Smuzhiyun static void UpdateSwapBarrierList(GLuint barrier,
49*4882a593Smuzhiyun                                   SwapGroupPtr pOldSwap, SwapGroupPtr pNewSwap);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /************************************************************************
52*4882a593Smuzhiyun  *
53*4882a593Smuzhiyun  * Swap Groups
54*4882a593Smuzhiyun  *
55*4882a593Smuzhiyun  ************************************************************************/
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun typedef struct _SwapGroup {
58*4882a593Smuzhiyun     WindowPtr pWin;
59*4882a593Smuzhiyun     SwapGroupPtr pNext;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun     Bool swapping;
62*4882a593Smuzhiyun     Bool sleeping;
63*4882a593Smuzhiyun     GLuint barrier;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun     XID drawable;
66*4882a593Smuzhiyun     GLXContextTag tag;
67*4882a593Smuzhiyun     __GLXclientState *clState;
68*4882a593Smuzhiyun } SwapGroupRec;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static void
SwapSwapGroup(SwapGroupPtr pSwap)71*4882a593Smuzhiyun SwapSwapGroup(SwapGroupPtr pSwap)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun     SwapGroupPtr pCur;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun     /* All drawables in swap group are ready to swap, so just swap all
76*4882a593Smuzhiyun      * drawables buffers and then wake up those clients that were
77*4882a593Smuzhiyun      * previously sleeping */
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun     for (pCur = pSwap; pCur; pCur = pCur->pNext) {
80*4882a593Smuzhiyun         if (pCur->swapping) {
81*4882a593Smuzhiyun             /* Swap pCur's buffers */
82*4882a593Smuzhiyun             __glXDoSwapBuffers(pCur->clState, pCur->drawable, pCur->tag);
83*4882a593Smuzhiyun             pCur->swapping = FALSE;
84*4882a593Smuzhiyun         }
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun         /* Wakeup client */
87*4882a593Smuzhiyun         if (pCur->sleeping) {
88*4882a593Smuzhiyun             ClientWakeup(pCur->clState->client);
89*4882a593Smuzhiyun             pCur->sleeping = FALSE;
90*4882a593Smuzhiyun         }
91*4882a593Smuzhiyun     }
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun static Bool
SwapGroupIsReadyToSwap(SwapGroupPtr pSwap)95*4882a593Smuzhiyun SwapGroupIsReadyToSwap(SwapGroupPtr pSwap)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun     Bool isReady = TRUE;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun     /* The swap group is ready to swap when all drawables are ready to
100*4882a593Smuzhiyun      * swap.  NOTE: A drawable is also ready to swap if it is not
101*4882a593Smuzhiyun      * currently mapped */
102*4882a593Smuzhiyun     for (; pSwap; pSwap = pSwap->pNext) {
103*4882a593Smuzhiyun         isReady &= (pSwap->swapping || !pSwap->pWin->mapped);
104*4882a593Smuzhiyun         /* FIXME: Should we use pSwap->pWin->mapped or ...->realized ??? */
105*4882a593Smuzhiyun     }
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun     return isReady;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun static Bool
SGSwapCleanup(ClientPtr client,void * closure)111*4882a593Smuzhiyun SGSwapCleanup(ClientPtr client, void *closure)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun     /* SwapGroupPtr  pSwap = (SwapGroupPtr)closure; */
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun     /* This should not be called unless the client has died in which
116*4882a593Smuzhiyun      * case we should remove the buffer from the swap list */
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun     return TRUE;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun int
SGSwapBuffers(__GLXclientState * cl,XID drawId,GLXContextTag tag,DrawablePtr pDraw)122*4882a593Smuzhiyun SGSwapBuffers(__GLXclientState * cl, XID drawId, GLXContextTag tag,
123*4882a593Smuzhiyun               DrawablePtr pDraw)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun     WindowPtr pWin = (WindowPtr) pDraw;
126*4882a593Smuzhiyun     dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
127*4882a593Smuzhiyun     SwapGroupPtr pSwap = pWinPriv->swapGroup;
128*4882a593Smuzhiyun     SwapGroupPtr pCur;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun     for (pCur = pSwap; pCur && pCur->pWin != pWin; pCur = pCur->pNext);
131*4882a593Smuzhiyun     if (!pCur)
132*4882a593Smuzhiyun         return BadDrawable;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun     pCur->clState = cl;
135*4882a593Smuzhiyun     pCur->drawable = drawId;
136*4882a593Smuzhiyun     pCur->tag = tag;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun     /* We are now in the process of swapping */
139*4882a593Smuzhiyun     pCur->swapping = TRUE;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun     if (pSwap->barrier && SwapBarrierIsReadyToSwap(pSwap->barrier)) {
142*4882a593Smuzhiyun         /* The swap group is bound to a barrier and the barrier is ready
143*4882a593Smuzhiyun          * to swap, so swap all the swap groups that are bound to this
144*4882a593Smuzhiyun          * group's swap barrier */
145*4882a593Smuzhiyun         SwapSwapBarrier(pSwap->barrier);
146*4882a593Smuzhiyun     }
147*4882a593Smuzhiyun     else if (!pSwap->barrier && SwapGroupIsReadyToSwap(pSwap)) {
148*4882a593Smuzhiyun         /* Do the swap if the entire swap group is ready to swap and the
149*4882a593Smuzhiyun          * group is not bound to a swap barrier */
150*4882a593Smuzhiyun         SwapSwapGroup(pSwap);
151*4882a593Smuzhiyun     }
152*4882a593Smuzhiyun     else {
153*4882a593Smuzhiyun         /* The swap group/barrier is not yet ready to swap, so put
154*4882a593Smuzhiyun          * client to sleep until the rest are ready to swap */
155*4882a593Smuzhiyun         ClientSleep(cl->client, SGSwapCleanup, (void *) pWin);
156*4882a593Smuzhiyun         pCur->sleeping = TRUE;
157*4882a593Smuzhiyun     }
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun     return Success;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun static void
SGWindowUnmapped(WindowPtr pWin)163*4882a593Smuzhiyun SGWindowUnmapped(WindowPtr pWin)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun     dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
166*4882a593Smuzhiyun     SwapGroupPtr pSwap = pWinPriv->swapGroup;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun     /* Now that one of the windows in the swap group has been unmapped,
169*4882a593Smuzhiyun      * see if the entire swap group/barrier is ready to swap */
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun     if (pSwap->barrier && SwapBarrierIsReadyToSwap(pSwap->barrier)) {
172*4882a593Smuzhiyun         SwapSwapBarrier(pSwap->barrier);
173*4882a593Smuzhiyun     }
174*4882a593Smuzhiyun     else if (!pSwap->barrier && SwapGroupIsReadyToSwap(pSwap)) {
175*4882a593Smuzhiyun         SwapSwapGroup(pSwap);
176*4882a593Smuzhiyun     }
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun static void
SGWindowDestroyed(WindowPtr pWin)180*4882a593Smuzhiyun SGWindowDestroyed(WindowPtr pWin)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun     JoinSwapGroupSGIX((DrawablePtr) pWin, NULL);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun static SwapGroupPtr
CreateSwapEntry(WindowPtr pWin)186*4882a593Smuzhiyun CreateSwapEntry(WindowPtr pWin)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun     SwapGroupPtr pEntry;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun     /* Allocate new swap group */
191*4882a593Smuzhiyun     pEntry = malloc(sizeof(*pEntry));
192*4882a593Smuzhiyun     if (!pEntry)
193*4882a593Smuzhiyun         return NULL;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun     /* Initialize swap group */
196*4882a593Smuzhiyun     pEntry->pWin = pWin;
197*4882a593Smuzhiyun     pEntry->pNext = NULL;
198*4882a593Smuzhiyun     pEntry->swapping = FALSE;
199*4882a593Smuzhiyun     pEntry->sleeping = FALSE;
200*4882a593Smuzhiyun     pEntry->barrier = 0;
201*4882a593Smuzhiyun     /* The following are not initialized until SwapBuffers is called:
202*4882a593Smuzhiyun      *     pEntry->drawable
203*4882a593Smuzhiyun      *     pEntry->tag
204*4882a593Smuzhiyun      *     pEntry->clState
205*4882a593Smuzhiyun      */
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun     return pEntry;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun static void
FreeSwapEntry(SwapGroupPtr pEntry)211*4882a593Smuzhiyun FreeSwapEntry(SwapGroupPtr pEntry)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun     /* Since we have removed the drawable from its previous swap group
214*4882a593Smuzhiyun      * and it won't be added to another swap group, the only thing that
215*4882a593Smuzhiyun      * we need to do is to make sure that the drawable's client is not
216*4882a593Smuzhiyun      * sleeping.  This could happen if one thread is sleeping, while
217*4882a593Smuzhiyun      * another thread called glxJoinSwapGroup().  Note that all sleeping
218*4882a593Smuzhiyun      * threads should also be swapping, but there is a small window in
219*4882a593Smuzhiyun      * the SGSwapBuffer() logic, above, where swapping can be set but
220*4882a593Smuzhiyun      * sleeping is not.  We check both independently here just to be
221*4882a593Smuzhiyun      * pedantic. */
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun     /* Handle swap buffer request */
224*4882a593Smuzhiyun     if (pEntry->swapping)
225*4882a593Smuzhiyun         __glXDoSwapBuffers(pEntry->clState, pEntry->drawable, pEntry->tag);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun     /* Wake up client */
228*4882a593Smuzhiyun     if (pEntry->sleeping)
229*4882a593Smuzhiyun         ClientWakeup(pEntry->clState->client);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun     /* We can free the pEntry entry since it has already been removed
232*4882a593Smuzhiyun      * from the swap group list and it won't be needed any longer */
233*4882a593Smuzhiyun     free(pEntry);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun int
JoinSwapGroupSGIX(DrawablePtr pDraw,DrawablePtr pMember)237*4882a593Smuzhiyun JoinSwapGroupSGIX(DrawablePtr pDraw, DrawablePtr pMember)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun     if (pDraw->type == DRAWABLE_WINDOW) {
240*4882a593Smuzhiyun         WindowPtr pWin = (WindowPtr) pDraw;
241*4882a593Smuzhiyun         dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
242*4882a593Smuzhiyun         SwapGroupPtr pOldSwap = NULL;
243*4882a593Smuzhiyun         SwapGroupPtr pEntry;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun         /* If pDraw and pMember are already members of the same swap
246*4882a593Smuzhiyun          * group, just return Success since there is nothing to do */
247*4882a593Smuzhiyun         for (pEntry = pWinPriv->swapGroup; pEntry; pEntry = pEntry->pNext)
248*4882a593Smuzhiyun             if (pEntry->pWin == (WindowPtr) pMember)
249*4882a593Smuzhiyun                 return Success;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun         /* Remove pDraw from its current swap group */
252*4882a593Smuzhiyun         if (pWinPriv->swapGroup) {
253*4882a593Smuzhiyun             SwapGroupPtr pSwapGroup = pWinPriv->swapGroup;
254*4882a593Smuzhiyun             SwapGroupPtr pPrev;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun             /* Find old swap entry in swap group and save in pOldSwap
257*4882a593Smuzhiyun              * for later use */
258*4882a593Smuzhiyun             for (pOldSwap = pWinPriv->swapGroup, pPrev = NULL;
259*4882a593Smuzhiyun                  pOldSwap && pOldSwap->pWin != pWin;
260*4882a593Smuzhiyun                  pPrev = pOldSwap, pOldSwap = pOldSwap->pNext);
261*4882a593Smuzhiyun             if (!pOldSwap)
262*4882a593Smuzhiyun                 return BadDrawable;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun             /* Remove pDraw's swap group entry from swap group list */
265*4882a593Smuzhiyun             if (pPrev) {
266*4882a593Smuzhiyun                 pPrev->pNext = pOldSwap->pNext;
267*4882a593Smuzhiyun             }
268*4882a593Smuzhiyun             else {
269*4882a593Smuzhiyun                 /* pWin is at the head of the swap group list, so we
270*4882a593Smuzhiyun                  * need to update all other members of this swap
271*4882a593Smuzhiyun                  * group */
272*4882a593Smuzhiyun                 for (pEntry = pOldSwap->pNext; pEntry; pEntry = pEntry->pNext)
273*4882a593Smuzhiyun                     DMX_GET_WINDOW_PRIV(pEntry->pWin)->swapGroup
274*4882a593Smuzhiyun                         = pOldSwap->pNext;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun                 /* Update the barrier list as well */
277*4882a593Smuzhiyun                 if (pOldSwap->barrier)
278*4882a593Smuzhiyun                     UpdateSwapBarrierList(pOldSwap->barrier,
279*4882a593Smuzhiyun                                           pOldSwap, pOldSwap->pNext);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun                 /* Set pSwapGroup to point to the swap group without
282*4882a593Smuzhiyun                  * pOldSwap */
283*4882a593Smuzhiyun                 pSwapGroup = pOldSwap->pNext;
284*4882a593Smuzhiyun             }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun             /* Check to see if current swap group can now swap since we
287*4882a593Smuzhiyun              * know at this point that pDraw and pMember are guaranteed
288*4882a593Smuzhiyun              * to previously be in different swap groups */
289*4882a593Smuzhiyun             if (pSwapGroup && SwapGroupIsReadyToSwap(pSwapGroup)) {
290*4882a593Smuzhiyun                 SwapSwapGroup(pSwapGroup);
291*4882a593Smuzhiyun             }
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun             /* Make the old swap entry a standalone group */
294*4882a593Smuzhiyun             pOldSwap->pNext = NULL;
295*4882a593Smuzhiyun             pOldSwap->barrier = 0;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun             /* Reset pWin's swap group */
298*4882a593Smuzhiyun             pWinPriv->swapGroup = NULL;
299*4882a593Smuzhiyun             pWinPriv->windowDestroyed = NULL;
300*4882a593Smuzhiyun             pWinPriv->windowUnmapped = NULL;
301*4882a593Smuzhiyun         }
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun         if (!pMember || pMember->type != DRAWABLE_WINDOW) {
304*4882a593Smuzhiyun             /* Free old swap group since it is no longer needed */
305*4882a593Smuzhiyun             if (pOldSwap)
306*4882a593Smuzhiyun                 FreeSwapEntry(pOldSwap);
307*4882a593Smuzhiyun         }
308*4882a593Smuzhiyun         else if (pDraw == pMember && pOldSwap) {
309*4882a593Smuzhiyun             /* Special case where pDraw was previously created and we
310*4882a593Smuzhiyun              * are now just putting it to its own swap group */
311*4882a593Smuzhiyun             pWinPriv->swapGroup = pOldSwap;
312*4882a593Smuzhiyun             pWinPriv->windowDestroyed = SGWindowDestroyed;
313*4882a593Smuzhiyun             pWinPriv->windowUnmapped = SGWindowUnmapped;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun             /* Check to see if pDraw is ready to swap */
316*4882a593Smuzhiyun             if (SwapGroupIsReadyToSwap(pOldSwap))
317*4882a593Smuzhiyun                 SwapSwapGroup(pOldSwap);
318*4882a593Smuzhiyun         }
319*4882a593Smuzhiyun         else if (pMember->type == DRAWABLE_WINDOW) {
320*4882a593Smuzhiyun             WindowPtr pMemberWin = (WindowPtr) pMember;
321*4882a593Smuzhiyun             dmxWinPrivPtr pMemberPriv = DMX_GET_WINDOW_PRIV(pMemberWin);
322*4882a593Smuzhiyun             SwapGroupPtr pMemberSwapGroup = pMemberPriv->swapGroup;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun             /* Finally, how we can add pDraw to pMember's swap group */
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun             /* If pMember is not currently in a swap group, then create
327*4882a593Smuzhiyun              * one for it since we are just about to add pDraw to it. */
328*4882a593Smuzhiyun             if (!pMemberSwapGroup) {
329*4882a593Smuzhiyun                 /* Create new swap group */
330*4882a593Smuzhiyun                 pMemberSwapGroup = CreateSwapEntry(pMemberWin);
331*4882a593Smuzhiyun                 if (!pMemberSwapGroup) {
332*4882a593Smuzhiyun                     if (pOldSwap)
333*4882a593Smuzhiyun                         FreeSwapEntry(pOldSwap);
334*4882a593Smuzhiyun                     return BadAlloc;
335*4882a593Smuzhiyun                 }
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun                 /* Set pMember's swap group */
338*4882a593Smuzhiyun                 pMemberPriv->swapGroup = pMemberSwapGroup;
339*4882a593Smuzhiyun                 pMemberPriv->windowDestroyed = SGWindowDestroyed;
340*4882a593Smuzhiyun                 pMemberPriv->windowUnmapped = SGWindowUnmapped;
341*4882a593Smuzhiyun             }
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun             /* If pDraw == pMember, that means pDraw was not a member of
344*4882a593Smuzhiyun              * a group previously (or it would have been handled by the
345*4882a593Smuzhiyun              * special case above), so no additional work is required
346*4882a593Smuzhiyun              * since we just created a new swap group for pMember (i.e.,
347*4882a593Smuzhiyun              * pDraw). */
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun             if (pDraw != pMember) {
350*4882a593Smuzhiyun                 /* If pDraw was not previously in a swap group, then create
351*4882a593Smuzhiyun                  * an entry for it */
352*4882a593Smuzhiyun                 if (!pOldSwap) {
353*4882a593Smuzhiyun                     /* Create new swap group */
354*4882a593Smuzhiyun                     pOldSwap = CreateSwapEntry(pWin);
355*4882a593Smuzhiyun                     if (!pOldSwap) {
356*4882a593Smuzhiyun                         /* If we just created a swap group for pMember, we
357*4882a593Smuzhiyun                          * need to free it here */
358*4882a593Smuzhiyun                         if (pMemberSwapGroup->pNext == NULL) {
359*4882a593Smuzhiyun                             FreeSwapEntry(pMemberSwapGroup);
360*4882a593Smuzhiyun                             pMemberPriv->swapGroup = NULL;
361*4882a593Smuzhiyun                         }
362*4882a593Smuzhiyun                         return BadAlloc;
363*4882a593Smuzhiyun                     }
364*4882a593Smuzhiyun                 }
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun                 /* Find last entry in pMember's swap group */
367*4882a593Smuzhiyun                 for (pEntry = pMemberSwapGroup;
368*4882a593Smuzhiyun                      pEntry->pNext; pEntry = pEntry->pNext);
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun                 /* Add pDraw's swap group entry to pMember's swap group list */
371*4882a593Smuzhiyun                 pEntry->pNext = pOldSwap;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun                 /* Add pDraw to pMember's swap barrier */
374*4882a593Smuzhiyun                 pOldSwap->barrier = pEntry->barrier;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun                 /* Set pDraw's swap group */
377*4882a593Smuzhiyun                 pWinPriv->swapGroup = pMemberSwapGroup;
378*4882a593Smuzhiyun                 pWinPriv->windowDestroyed = SGWindowDestroyed;
379*4882a593Smuzhiyun                 pWinPriv->windowUnmapped = SGWindowUnmapped;
380*4882a593Smuzhiyun             }
381*4882a593Smuzhiyun         }
382*4882a593Smuzhiyun     }
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun     return Success;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun /************************************************************************
388*4882a593Smuzhiyun  *
389*4882a593Smuzhiyun  * Swap Barriers
390*4882a593Smuzhiyun  *
391*4882a593Smuzhiyun  ************************************************************************/
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun #define GLX_MAX_SWAP_BARRIERS 10
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun typedef struct _SwapBarrier *SwapBarrierPtr;
396*4882a593Smuzhiyun typedef struct _SwapBarrier {
397*4882a593Smuzhiyun     SwapGroupPtr pSwap;
398*4882a593Smuzhiyun     SwapBarrierPtr pNext;
399*4882a593Smuzhiyun } SwapBarrierRec;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun static SwapBarrierPtr SwapBarrierList[GLX_MAX_SWAP_BARRIERS + 1];
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun void
SwapBarrierInit(void)404*4882a593Smuzhiyun SwapBarrierInit(void)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun     int i;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun     for (i = 0; i <= GLX_MAX_SWAP_BARRIERS; i++)
409*4882a593Smuzhiyun         SwapBarrierList[i] = NULL;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun void
SwapBarrierReset(void)413*4882a593Smuzhiyun SwapBarrierReset(void)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun     int i;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun     for (i = 0; i <= GLX_MAX_SWAP_BARRIERS; i++) {
418*4882a593Smuzhiyun         SwapBarrierPtr pBarrier, pNextBarrier;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun         for (pBarrier = SwapBarrierList[i]; pBarrier; pBarrier = pNextBarrier) {
421*4882a593Smuzhiyun             pNextBarrier = pBarrier->pNext;
422*4882a593Smuzhiyun             free(pBarrier);
423*4882a593Smuzhiyun         }
424*4882a593Smuzhiyun         SwapBarrierList[i] = NULL;
425*4882a593Smuzhiyun     }
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun int
QueryMaxSwapBarriersSGIX(int screen)429*4882a593Smuzhiyun QueryMaxSwapBarriersSGIX(int screen)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun     return GLX_MAX_SWAP_BARRIERS;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun static Bool
BindSwapGroupToBarrier(GLuint barrier,SwapGroupPtr pSwapGroup)435*4882a593Smuzhiyun BindSwapGroupToBarrier(GLuint barrier, SwapGroupPtr pSwapGroup)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun     SwapBarrierPtr pBarrier;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun     pBarrier = malloc(sizeof(*pBarrier));
440*4882a593Smuzhiyun     if (!pBarrier)
441*4882a593Smuzhiyun         return FALSE;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun     /* Add the swap group to barrier's list */
444*4882a593Smuzhiyun     pBarrier->pSwap = pSwapGroup;
445*4882a593Smuzhiyun     pBarrier->pNext = SwapBarrierList[barrier];
446*4882a593Smuzhiyun     SwapBarrierList[barrier] = pBarrier;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun     return TRUE;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun static Bool
UnbindSwapGroupFromBarrier(GLuint barrier,SwapGroupPtr pSwapGroup)452*4882a593Smuzhiyun UnbindSwapGroupFromBarrier(GLuint barrier, SwapGroupPtr pSwapGroup)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun     SwapBarrierPtr pBarrier, pPrevBarrier;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun     /* Find the swap group in barrier's list */
457*4882a593Smuzhiyun     for (pBarrier = SwapBarrierList[barrier], pPrevBarrier = NULL;
458*4882a593Smuzhiyun          pBarrier && pBarrier->pSwap != pSwapGroup;
459*4882a593Smuzhiyun          pPrevBarrier = pBarrier, pBarrier = pBarrier->pNext);
460*4882a593Smuzhiyun     if (!pBarrier)
461*4882a593Smuzhiyun         return FALSE;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun     /* Remove the swap group from barrier's list */
464*4882a593Smuzhiyun     if (pPrevBarrier)
465*4882a593Smuzhiyun         pPrevBarrier->pNext = pBarrier->pNext;
466*4882a593Smuzhiyun     else
467*4882a593Smuzhiyun         SwapBarrierList[barrier] = pBarrier->pNext;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun     /* Free memory */
470*4882a593Smuzhiyun     free(pBarrier);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun     return TRUE;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun static void
UpdateSwapBarrierList(GLuint barrier,SwapGroupPtr pOldSwap,SwapGroupPtr pNewSwap)476*4882a593Smuzhiyun UpdateSwapBarrierList(GLuint barrier,
477*4882a593Smuzhiyun                       SwapGroupPtr pOldSwap, SwapGroupPtr pNewSwap)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun     SwapBarrierPtr pBarrier;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun     /* If the old swap group is being destroyed, then we need to remove
482*4882a593Smuzhiyun      * the swap group from the list entirely */
483*4882a593Smuzhiyun     if (!pNewSwap) {
484*4882a593Smuzhiyun         UnbindSwapGroupFromBarrier(barrier, pOldSwap);
485*4882a593Smuzhiyun         return;
486*4882a593Smuzhiyun     }
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun     /* Otherwise, find the old swap group in the barrier list and change
489*4882a593Smuzhiyun      * it to the new swap group */
490*4882a593Smuzhiyun     for (pBarrier = SwapBarrierList[barrier];
491*4882a593Smuzhiyun          pBarrier; pBarrier = pBarrier->pNext) {
492*4882a593Smuzhiyun         if (pBarrier->pSwap == pOldSwap) {
493*4882a593Smuzhiyun             pBarrier->pSwap = pNewSwap;
494*4882a593Smuzhiyun             return;
495*4882a593Smuzhiyun         }
496*4882a593Smuzhiyun     }
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun static Bool
SwapBarrierIsReadyToSwap(GLuint barrier)500*4882a593Smuzhiyun SwapBarrierIsReadyToSwap(GLuint barrier)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun     SwapBarrierPtr pBarrier;
503*4882a593Smuzhiyun     Bool isReady = TRUE;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun     /* The swap barier is ready to swap when swap groups that are bound
506*4882a593Smuzhiyun      * to barrier are ready to swap */
507*4882a593Smuzhiyun     for (pBarrier = SwapBarrierList[barrier];
508*4882a593Smuzhiyun          pBarrier; pBarrier = pBarrier->pNext)
509*4882a593Smuzhiyun         isReady &= SwapGroupIsReadyToSwap(pBarrier->pSwap);
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun     return isReady;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun static void
SwapSwapBarrier(GLuint barrier)515*4882a593Smuzhiyun SwapSwapBarrier(GLuint barrier)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun     SwapBarrierPtr pBarrier;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun     /* Swap each group that is a member of this barrier */
520*4882a593Smuzhiyun     for (pBarrier = SwapBarrierList[barrier];
521*4882a593Smuzhiyun          pBarrier; pBarrier = pBarrier->pNext)
522*4882a593Smuzhiyun         SwapSwapGroup(pBarrier->pSwap);
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun int
BindSwapBarrierSGIX(DrawablePtr pDraw,int barrier)526*4882a593Smuzhiyun BindSwapBarrierSGIX(DrawablePtr pDraw, int barrier)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun     /* FIXME: Check for errors when pDraw->type != DRAWABLE_WINDOW */
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun     if (barrier < 0 || barrier > GLX_MAX_SWAP_BARRIERS)
531*4882a593Smuzhiyun         return BadValue;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun     if (pDraw->type == DRAWABLE_WINDOW) {
534*4882a593Smuzhiyun         WindowPtr pWin = (WindowPtr) pDraw;
535*4882a593Smuzhiyun         dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
536*4882a593Smuzhiyun         SwapGroupPtr pSwapGroup = pWinPriv->swapGroup;
537*4882a593Smuzhiyun         SwapGroupPtr pCur;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun         if (!pSwapGroup)
540*4882a593Smuzhiyun             return BadDrawable;
541*4882a593Smuzhiyun         if (barrier && pSwapGroup->barrier)
542*4882a593Smuzhiyun             return BadValue;
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun         /* Update the swap barrier list */
545*4882a593Smuzhiyun         if (barrier) {
546*4882a593Smuzhiyun             if (!BindSwapGroupToBarrier(barrier, pSwapGroup))
547*4882a593Smuzhiyun                 return BadAlloc;
548*4882a593Smuzhiyun         }
549*4882a593Smuzhiyun         else {
550*4882a593Smuzhiyun             if (!UnbindSwapGroupFromBarrier(pSwapGroup->barrier, pSwapGroup))
551*4882a593Smuzhiyun                 return BadDrawable;
552*4882a593Smuzhiyun         }
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun         /* Set the barrier for each member of this swap group */
555*4882a593Smuzhiyun         for (pCur = pSwapGroup; pCur; pCur = pCur->pNext)
556*4882a593Smuzhiyun             pCur->barrier = barrier;
557*4882a593Smuzhiyun     }
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun     return Success;
560*4882a593Smuzhiyun }
561