aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/dmx/glxProxy/glxswap.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/dmx/glxProxy/glxswap.c')
-rw-r--r--xorg-server/hw/dmx/glxProxy/glxswap.c1076
1 files changed, 538 insertions, 538 deletions
diff --git a/xorg-server/hw/dmx/glxProxy/glxswap.c b/xorg-server/hw/dmx/glxProxy/glxswap.c
index 1e184f914..1471d8b5f 100644
--- a/xorg-server/hw/dmx/glxProxy/glxswap.c
+++ b/xorg-server/hw/dmx/glxProxy/glxswap.c
@@ -1,538 +1,538 @@
-/*
- * 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;
-}
+/*
+ * 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 = malloc(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 */
+ free(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;
+ free(pBarrier);
+ }
+ SwapBarrierList[i] = NULL;
+ }
+}
+
+int QueryMaxSwapBarriersSGIX(int screen)
+{
+ return GLX_MAX_SWAP_BARRIERS;
+}
+
+static Bool BindSwapGroupToBarrier(GLuint barrier, SwapGroupPtr pSwapGroup)
+{
+ SwapBarrierPtr pBarrier;
+
+ pBarrier = malloc(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 */
+ free(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;
+}