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