539 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			539 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright 2003 Red Hat Inc., Raleigh, North Carolina.
 | 
						|
 *
 | 
						|
 * All Rights Reserved.
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining
 | 
						|
 * a copy of this software and associated documentation files (the
 | 
						|
 * "Software"), to deal in the Software without restriction, including
 | 
						|
 * without limitation on the rights to use, copy, modify, merge,
 | 
						|
 * publish, distribute, sublicense, and/or sell copies of the Software,
 | 
						|
 * and to permit persons to whom the Software is furnished to do so,
 | 
						|
 * subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice (including the
 | 
						|
 * next paragraph) shall be included in all copies or substantial
 | 
						|
 * portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
						|
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
						|
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
						|
 * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
 | 
						|
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
						|
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * Authors:
 | 
						|
 *   Kevin E. Martin <kem@redhat.com>
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DMX_CONFIG_H
 | 
						|
#include <dmx-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "dmx.h"
 | 
						|
#include "dmxwindow.h"
 | 
						|
#include "glxserver.h"
 | 
						|
#include "glxswap.h"
 | 
						|
 | 
						|
extern int __glXDoSwapBuffers(__GLXclientState *cl, XID drawId,
 | 
						|
			      GLXContextTag tag);
 | 
						|
 | 
						|
typedef struct _SwapGroup *SwapGroupPtr;
 | 
						|
 | 
						|
static Bool SwapBarrierIsReadyToSwap(GLuint barrier);
 | 
						|
static void SwapSwapBarrier(GLuint barrier);
 | 
						|
static void UpdateSwapBarrierList(GLuint barrier,
 | 
						|
				  SwapGroupPtr pOldSwap,
 | 
						|
				  SwapGroupPtr pNewSwap);
 | 
						|
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
 *
 | 
						|
 * Swap Groups
 | 
						|
 *
 | 
						|
 ************************************************************************/
 | 
						|
 | 
						|
typedef struct _SwapGroup {
 | 
						|
    WindowPtr         pWin;
 | 
						|
    SwapGroupPtr      pNext;
 | 
						|
 | 
						|
    Bool              swapping;
 | 
						|
    Bool              sleeping;
 | 
						|
    GLuint            barrier;
 | 
						|
 | 
						|
    XID               drawable;
 | 
						|
    GLXContextTag     tag;
 | 
						|
    __GLXclientState *clState;
 | 
						|
} SwapGroupRec;
 | 
						|
 | 
						|
 | 
						|
