From 0f834b91a4768673833ab4917e87d86c237bb1a6 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 23 Mar 2012 10:05:55 +0100 Subject: libX11 xserver fontconfig mesa pixman xkbcomp xkeyboard-config git update 23 Mar 2012 --- xorg-server/hw/dmx/glxProxy/glxswap.c | 1100 +++++++++++++++++---------------- 1 file changed, 562 insertions(+), 538 deletions(-) (limited to 'xorg-server/hw/dmx/glxProxy/glxswap.c') diff --git a/xorg-server/hw/dmx/glxProxy/glxswap.c b/xorg-server/hw/dmx/glxProxy/glxswap.c index 1471d8b5f..87a748621 100644 --- a/xorg-server/hw/dmx/glxProxy/glxswap.c +++ b/xorg-server/hw/dmx/glxProxy/glxswap.c @@ -1,538 +1,562 @@ -/* - * 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 - * - */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#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; -} +/* + * 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 + * + */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#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; +} -- cgit v1.2.3