|
|
/******************************Module*Header*******************************\
* Module Name: swapmult.c * * wglSwapMultiple implementation * * Created: 02-10-1997 * Author: Drew Bliss [drewb] * * Copyright (c) 1993-1997 Microsoft Corporation \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include <gencx.h>
#include <mcdcx.h>
/******************************Public*Routine******************************\
* * BufferSwapperType * * Determines what basic type of swapper is responsible for the given * swap info. * * History: * Mon Oct 14 18:46:28 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
#define BSWP_ICD 0
#define BSWP_MCD 1
#define BSWP_GENERIC 2
int BufferSwapperType(GENMCDSWAP *pgms) { // The buffer can be for an ICD, an MCD or generic
// 1. ICD buffers have an ICD pixel format
// 2. MCD buffers have MCD state
if (pgms->pwnd->ipfd <= pgms->pwnd->ipfdDevMax) { return BSWP_ICD; } else { if (pgms->pwnd->buffers != NULL) { if (pgms->pwnd->buffers->pMcdSurf != NULL) { return BSWP_MCD; } } }
return BSWP_GENERIC; }
/******************************Public*Routine******************************\
* * SameSwapper * * Checks whether the two swapinfos are swapped by the same swapping * agency. * * History: * Mon Oct 14 18:49:26 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
BOOL SameSwapper(int iSwapperTypeA, GENMCDSWAP *pgmsA, GENMCDSWAP *pgmsB) { switch(iSwapperTypeA) { case BSWP_ICD: // Must be the same ICD
if (BufferSwapperType(pgmsB) != BSWP_ICD || pgmsA->pwnd->pvDriver != pgmsB->pwnd->pvDriver) { return FALSE; } return TRUE; case BSWP_MCD: case BSWP_GENERIC: // No way to refine the comparison any more
return BufferSwapperType(pgmsB) == iSwapperTypeA;
default: ASSERTOPENGL(FALSE, "SameSwapper UNREACHED\n"); return FALSE; } }
/******************************Public*Routine******************************\
* * wglSwapMultipleBuffers * * Swaps as many of the given buffers as possible. * Returns a bitmask of the buffers that were swapped. * * History: * Mon Oct 14 17:19:09 1996 -by- Drew Bliss [drewb] * Created * \**************************************************************************/
// #define VERBOSE_MULTI
DWORD WINAPI wglSwapMultipleBuffers(UINT cBuffers, CONST WGLSWAP *pwswapAll) { GENMCDSWAP agmsAll[WGL_SWAPMULTIPLE_MAX]; GENMCDSWAP *pgmsFirst; GENMCDSWAP *pgmsEnd; GENMCDSWAP *pgms; GENMCDSWAP *apgmsGroup[WGL_SWAPMULTIPLE_MAX]; GENMCDSWAP **ppgmsGroup; WGLSWAP *pwswap; DWORD dwMask; UINT uiCur; UINT uiIdx; GLWINDOWID gwid; GLGENwindow *pwnd; DWORD dwBit; DWORD dwCallMask; DWORD adwCallIndex[WGL_SWAPMULTIPLE_MAX]; DWORD *pdwCallIndex; DWORD cGroup; DWORD cDone; int iSwapperType; BOOL bCall;
ASSERTOPENGL(WGL_SWAPMULTIPLE_MAX <= 16, "WGL_SWAPMULTIPLE_MAX too large\n"); ASSERTOPENGL(WGL_SWAPMULTIPLE_MAX == OPENGLCMD_MAXMULTI && WGL_SWAPMULTIPLE_MAX == MCDESC_MAX_EXTRA_WNDOBJ, "WGL_SWAPMULTIPLE_MAX mismatch\n");
if (cBuffers > WGL_SWAPMULTIPLE_MAX) { SetLastError(ERROR_INVALID_FUNCTION); return 0; } dwMask = 0; // Validate all input buffers and do one-time information gathering for
// them.
pgms = agmsAll; pwswap = (WGLSWAP *)pwswapAll; for (uiCur = 0; uiCur < cBuffers; uiCur++, pwswap++) { // Validate DC
if (IsDirectDrawDevice(pwswap->hdc)) { continue; } switch(GetObjectType(pwswap->hdc)) { case OBJ_DC: break; case OBJ_MEMDC: // Nothing to do for memdc
dwMask |= 1 << uiCur; // Fall through
default: continue; }
// Look up pwnd
WindowIdFromHdc(pwswap->hdc, &gwid); pwnd = pwndGetFromID(&gwid); if (pwnd == NULL) { continue; }
if (pwnd->ipfd == 0) { pwndRelease(pwnd); continue; }
// We have a valid candidate for swapping. Remember it.
pgms->pwswap = pwswap; pgms->pwnd = pwnd; pgms++; }
#ifdef VERBOSE_MULTI
DbgPrint("%d cand\n", pgms-agmsAll); #endif
// Walk list of candidates and gather by swapper
pgmsEnd = pgms; pgmsFirst = agmsAll; while (pgmsFirst < pgmsEnd) { // Skip over any candidates that have already been swapped
if (pgmsFirst->pwswap == NULL) { pgmsFirst++; continue; }
iSwapperType = BufferSwapperType(pgmsFirst);
#ifdef VERBOSE_MULTI
DbgPrint(" Gathering for %d, type %d\n", pgmsFirst-agmsAll, iSwapperType); #endif
ppgmsGroup = apgmsGroup; *ppgmsGroup++ = pgmsFirst; pgmsFirst++;
pgms = pgmsFirst; while (pgms < pgmsEnd) { if (pgms->pwswap != NULL) { if (SameSwapper(iSwapperType, apgmsGroup[0], pgms)) { #ifdef VERBOSE_MULTI
DbgPrint(" Match with %d\n", pgms-agmsAll); #endif
*ppgmsGroup++ = pgms; } }
pgms++; }
// Dispatch group to swapper for swapping. This may require
// multiple attempts because the same swapper may be responsible
// for multiple devices and only one device can be handled at
// a time.
cGroup = (DWORD)((ULONG_PTR)(ppgmsGroup-apgmsGroup));
#ifdef VERBOSE_MULTI
DbgPrint(" Group of %d\n", cGroup); #endif
cDone = 0; while (cDone < cGroup) { WGLSWAP awswapIcdCall[WGL_SWAPMULTIPLE_MAX]; PGLDRIVER pgldrv; GENMCDSWAP agmsMcdCall[WGL_SWAPMULTIPLE_MAX]; GENMCDSWAP *pgmsCall; // Collect any remaining swaps into calling format
pdwCallIndex = adwCallIndex; pgms = NULL;
// After each case, uiCur must be set to the number of
// swaps attempted and dwMask must be set to the
// attempted/succeeded mask.
switch(iSwapperType) { case BSWP_ICD: pwswap = awswapIcdCall; for (uiCur = 0; uiCur < cGroup; uiCur++) { if (apgmsGroup[uiCur] != NULL) { pgms = apgmsGroup[uiCur]; *pwswap++ = *pgms->pwswap; *pdwCallIndex++ = uiCur; } }
uiCur = (UINT)((ULONG_PTR)(pwswap-awswapIcdCall)); // Quit if nothing remaining
if (uiCur == 0) { dwCallMask = 0; } else { pgldrv = (PGLDRIVER)pgms->pwnd->pvDriver; ASSERTOPENGL(pgldrv != NULL, "ICD not loaded\n"); // Ask for swap
// If the ICD supports SwapMultiple, pass the call on
if (pgldrv->pfnDrvSwapMultipleBuffers != NULL) { dwCallMask = pgldrv-> pfnDrvSwapMultipleBuffers(uiCur, awswapIcdCall); } else if (pgldrv->pfnDrvSwapLayerBuffers != NULL) { // The ICD doesn't support multiple swap but
// it does support layer swaps so iterate
// through all the separate swaps.
dwCallMask = 0; dwBit = 1 << (uiCur-1); while (--pwswap >= awswapIcdCall) { // Every swap is attempted
dwCallMask |= dwBit << (32-WGL_SWAPMULTIPLE_MAX);
if (pgldrv-> pfnDrvSwapLayerBuffers(pwswap->hdc, pwswap->uiFlags)) { dwCallMask |= dwBit; }
dwBit >>= 1; } } else { // The ICD only supports SwapBuffers so
// iterate and swap all main plane requests.
// Any overlay plane swaps are ignored and
// reported as successful.
dwCallMask = 0; dwBit = 1 << (uiCur-1); while (--pwswap >= awswapIcdCall) { // Every swap is attempted
dwCallMask |= dwBit << (32-WGL_SWAPMULTIPLE_MAX);
if (pwswap->uiFlags & WGL_SWAP_MAIN_PLANE) { bCall = __DrvSwapBuffers(pwswap->hdc, FALSE); } else { bCall = TRUE; }
if (bCall) { dwCallMask |= dwBit; }
dwBit >>= 1; } } } break; case BSWP_MCD: pgmsCall = agmsMcdCall; for (uiCur = 0; uiCur < cGroup; uiCur++) { if (apgmsGroup[uiCur] != NULL) { pgms = apgmsGroup[uiCur]; *pgmsCall++ = *pgms; *pdwCallIndex++ = uiCur; } }
uiCur = (UINT)((ULONG_PTR)(pgmsCall-agmsMcdCall)); // Quit if nothing remaining
if (uiCur == 0) { dwCallMask = 0; } else { // Ask for swap
dwCallMask = GenMcdSwapMultiple(uiCur, agmsMcdCall); } break;
case BSWP_GENERIC: // No accleration exists so just iterate and swap
dwCallMask = 0; dwBit = 1; for (uiCur = 0; uiCur < cGroup; uiCur++) { pgms = apgmsGroup[uiCur]; *pdwCallIndex++ = uiCur;
// Every swap is attempted
dwCallMask |= dwBit << (32-WGL_SWAPMULTIPLE_MAX);
// Since this is a generic swap we only swap the
// main plane. Overlay planes are ignored and
// reported as successful.
if (pgms->pwswap->uiFlags & WGL_SWAP_MAIN_PLANE) { ENTER_WINCRIT(pgms->pwnd);
bCall = glsrvSwapBuffers(pgms->pwswap->hdc, pgms->pwnd); LEAVE_WINCRIT(pgms->pwnd); } else { bCall = TRUE; }
if (bCall) { dwCallMask |= dwBit; } dwBit <<= 1; } break; }
#ifdef VERBOSE_MULTI
DbgPrint(" Attempted %d, mask %X\n", uiCur, dwCallMask); #endif
// Quit if nothing was swapped.
if (dwCallMask == 0) { break; } // Determine which buffers were really swapped and
// clear any buffers for which a swap was attempted.
dwBit = 1 << (uiCur-1); while (uiCur-- > 0) { uiIdx = adwCallIndex[uiCur]; pgms = apgmsGroup[uiIdx]; if (dwCallMask & dwBit) { dwMask |= 1 << (pgms->pwswap-pwswapAll); } if ((dwCallMask >> (32-WGL_SWAPMULTIPLE_MAX)) & dwBit) { // Take out of overall list
pgms->pwswap = NULL; // Take out of group list
apgmsGroup[uiIdx] = NULL;
cDone++; } dwBit >>= 1; }
#ifdef VERBOSE_MULTI
DbgPrint(" Done with %d, mask %X\n", cDone, dwMask); #endif
} }
// Release all the pwnds
pgms = agmsAll; while (pgms < pgmsEnd) { pwndRelease(pgms->pwnd); pgms++; }
#ifdef VERBOSE_MULTI
DbgPrint("Final mask %X\n", dwMask); #endif
return dwMask; }
|