static void SwapSwapGroup(SwapGroupPtr pSwap)
 | 
						|
{
 | 
						|
    SwapGroupPtr  pCur;
 | 
						|
 | 
						|
    /* All drawables in swap group are ready to swap, so just swap all
 | 
						|
     * drawables buffers and then wake up those clients that were
 | 
						|
     * previously sleeping */
 | 
						|
 | 
						|
    for (pCur = pSwap; pCur; pCur = pCur->pNext) {
 | 
						|
	if (pCur->swapping) {
 | 
						|
	    /* Swap pCur's buffers */
 | 
						|
	    __glXDoSwapBuffers(pCur->clState, pCur->drawable, pCur->tag);
 | 
						|
	    pCur->swapping = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Wakeup client */
 | 
						|
	if (pCur->sleeping) {
 | 
						|
	    ClientWakeup(pCur->clState->client);
 | 
						|
	    pCur->sleeping = FALSE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static Bool SwapGroupIsReadyToSwap(SwapGroupPtr pSwap)
 | 
						|
{
 | 
						|
    Bool  isReady = TRUE;
 | 
						|
 | 
						|
    /* The swap group is ready to swap when all drawables are ready to
 | 
						|
     * swap.  NOTE: A drawable is also ready to swap if it is not
 | 
						|
     * currently mapped */
 | 
						|
    for (; pSwap; pSwap = pSwap->pNext) {
 | 
						|
	isReady &= (pSwap->swapping || !pSwap->pWin->mapped);
 | 
						|
	/* FIXME: Should we use pSwap->pWin->mapped or ...->realized ??? */
 | 
						|
    }
 | 
						|
 | 
						|
    return isReady;
 | 
						|
}
 | 
						|
 | 
						|
static Bool SGSwapCleanup(ClientPtr client, pointer closure)
 | 
						|
{
 | 
						|
    /* SwapGroupPtr  pSwap = (SwapGroupPtr)closure; */
 | 
						|
 | 
						|
    /* This should not be called unless the client has died in which
 | 
						|
     * case we should remove the buffer from the swap list */
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
int SGSwapBuffers(__GLXclientState *cl, XID drawId, GLXContextTag tag,
 | 
						|
		  DrawablePtr pDraw)
 | 
						|
{
 | 
						|
    WindowPtr      pWin     = (WindowPtr)pDraw;
 | 
						|
    dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
 | 
						|
    SwapGroupPtr   pSwap    = pWinPriv->swapGroup;
 | 
						|
    SwapGroupPtr   pCur;
 | 
						|
 | 
						|
    for (pCur = pSwap; pCur && pCur->pWin != pWin; pCur = pCur->pNext);
 | 
						|
    if (!pCur)
 | 
						|
	return BadDrawable;
 | 
						|
 | 
						|
    pCur->clState  = cl;
 | 
						|
    pCur->drawable = drawId;
 | 
						|
    pCur->tag      = tag;
 | 
						|
 | 
						|
    /* We are now in the process of swapping */
 | 
						|
    pCur->swapping = TRUE;
 | 
						|
 | 
						|
    if (pSwap->barrier && SwapBarrierIsReadyToSwap(pSwap->barrier)) {
 | 
						|
	/* The swap group is bound to a barrier and the barrier is ready
 | 
						|
	 * to swap, so swap all the swap groups that are bound to this
 | 
						|
	 * group's swap barrier */
 | 
						|
	SwapSwapBarrier(pSwap->barrier);
 | 
						|
    } else if (!pSwap->barrier && SwapGroupIsReadyToSwap(pSwap)) {
 | 
						|
	/* Do the swap if the entire swap group is ready to swap and the
 | 
						|
	 * group is not bound to a swap barrier */
 | 
						|
	SwapSwapGroup(pSwap);
 | 
						|
    } else {
 | 
						|
	/* The swap group/barrier is not yet ready to swap, so put
 | 
						|
	 * client to sleep until the rest are ready to swap */
 | 
						|
	ClientSleep(cl->client, SGSwapCleanup, (pointer)pWin);
 | 
						|
	pCur->sleeping = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static void SGWindowUnmapped(WindowPtr pWin)
 | 
						|
{
 | 
						|
    dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
 | 
						|
    SwapGroupPtr   pSwap    = pWinPriv->swapGroup;
 | 
						|
 | 
						|
    /* Now that one of the windows in the swap group has been unmapped,
 | 
						|
     * see if the entire swap group/barrier is ready to swap */
 | 
						|
 | 
						|
    if (pSwap->barrier && SwapBarrierIsReadyToSwap(pSwap->barrier)) {
 | 
						|
	SwapSwapBarrier(pSwap->barrier);
 | 
						|
    } else if (!pSwap->barrier && SwapGroupIsReadyToSwap(pSwap)) {
 | 
						|
	SwapSwapGroup(pSwap);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void SGWindowDestroyed(WindowPtr pWin)
 | 
						|
{
 | 
						|
    JoinSwapGroupSGIX((DrawablePtr)pWin, NULL);
 | 
						|
}
 | 
						|
 | 
						|
static SwapGroupPtr CreateSwapEntry(WindowPtr pWin)
 | 
						|
{
 | 
						|
    SwapGroupPtr  pEntry;
 | 
						|
 | 
						|
    /* Allocate new swap group */
 | 
						|
    pEntry = xalloc(sizeof(*pEntry));
 | 
						|
    if (!pEntry) return NULL;
 | 
						|
 | 
						|
    /* Initialize swap group */
 | 
						|
    pEntry->pWin     = pWin;
 | 
						|
    pEntry->pNext    = NULL;
 | 
						|
    pEntry->swapping = FALSE;
 | 
						|
    pEntry->sleeping = FALSE;
 | 
						|
    pEntry->barrier  = 0;
 | 
						|
    /* The following are not initialized until SwapBuffers is called:
 | 
						|
     *     pEntry->drawable
 | 
						|
     *     pEntry->tag
 | 
						|
     *     pEntry->clState
 | 
						|
     */
 | 
						|
 | 
						|
    return pEntry;
 | 
						|
}
 | 
						|
 | 
						|
static void FreeSwapEntry(SwapGroupPtr pEntry)
 | 
						|
{
 | 
						|
    /* Since we have removed the drawable from its previous swap group
 | 
						|
     * and it won't be added to another swap group, the only thing that
 | 
						|
     * we need to do is to make sure that the drawable's client is not
 | 
						|
     * sleeping.  This could happen if one thread is sleeping, while
 | 
						|
     * another thread called glxJoinSwapGroup().  Note that all sleeping
 | 
						|
     * threads should also be swapping, but there is a small window in
 | 
						|
     * the SGSwapBuffer() logic, above, where swapping can be set but
 | 
						|
     * sleeping is not.  We check both independently here just to be
 | 
						|
     * pedantic. */
 | 
						|
 | 
						|
    /* Handle swap buffer request */
 | 
						|
    if (pEntry->swapping)
 | 
						|
	__glXDoSwapBuffers(pEntry->clState, pEntry->drawable, pEntry->tag);
 | 
						|
 | 
						|
    /* Wake up client */
 | 
						|
    if (pEntry->sleeping)
 | 
						|
	ClientWakeup(pEntry->clState->client);
 | 
						|
 | 
						|
    /* We can free the pEntry entry since it has already been removed
 | 
						|
     * from the swap group list and it won't be needed any longer */
 | 
						|
    xfree(pEntry);
 | 
						|
}
 | 
						|
 | 
						|
int JoinSwapGroupSGIX(DrawablePtr pDraw, DrawablePtr pMember)
 | 
						|
{
 | 
						|
    if (pDraw->type == DRAWABLE_WINDOW) {
 | 
						|
	WindowPtr      pWin     = (WindowPtr)pDraw;
 | 
						|
	dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
 | 
						|
	SwapGroupPtr   pOldSwap = NULL;
 | 
						|
	SwapGroupPtr   pEntry;
 | 
						|
 | 
						|
	/* If pDraw and pMember are already members of the same swap
 | 
						|
	 * group, just return Success since there is nothing to do */
 | 
						|
	for (pEntry = pWinPriv->swapGroup; pEntry; pEntry = pEntry->pNext)
 | 
						|
	    if (pEntry->pWin == (WindowPtr)pMember)
 | 
						|
		return Success;
 | 
						|
 | 
						|
	/* Remove pDraw from its current swap group */
 | 
						|
	if (pWinPriv->swapGroup) {
 | 
						|
	    SwapGroupPtr  pSwapGroup = pWinPriv->swapGroup;
 | 
						|
	    SwapGroupPtr  pPrev;
 | 
						|
 | 
						|
	    /* Find old swap entry in swap group and save in pOldSwap
 | 
						|
	     * for later use */
 | 
						|
	    for (pOldSwap = pWinPriv->swapGroup, pPrev = NULL;
 | 
						|
		 pOldSwap && pOldSwap->pWin != pWin;
 | 
						|
		 pPrev = pOldSwap, pOldSwap = pOldSwap->pNext);
 | 
						|
	    if (!pOldSwap)
 | 
						|
		return BadDrawable;
 | 
						|
 | 
						|
	    /* Remove pDraw's swap group entry from swap group list */
 | 
						|
	    if (pPrev) {
 | 
						|
		pPrev->pNext = pOldSwap->pNext;
 | 
						|
	    } else {
 | 
						|
		/* pWin is at the head of the swap group list, so we
 | 
						|
		 * need to update all other members of this swap
 | 
						|
		 * group */
 | 
						|
		for (pEntry = pOldSwap->pNext; pEntry; pEntry = pEntry->pNext)
 | 
						|
		    DMX_GET_WINDOW_PRIV(pEntry->pWin)->swapGroup
 | 
						|
			= pOldSwap->pNext;
 | 
						|
 | 
						|
		/* Update the barrier list as well */
 | 
						|
		if (pOldSwap->barrier)
 | 
						|
		    UpdateSwapBarrierList(pOldSwap->barrier,
 | 
						|
					  pOldSwap, pOldSwap->pNext);
 | 
						|
 | 
						|
		/* Set pSwapGroup to point to the swap group without
 | 
						|
		 * pOldSwap */
 | 
						|
		pSwapGroup = pOldSwap->pNext;
 | 
						|
	    }
 | 
						|
 | 
						|
	    /* Check to see if current swap group can now swap since we
 | 
						|
	     * know at this point that pDraw and pMember are guaranteed
 | 
						|
	     * to previously be in different swap groups */
 | 
						|
	    if (pSwapGroup && SwapGroupIsReadyToSwap(pSwapGroup)) {
 | 
						|
		SwapSwapGroup(pSwapGroup);
 | 
						|
	    }
 | 
						|
 | 
						|
	    /* Make the old swap entry a standalone group */
 | 
						|
	    pOldSwap->pNext = NULL;
 | 
						|
	    pOldSwap->barrier = 0;
 | 
						|
 | 
						|
	    /* Reset pWin's swap group */
 | 
						|
	    pWinPriv->swapGroup = NULL;
 | 
						|
	    pWinPriv->windowDestroyed = NULL;
 | 
						|
	    pWinPriv->windowUnmapped = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pMember || pMember->type != DRAWABLE_WINDOW) {
 | 
						|
	    /* Free old swap group since it is no longer needed */
 | 
						|
	    if (pOldSwap) FreeSwapEntry(pOldSwap);
 | 
						|
	} else if (pDraw == pMember && pOldSwap) {
 | 
						|
	    /* Special case where pDraw was previously created and we
 | 
						|
	     * are now just putting it to its own swap group */
 | 
						|
	    pWinPriv->swapGroup = pOldSwap;
 | 
						|
	    pWinPriv->windowDestroyed = SGWindowDestroyed;
 | 
						|
	    pWinPriv->windowUnmapped = SGWindowUnmapped;
 | 
						|
 | 
						|
	    /* Check to see if pDraw is ready to swap */
 | 
						|
	    if (SwapGroupIsReadyToSwap(pOldSwap))
 | 
						|
		SwapSwapGroup(pOldSwap);
 | 
						|
	} else if (pMember->type == DRAWABLE_WINDOW) {
 | 
						|
	    WindowPtr      pMemberWin       = (WindowPtr)pMember;
 | 
						|
	    dmxWinPrivPtr  pMemberPriv      = DMX_GET_WINDOW_PRIV(pMemberWin);
 | 
						|
	    SwapGroupPtr   pMemberSwapGroup = pMemberPriv->swapGroup;
 | 
						|
 | 
						|
	    /* Finally, how we can add pDraw to pMember's swap group */
 | 
						|
 | 
						|
	    /* If pMember is not currently in a swap group, then create
 | 
						|
	     * one for it since we are just about to add pDraw to it. */
 | 
						|
	    if (!pMemberSwapGroup) {
 | 
						|
		/* Create new swap group */
 | 
						|
		pMemberSwapGroup = CreateSwapEntry(pMemberWin);
 | 
						|
		if (!pMemberSwapGroup) {
 | 
						|
		    if (pOldSwap) FreeSwapEntry(pOldSwap);
 | 
						|
		    return BadAlloc;
 | 
						|
		}
 | 
						|
 | 
						|
		/* Set pMember's swap group */
 | 
						|
		pMemberPriv->swapGroup = pMemberSwapGroup;
 | 
						|
		pMemberPriv->windowDestroyed = SGWindowDestroyed;
 | 
						|
		pMemberPriv->windowUnmapped = SGWindowUnmapped;
 | 
						|
	    }
 | 
						|
 | 
						|
	    /* If pDraw == pMember, that means pDraw was not a member of
 | 
						|
	     * a group previously (or it would have been handled by the
 | 
						|
	     * special case above), so no additional work is required
 | 
						|
	     * since we just created a new swap group for pMember (i.e.,
 | 
						|
	     * pDraw). */
 | 
						|
 | 
						|
	    if (pDraw != pMember) {
 | 
						|
		/* If pDraw was not previously in a swap group, then create
 | 
						|
		 * an entry for it */
 | 
						|
		if (!pOldSwap) {
 | 
						|
		    /* Create new swap group */
 | 
						|
		    pOldSwap = CreateSwapEntry(pWin);
 | 
						|
		    if (!pOldSwap) {
 | 
						|
			/* If we just created a swap group for pMember, we
 | 
						|
			 * need to free it here */
 | 
						|
			if (pMemberSwapGroup->pNext == NULL) {
 | 
						|
			    FreeSwapEntry(pMemberSwapGroup);
 | 
						|
			    pMemberPriv->swapGroup = NULL;
 | 
						|
			}
 | 
						|
			return BadAlloc;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
 | 
						|
		/* Find last entry in pMember's swap group */
 | 
						|
		for (pEntry = pMemberSwapGroup;
 | 
						|
		     pEntry->pNext;
 | 
						|
		     pEntry = pEntry->pNext);
 | 
						|
 | 
						|
		/* Add pDraw's swap group entry to pMember's swap group list */
 | 
						|
		pEntry->pNext = pOldSwap;
 | 
						|
 | 
						|
		/* Add pDraw to pMember's swap barrier */
 | 
						|
		pOldSwap->barrier = pEntry->barrier;
 | 
						|
 | 
						|
		/* Set pDraw's swap group */
 | 
						|
		pWinPriv->swapGroup = pMemberSwapGroup;
 | 
						|
		pWinPriv->windowDestroyed = SGWindowDestroyed;
 | 
						|
		pWinPriv->windowUnmapped = SGWindowUnmapped;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
 *
 | 
						|
 * Swap Barriers
 | 
						|
 *
 | 
						|
 ************************************************************************/
 | 
						|
 | 
						|
#define GLX_MAX_SWAP_BARRIERS 10
 | 
						|
 | 
						|
typedef struct _SwapBarrier *SwapBarrierPtr;
 | 
						|
typedef struct _SwapBarrier {
 | 
						|
    SwapGroupPtr    pSwap;
 | 
						|
    SwapBarrierPtr  pNext;
 | 
						|
} SwapBarrierRec;
 | 
						|
 | 
						|
static SwapBarrierPtr SwapBarrierList[GLX_MAX_SWAP_BARRIERS+1];
 | 
						|
 | 
						|
void SwapBarrierInit(void)
 | 
						|
{
 | 
						|
    int  i;
 | 
						|
 | 
						|
    for (i = 0; i <= GLX_MAX_SWAP_BARRIERS; i++)
 | 
						|
	SwapBarrierList[i] = NULL;
 | 
						|
}
 | 
						|
 | 
						|
void SwapBarrierReset(void)
 | 
						|
{
 | 
						|
    int  i;
 | 
						|
 | 
						|
    for (i = 0; i <= GLX_MAX_SWAP_BARRIERS; i++) {
 | 
						|
	SwapBarrierPtr  pBarrier, pNextBarrier;;
 | 
						|
	for (pBarrier = SwapBarrierList[i];
 | 
						|
	     pBarrier;
 | 
						|
	     pBarrier = pNextBarrier) {
 | 
						|
	    pNextBarrier = pBarrier->pNext;
 | 
						|
	    xfree(pBarrier);
 | 
						|
	}
 | 
						|
	SwapBarrierList[i] = NULL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int QueryMaxSwapBarriersSGIX(int screen)
 | 
						|
{
 | 
						|
    return GLX_MAX_SWAP_BARRIERS;
 | 
						|
}
 | 
						|
 | 
						|
static Bool BindSwapGroupToBarrier(GLuint barrier, SwapGroupPtr pSwapGroup)
 | 
						|
{
 | 
						|
    SwapBarrierPtr  pBarrier;
 | 
						|
 | 
						|
    pBarrier = xalloc(sizeof(*pBarrier));
 | 
						|
    if (!pBarrier) return FALSE;
 | 
						|
 | 
						|
    /* Add the swap group to barrier's list */
 | 
						|
    pBarrier->pSwap = pSwapGroup;
 | 
						|
    pBarrier->pNext = SwapBarrierList[barrier];
 | 
						|
    SwapBarrierList[barrier] = pBarrier;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static Bool UnbindSwapGroupFromBarrier(GLuint barrier, SwapGroupPtr pSwapGroup)
 | 
						|
{
 | 
						|
    SwapBarrierPtr  pBarrier, pPrevBarrier;
 | 
						|
 | 
						|
    /* Find the swap group in barrier's list */
 | 
						|
    for (pBarrier = SwapBarrierList[barrier], pPrevBarrier = NULL;
 | 
						|
	 pBarrier && pBarrier->pSwap != pSwapGroup;
 | 
						|
	 pPrevBarrier = pBarrier, pBarrier = pBarrier->pNext);
 | 
						|
    if (!pBarrier) return FALSE;
 | 
						|
 | 
						|
    /* Remove the swap group from barrier's list */
 | 
						|
    if (pPrevBarrier) pPrevBarrier->pNext = pBarrier->pNext;
 | 
						|
    else              SwapBarrierList[barrier] = pBarrier->pNext;
 | 
						|
 | 
						|
    /* Free memory */
 | 
						|
    xfree(pBarrier);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void UpdateSwapBarrierList(GLuint barrier,
 | 
						|
				  SwapGroupPtr pOldSwap,
 | 
						|
				  SwapGroupPtr pNewSwap)
 | 
						|
{
 | 
						|
    SwapBarrierPtr  pBarrier;
 | 
						|
 | 
						|
    /* If the old swap group is being destroyed, then we need to remove
 | 
						|
     * the swap group from the list entirely */
 | 
						|
    if (!pNewSwap) {
 | 
						|
	UnbindSwapGroupFromBarrier(barrier, pOldSwap);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Otherwise, find the old swap group in the barrier list and change
 | 
						|
     * it to the new swap group */
 | 
						|
    for (pBarrier = SwapBarrierList[barrier];
 | 
						|
	 pBarrier;
 | 
						|
	 pBarrier = pBarrier->pNext) {
 | 
						|
	if (pBarrier->pSwap == pOldSwap) {
 | 
						|
	    pBarrier->pSwap = pNewSwap;
 | 
						|
	    return;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static Bool SwapBarrierIsReadyToSwap(GLuint barrier)
 | 
						|
{
 | 
						|
    SwapBarrierPtr  pBarrier;
 | 
						|
    Bool            isReady = TRUE;
 | 
						|
 | 
						|
    /* The swap barier is ready to swap when swap groups that are bound
 | 
						|
     * to barrier are ready to swap */
 | 
						|
    for (pBarrier = SwapBarrierList[barrier];
 | 
						|
	 pBarrier;
 | 
						|
	 pBarrier = pBarrier->pNext)
 | 
						|
	isReady &= SwapGroupIsReadyToSwap(pBarrier->pSwap);
 | 
						|
 | 
						|
    return isReady;
 | 
						|
}
 | 
						|
 | 
						|
static void SwapSwapBarrier(GLuint barrier)
 | 
						|
{
 | 
						|
    SwapBarrierPtr  pBarrier;
 | 
						|
 | 
						|
    /* Swap each group that is a member of this barrier */
 | 
						|
    for (pBarrier = SwapBarrierList[barrier];
 | 
						|
	 pBarrier;
 | 
						|
	 pBarrier = pBarrier->pNext)
 | 
						|
	SwapSwapGroup(pBarrier->pSwap);
 | 
						|
}
 | 
						|
 | 
						|
int BindSwapBarrierSGIX(DrawablePtr pDraw, int barrier)
 | 
						|
{
 | 
						|
    /* FIXME: Check for errors when pDraw->type != DRAWABLE_WINDOW */
 | 
						|
 | 
						|
    if (barrier < 0 || barrier > GLX_MAX_SWAP_BARRIERS)
 | 
						|
	return BadValue;
 | 
						|
 | 
						|
    if (pDraw->type == DRAWABLE_WINDOW) {
 | 
						|
	WindowPtr       pWin       = (WindowPtr)pDraw;
 | 
						|
	dmxWinPrivPtr   pWinPriv   = DMX_GET_WINDOW_PRIV(pWin);
 | 
						|
	SwapGroupPtr    pSwapGroup = pWinPriv->swapGroup;
 | 
						|
	SwapGroupPtr    pCur;
 | 
						|
 | 
						|
	if (!pSwapGroup) return BadDrawable;
 | 
						|
	if (barrier && pSwapGroup->barrier) return BadValue;
 | 
						|
 | 
						|
	/* Update the swap barrier list */
 | 
						|
	if (barrier) {
 | 
						|
	    if (!BindSwapGroupToBarrier(barrier, pSwapGroup))
 | 
						|
		return BadAlloc;
 | 
						|
	} else {
 | 
						|
	    if (!UnbindSwapGroupFromBarrier(pSwapGroup->barrier, pSwapGroup))
 | 
						|
		return BadDrawable;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Set the barrier for each member of this swap group */
 | 
						|
	for (pCur = pSwapGroup; pCur; pCur = pCur->pNext)
 | 
						|
	    pCur->barrier = barrier;
 | 
						|
    }
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 |