4266 lines
131 KiB
C
4266 lines
131 KiB
C
/******************************Module*Header*******************************\
|
|
* Module Name: mcdcx.c
|
|
*
|
|
* GenMcdXXX layer between generic software implementation and MCD functions.
|
|
*
|
|
* Created: 05-Feb-1996 21:37:33
|
|
* Author: Gilman Wong [gilmanw]
|
|
*
|
|
* Copyright (c) 1995 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef _MCD_
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bInitMcd
|
|
*
|
|
* Load MCD32.DLL and initialize the MCD api function table.
|
|
*
|
|
* History:
|
|
* 11-Mar-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
MCDTABLE *gpMcdTable = (MCDTABLE *) NULL;
|
|
MCDTABLE McdTable;
|
|
MCDDRIVERINFOI McdDriverInfo;
|
|
|
|
// Checks MCD version to see if the driver can accept direct buffer
|
|
// access. Direct access was introduced in 1.1.
|
|
#define SUPPORTS_DIRECT() \
|
|
(McdDriverInfo.mcdDriverInfo.verMinor >= 0x10 || \
|
|
McdDriverInfo.mcdDriverInfo.verMajor > 1)
|
|
|
|
// Checks MCD version for 2.0 or greater
|
|
#define SUPPORTS_20() \
|
|
(McdDriverInfo.mcdDriverInfo.verMajor >= 2)
|
|
|
|
static char *pszMcdEntryPoints[] = {
|
|
"MCDGetDriverInfo",
|
|
"MCDDescribeMcdPixelFormat",
|
|
"MCDDescribePixelFormat",
|
|
"MCDCreateContext",
|
|
"MCDDeleteContext",
|
|
"MCDAlloc",
|
|
"MCDFree",
|
|
"MCDBeginState",
|
|
"MCDFlushState",
|
|
"MCDAddState",
|
|
"MCDAddStateStruct",
|
|
"MCDSetViewport",
|
|
"MCDSetScissorRect",
|
|
"MCDQueryMemStatus",
|
|
"MCDProcessBatch",
|
|
"MCDReadSpan",
|
|
"MCDWriteSpan",
|
|
"MCDClear",
|
|
"MCDSwap",
|
|
"MCDGetBuffers",
|
|
"MCDAllocBuffers",
|
|
"MCDLock",
|
|
"MCDUnlock",
|
|
"MCDBindContext",
|
|
"MCDSync",
|
|
"MCDCreateTexture",
|
|
"MCDDeleteTexture",
|
|
"MCDUpdateSubTexture",
|
|
"MCDUpdateTexturePalette",
|
|
"MCDUpdateTexturePriority",
|
|
"MCDUpdateTextureState",
|
|
"MCDTextureStatus",
|
|
"MCDTextureKey",
|
|
"MCDDescribeMcdLayerPlane",
|
|
"MCDDescribeLayerPlane",
|
|
"MCDSetLayerPalette",
|
|
"MCDDrawPixels",
|
|
"MCDReadPixels",
|
|
"MCDCopyPixels",
|
|
"MCDPixelMap",
|
|
"MCDDestroyWindow",
|
|
"MCDGetTextureFormats",
|
|
"MCDSwapMultiple",
|
|
"MCDProcessBatch2"
|
|
};
|
|
#define NUM_MCD_ENTRY_POINTS (sizeof(pszMcdEntryPoints)/sizeof(char *))
|
|
|
|
#define STR_MCD32_DLL "MCD32.DLL"
|
|
|
|
BOOL FASTCALL bInitMcd(HDC hdc)
|
|
{
|
|
static BOOL bFirstTime = TRUE;
|
|
|
|
ASSERTOPENGL(NUM_MCD_ENTRY_POINTS == sizeof(MCDTABLE)/sizeof(void *),
|
|
"MCD entry points mismatch\n");
|
|
//
|
|
// Note on multi-threaded initialization.
|
|
//
|
|
// Since the table memory exists in global memory and the pointer to
|
|
// the table is always set to point to this, it doesn't matter if multiple
|
|
// thread attempt to run the initialization routine. The worse that
|
|
// could happen is that we set the table multiple times.
|
|
//
|
|
|
|
if (bFirstTime && (gpMcdTable == (MCDTABLE *) NULL))
|
|
{
|
|
HMODULE hmod;
|
|
PROC *ppfn;
|
|
|
|
//
|
|
// Attempt the load once and once only. Otherwise application
|
|
// initialization time could be significantly slowed if MCD32.DLL
|
|
// does not exist.
|
|
//
|
|
// We could have attempted this in the DLL entry point in responce
|
|
// to PROCESS_ATTACH, but then we might end up wasting working set
|
|
// if MCD is never used.
|
|
//
|
|
// So instead we control the load attempt with this static flag.
|
|
//
|
|
|
|
bFirstTime = FALSE;
|
|
|
|
hmod = LoadLibraryA(STR_MCD32_DLL);
|
|
|
|
if (hmod)
|
|
{
|
|
MCDTABLE McdTableLocal;
|
|
BOOL bLoadFailed = FALSE;
|
|
BOOL bDriverValid = FALSE;
|
|
int i;
|
|
|
|
//
|
|
// Get address for each of the MCD entry points.
|
|
//
|
|
// To be multi-thread safe, we store the pointers in a local
|
|
// table. Only after the *entire* table is successfully
|
|
// initialized can we copy it to the global table.
|
|
//
|
|
|
|
ppfn = (PROC *) &McdTableLocal.pMCDGetDriverInfo;
|
|
for (i = 0; i < NUM_MCD_ENTRY_POINTS; i++, ppfn++)
|
|
{
|
|
*ppfn = GetProcAddress(hmod, pszMcdEntryPoints[i]);
|
|
|
|
if (!*ppfn)
|
|
{
|
|
WARNING1("bInitMcd: missing entry point %s\n", pszMcdEntryPoints[i]);
|
|
bLoadFailed = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If all entry points successfully loaded, validate driver
|
|
// by checking the MCDDRIVERINFO.
|
|
//
|
|
|
|
if (!bLoadFailed)
|
|
{
|
|
if ((McdTableLocal.pMCDGetDriverInfo)(hdc, &McdDriverInfo))
|
|
{
|
|
//
|
|
// Validate MCD driver version, etc.
|
|
//
|
|
|
|
//!!!mcd -- what other types of validation can we do?
|
|
#ifdef ALLOW_NEW_MCD
|
|
if ((McdDriverInfo.mcdDriverInfo.verMajor == 1 &&
|
|
(McdDriverInfo.mcdDriverInfo.verMinor == 0 ||
|
|
McdDriverInfo.mcdDriverInfo.verMinor == 0x10)) ||
|
|
(McdDriverInfo.mcdDriverInfo.verMajor == 2 &&
|
|
McdDriverInfo.mcdDriverInfo.verMinor == 0))
|
|
#else
|
|
if (McdDriverInfo.mcdDriverInfo.verMajor == 1 &&
|
|
McdDriverInfo.mcdDriverInfo.verMinor == 0)
|
|
#endif
|
|
{
|
|
bDriverValid = TRUE;
|
|
}
|
|
else
|
|
{
|
|
WARNING("bInitMcd: bad version\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// It is now safe to call MCD entry points via the table. Copy
|
|
// local copy to the global table and set the global pointer.
|
|
//
|
|
|
|
if (bDriverValid)
|
|
{
|
|
McdTable = McdTableLocal;
|
|
gpMcdTable = &McdTable;
|
|
}
|
|
else
|
|
{
|
|
WARNING1("bInitMcd: unloading %s\n", STR_MCD32_DLL);
|
|
FreeLibrary(hmod);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (gpMcdTable != (MCDTABLE *) NULL);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vFlushDirtyState
|
|
*
|
|
* GENMCDSTATE maintains a set of dirty flags to track state changes.
|
|
* This function updates the MCD driver state that is marked dirty.
|
|
* The dirty flags are consequently cleared.
|
|
*
|
|
* History:
|
|
* 07-Mar-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID FASTCALL vFlushDirtyState(__GLGENcontext *gengc)
|
|
{
|
|
if (gengc->pMcdState)
|
|
{
|
|
//
|
|
// Viewport, scissor, and texture each have separate update
|
|
// functions/structures. Check the dirty flags and update
|
|
// these first.
|
|
//
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, VIEWPORT))
|
|
{
|
|
GenMcdViewport(gengc);
|
|
MCD_STATE_CLEAR(gengc, VIEWPORT);
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, SCISSOR))
|
|
{
|
|
GenMcdScissor(gengc);
|
|
|
|
//
|
|
// DO NOT CLEAR. Scissor is passed in two forms: a direct call
|
|
// that affects clipping in MCDSRV32.DLL and a state call that
|
|
// the MCD driver can optionally use for high performance h/w.
|
|
// We need to leave the flag set so that the state call will
|
|
// also be processed.
|
|
//
|
|
//MCD_STATE_CLEAR(gengc, SCISSOR);
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, TEXTURE))
|
|
{
|
|
if (gengc->gc.texture.currentTexture)
|
|
{
|
|
__GLtextureObject *texobj;
|
|
|
|
if (gengc->gc.state.enables.general & __GL_TEXTURE_2D_ENABLE)
|
|
texobj = __glLookUpTextureObject(&gengc->gc, GL_TEXTURE_2D);
|
|
else if (gengc->gc.state.enables.general & __GL_TEXTURE_1D_ENABLE)
|
|
texobj = __glLookUpTextureObject(&gengc->gc, GL_TEXTURE_1D);
|
|
else
|
|
texobj = (__GLtextureObject *) NULL;
|
|
|
|
if (texobj && texobj->loadKey)
|
|
{
|
|
ASSERTOPENGL(&texobj->texture.map == gengc->gc.texture.currentTexture,
|
|
"vFlushDirtyState: texobj not current texture\n");
|
|
|
|
GenMcdUpdateTextureState(gengc,
|
|
&texobj->texture.map,
|
|
texobj->loadKey);
|
|
MCD_STATE_CLEAR(gengc, TEXTURE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Take care of the other state.
|
|
//
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, ALL))
|
|
{
|
|
//
|
|
// Setup state command.
|
|
//
|
|
|
|
(gpMcdTable->pMCDBeginState)(&gengc->pMcdState->McdContext,
|
|
gengc->pMcdState->McdCmdBatch.pv);
|
|
|
|
//
|
|
// Add MCDPIXELSTATE structure to state command if needed.
|
|
//
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, PIXELSTATE))
|
|
{
|
|
GenMcdUpdatePixelState(gengc);
|
|
}
|
|
|
|
if (gengc->pMcdState->McdRcInfo.requestFlags &
|
|
MCDRCINFO_FINE_GRAINED_STATE)
|
|
{
|
|
// Add front-end and rendering states.
|
|
GenMcdUpdateFineState(gengc);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Add MCDRENDERSTATE structure to state command if needed.
|
|
//
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, RENDERSTATE))
|
|
{
|
|
GenMcdUpdateRenderState(gengc);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add MCDSCISSORSTATE structure to state command if needed.
|
|
//
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, SCISSOR))
|
|
{
|
|
GenMcdUpdateScissorState(gengc);
|
|
}
|
|
|
|
//
|
|
// Add MCDTEXENVSTATE structure to state command if needed.
|
|
//
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, TEXENV))
|
|
{
|
|
GenMcdUpdateTexEnvState(gengc);
|
|
}
|
|
|
|
//
|
|
// Send state command to MCD driver.
|
|
//
|
|
|
|
(gpMcdTable->pMCDFlushState)(gengc->pMcdState->McdCmdBatch.pv);
|
|
|
|
//
|
|
// Clear dirty flags.
|
|
//
|
|
|
|
MCD_STATE_RESET(gengc);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vInitPolyArrayBuffer
|
|
*
|
|
* Initialize the POLYARRAY/POLYDATA buffer pointed to by pdBuf.
|
|
*
|
|
* History:
|
|
* 12-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID FASTCALL vInitPolyArrayBuffer(__GLcontext *gc, POLYDATA *pdBuf,
|
|
UINT pdBufSizeBytes, UINT pdBufSize)
|
|
{
|
|
UINT i;
|
|
POLYDATA *pdBufSAVE;
|
|
GLuint pdBufSizeBytesSAVE;
|
|
GLuint pdBufSizeSAVE;
|
|
|
|
//
|
|
// Save current polyarray buffer. We are going to temporarily
|
|
// replace the current one with the new one for the purposes
|
|
// of initializing the buffer. However, it is too early to
|
|
// replace the current polyarray. The higher level code will
|
|
// figure that out later.
|
|
//
|
|
|
|
pdBufSAVE = gc->vertex.pdBuf;
|
|
pdBufSizeBytesSAVE = gc->vertex.pdBufSizeBytes;
|
|
pdBufSizeSAVE = gc->vertex.pdBufSize;
|
|
|
|
//
|
|
// Set polyarray buffer to memory allocated by MCD.
|
|
//
|
|
|
|
gc->vertex.pdBuf = pdBuf;
|
|
gc->vertex.pdBufSizeBytes = pdBufSizeBytes;
|
|
gc->vertex.pdBufSize = pdBufSize;
|
|
|
|
//
|
|
// Initialize the vertex buffer.
|
|
//
|
|
|
|
PolyArrayResetBuffer(gc);
|
|
|
|
//
|
|
// Restore the polyarray buffer.
|
|
//
|
|
|
|
gc->vertex.pdBuf = pdBufSAVE;
|
|
gc->vertex.pdBufSizeBytes = pdBufSizeBytesSAVE;
|
|
gc->vertex.pdBufSize = pdBufSizeSAVE;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdSetScaling
|
|
*
|
|
* Set up the various scale values needed for MCD or generic operation.
|
|
*
|
|
* This should be called when toggling between accelerated/non-accelerated
|
|
* operation.
|
|
*
|
|
* Returns:
|
|
* None.
|
|
*
|
|
* History:
|
|
* 03-May-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID FASTCALL GenMcdSetScaling(__GLGENcontext *gengc)
|
|
{
|
|
__GLcontext *gc = (__GLcontext *)gengc;
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
__GLviewport *vp = &gc->state.viewport;
|
|
double scale;
|
|
|
|
//
|
|
// If we're using MCD, set up the desired scale value:
|
|
//
|
|
|
|
if (pMcdState) {
|
|
if (pMcdState->McdRcInfo.requestFlags & MCDRCINFO_DEVZSCALE)
|
|
gengc->genAccel.zDevScale = pMcdState->McdRcInfo.zScale;
|
|
else
|
|
gengc->genAccel.zDevScale = pMcdState->McdRcInfo.depthBufferMax;
|
|
} else if (gengc->_pMcdState)
|
|
gengc->genAccel.zDevScale = gengc->_pMcdState->McdRcInfo.depthBufferMax;
|
|
|
|
if (pMcdState)
|
|
scale = gengc->genAccel.zDevScale * __glHalf;
|
|
else
|
|
scale = gc->depthBuffer.scale * __glHalf;
|
|
gc->state.viewport.zScale = (__GLfloat)((vp->zFar - vp->zNear) * scale);
|
|
gc->state.viewport.zCenter = (__GLfloat)((vp->zFar + vp->zNear) * scale);
|
|
|
|
if (pMcdState && pMcdState->McdRcInfo.requestFlags & MCDRCINFO_NOVIEWPORTADJUST) {
|
|
gc->constants.viewportXAdjust = 0;
|
|
gc->constants.viewportYAdjust = 0;
|
|
gc->constants.fviewportXAdjust = (__GLfloat)0.0;
|
|
gc->constants.fviewportYAdjust = (__GLfloat)0.0;
|
|
} else {
|
|
gc->constants.viewportXAdjust = __GL_VERTEX_X_BIAS + __GL_VERTEX_X_FIX;
|
|
gc->constants.viewportYAdjust = __GL_VERTEX_Y_BIAS + __GL_VERTEX_Y_FIX;
|
|
gc->constants.fviewportXAdjust = (__GLfloat)gc->constants.viewportXAdjust;
|
|
gc->constants.fviewportYAdjust = (__GLfloat)gc->constants.viewportYAdjust;
|
|
}
|
|
|
|
//
|
|
// The inverses for these are set in __glContextSetColorScales which is
|
|
// called on each MakeCurrent:
|
|
//
|
|
|
|
if (pMcdState && pMcdState->McdRcInfo.requestFlags & MCDRCINFO_DEVCOLORSCALE) {
|
|
gc->redVertexScale = pMcdState->McdRcInfo.redScale;
|
|
gc->greenVertexScale = pMcdState->McdRcInfo.greenScale;
|
|
gc->blueVertexScale = pMcdState->McdRcInfo.blueScale;
|
|
gc->alphaVertexScale = pMcdState->McdRcInfo.alphaScale;
|
|
} else {
|
|
if (gc->modes.colorIndexMode) {
|
|
gc->redVertexScale = (MCDFLOAT)1.0;
|
|
gc->greenVertexScale = (MCDFLOAT)1.0;
|
|
gc->blueVertexScale = (MCDFLOAT)1.0;
|
|
gc->alphaVertexScale = (MCDFLOAT)1.0;
|
|
} else {
|
|
gc->redVertexScale = (MCDFLOAT)((1 << gc->modes.redBits) - 1);
|
|
gc->greenVertexScale = (MCDFLOAT)((1 << gc->modes.greenBits) - 1);
|
|
gc->blueVertexScale = (MCDFLOAT)((1 << gc->modes.blueBits) - 1);
|
|
if( gc->modes.alphaBits )
|
|
gc->alphaVertexScale = (MCDFLOAT)((1 << gc->modes.alphaBits) - 1);
|
|
else
|
|
gc->alphaVertexScale = (MCDFLOAT)((1 << gc->modes.redBits) - 1);
|
|
}
|
|
}
|
|
|
|
gc->redClampTable[1] = gc->redVertexScale;
|
|
gc->redClampTable[2] = (__GLfloat)0.0;
|
|
gc->redClampTable[3] = (__GLfloat)0.0;
|
|
gc->greenClampTable[1] = gc->greenVertexScale;
|
|
gc->greenClampTable[2] = (__GLfloat)0.0;
|
|
gc->greenClampTable[3] = (__GLfloat)0.0;
|
|
gc->blueClampTable[1] = gc->blueVertexScale;
|
|
gc->blueClampTable[2] = (__GLfloat)0.0;
|
|
gc->blueClampTable[3] = (__GLfloat)0.0;
|
|
gc->alphaClampTable[1] = gc->alphaVertexScale;
|
|
gc->alphaClampTable[2] = (__GLfloat)0.0;
|
|
gc->alphaClampTable[3] = (__GLfloat)0.0;
|
|
|
|
if (pMcdState && pMcdState->McdRcInfo.requestFlags & MCDRCINFO_Y_LOWER_LEFT) {
|
|
gc->constants.yInverted = GL_FALSE;
|
|
gc->constants.ySign = 1;
|
|
} else {
|
|
gc->constants.yInverted = GL_TRUE;
|
|
gc->constants.ySign = -1;
|
|
}
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* McdPixelFormatFromPfd
|
|
*
|
|
* Fills out an MCDPIXELFORMAT from a PIXELFORMATDESCRIPTOR
|
|
*
|
|
* History:
|
|
* Mon Sep 16 14:51:42 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID FASTCALL McdPixelFormatFromPfd(PIXELFORMATDESCRIPTOR *pfd,
|
|
MCDPIXELFORMAT *mpf)
|
|
{
|
|
mpf->nSize = sizeof(MCDPIXELFORMAT);
|
|
mpf->dwFlags = pfd->dwFlags & (PFD_DOUBLEBUFFER |
|
|
PFD_NEED_PALETTE |
|
|
PFD_NEED_SYSTEM_PALETTE |
|
|
PFD_SWAP_EXCHANGE |
|
|
PFD_SWAP_COPY |
|
|
PFD_SWAP_LAYER_BUFFERS);
|
|
mpf->iPixelType = pfd->iPixelType;
|
|
mpf->cColorBits = pfd->cColorBits;
|
|
mpf->cRedBits = pfd->cRedBits;
|
|
mpf->cRedShift = pfd->cRedShift;
|
|
mpf->cGreenBits = pfd->cGreenBits;
|
|
mpf->cGreenShift = pfd->cGreenShift;
|
|
mpf->cBlueBits = pfd->cBlueBits;
|
|
mpf->cBlueShift = pfd->cBlueShift;
|
|
mpf->cAlphaBits = pfd->cAlphaBits;
|
|
mpf->cAlphaShift = pfd->cAlphaShift;
|
|
mpf->cDepthBits = pfd->cDepthBits;
|
|
mpf->cDepthShift = 0;
|
|
mpf->cDepthBufferBits = pfd->cDepthBits;
|
|
mpf->cStencilBits = pfd->cStencilBits;
|
|
mpf->cOverlayPlanes = pfd->bReserved & 0xf;
|
|
mpf->cUnderlayPlanes = pfd->bReserved >> 4;
|
|
mpf->dwTransparentColor = pfd->dwVisibleMask;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdResetViewportAdj
|
|
*
|
|
* If an MCD driver that specifies MCDRCINFO_NOVIEWPORTADJUST kicks back
|
|
* for simulations, we need to change the viewport adjust values from
|
|
* 0, 0 back to the default values in order to run the software
|
|
* implementation.
|
|
*
|
|
* If biasType is VP_FIXBIAS, this function will set the viewport adjust
|
|
* values to their software default.
|
|
*
|
|
* If biasType is VP_NOBIAS, this function will set the viewport adjust
|
|
* values to zero.
|
|
*
|
|
* Returns:
|
|
* TRUE is viewport is set, FALSE otherwise.
|
|
*
|
|
* Note:
|
|
* The main reason for returning a BOOL is so that caller can check if
|
|
* VP_FIXBIAS succeeds. If it does, it needs to reset values back to
|
|
* VP_NOBIAS.
|
|
*
|
|
* Also note that it is safe for non-MCD and MCD that does not set
|
|
* MCDRCINFO_NOVIEWPORTADJUST to call this function. This function
|
|
* will do nothing in these situations and will return FALSE.
|
|
*
|
|
* History:
|
|
* 22-May-1997 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdResetViewportAdj(__GLcontext *gc, VP_BIAS_TYPE biasType)
|
|
{
|
|
__GLGENcontext *gengc = (__GLGENcontext *) gc;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (gengc->pMcdState &&
|
|
(gengc->pMcdState->McdRcInfo.requestFlags & MCDRCINFO_NOVIEWPORTADJUST))
|
|
{
|
|
switch (biasType)
|
|
{
|
|
case VP_FIXBIAS:
|
|
if (gc->constants.viewportXAdjust == 0)
|
|
{
|
|
//
|
|
// The state of viewportYAdjust should match
|
|
// viewportXAdjust. If not, the test should be
|
|
// changed (perhaps state flag in the context to
|
|
// track biasing).
|
|
//
|
|
|
|
ASSERTOPENGL((gc->constants.viewportYAdjust == 0),
|
|
"GenMcdResetViewportAdj: "
|
|
"viewportYAdjust not zero\n");
|
|
|
|
gc->constants.viewportXAdjust = __GL_VERTEX_X_BIAS +
|
|
__GL_VERTEX_X_FIX;
|
|
gc->constants.viewportYAdjust = __GL_VERTEX_Y_BIAS +
|
|
__GL_VERTEX_Y_FIX;
|
|
gc->constants.fviewportXAdjust = (__GLfloat)gc->constants.viewportXAdjust;
|
|
gc->constants.fviewportYAdjust = (__GLfloat)gc->constants.viewportYAdjust;
|
|
|
|
//
|
|
// Apply new bias to the rasterPos.
|
|
//
|
|
|
|
gc->state.current.rasterPos.window.x += gc->constants.fviewportXAdjust;
|
|
gc->state.current.rasterPos.window.y += gc->constants.fviewportYAdjust;
|
|
}
|
|
bRet = TRUE;
|
|
break;
|
|
|
|
case VP_NOBIAS:
|
|
if (gc->constants.viewportXAdjust != 0)
|
|
{
|
|
//
|
|
// The state of viewportYAdjust should match
|
|
// viewportXAdjust. If not, the test should be
|
|
// changed (perhaps state flag in the context to
|
|
// track biasing).
|
|
//
|
|
|
|
ASSERTOPENGL((gc->constants.viewportYAdjust != 0),
|
|
"GenMcdResetViewportAdj: "
|
|
"viewportYAdjust zero\n");
|
|
|
|
//
|
|
// Remove bias from the rasterPos before resetting.
|
|
//
|
|
|
|
gc->state.current.rasterPos.window.x -= gc->constants.fviewportXAdjust;
|
|
gc->state.current.rasterPos.window.y -= gc->constants.fviewportYAdjust;
|
|
|
|
gc->constants.viewportXAdjust = 0;
|
|
gc->constants.viewportYAdjust = 0;
|
|
gc->constants.fviewportXAdjust = (__GLfloat)0.0;
|
|
gc->constants.fviewportYAdjust = (__GLfloat)0.0;
|
|
}
|
|
bRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
DBGPRINT("GenMcdResetViewportAdj: unknown type\n");
|
|
break;
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
__GLbeginMode beginMode = gc->beginMode;
|
|
|
|
//
|
|
// Why save/restore beginMode?
|
|
//
|
|
// Because we are playing around with the viewport values,
|
|
// ApplyViewport may inadvertently set beginMode to
|
|
// __GL_NEED_VALIDATE even though we will later restore the
|
|
// original viewport values. This can confuse glim_DrawPolyArray
|
|
// which plays around with the beginMode settings.
|
|
//
|
|
|
|
__glUpdateViewport(gc);
|
|
(gc->procs.applyViewport)(gc);
|
|
__glUpdateViewportDependents(gc);
|
|
|
|
gc->beginMode = beginMode;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bInitMcdContext
|
|
*
|
|
* Allocate and initialize the GENMCDSTATE structure. Create MCD context
|
|
* and shared memory buffers used to pass vertex arrays, commands, and state.
|
|
*
|
|
* This state exists per-context.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
* In addition, the gengc->pMcdState is valid IFF successful.
|
|
*
|
|
* History:
|
|
* 05-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL bInitMcdContext(__GLGENcontext *gengc, GLGENwindow *pwnd)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
__GLcontext *gc = &gengc->gc;
|
|
GENMCDSTATE *pMcdState = (GENMCDSTATE *) NULL;
|
|
ULONG ulBytes;
|
|
UINT nVertices;
|
|
UINT pdBufSize;
|
|
POLYDATA *pd;
|
|
DWORD dwFlags;
|
|
MCDRCINFOPRIV mriPriv;
|
|
|
|
//
|
|
// This functions cannot assume MCD entry point table is already
|
|
// initialized.
|
|
//
|
|
|
|
if (!bInitMcd(gengc->gsurf.hdc))
|
|
{
|
|
goto bInitMcdContext_exit;
|
|
}
|
|
|
|
//
|
|
// Fail if not an MCD pixelformat.
|
|
//
|
|
|
|
if (!(gengc->gsurf.pfd.dwFlags & PFD_GENERIC_ACCELERATED))
|
|
{
|
|
goto bInitMcdContext_exit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for our MCD state.
|
|
//
|
|
|
|
pMcdState = (GENMCDSTATE *)ALLOCZ(sizeof(*gengc->pMcdState));
|
|
|
|
if (pMcdState)
|
|
{
|
|
//
|
|
// Create an MCD context.
|
|
//
|
|
|
|
//
|
|
// Pickup viewportXAdjust and viewportYAdjust from the constants section
|
|
// of the gc.
|
|
//
|
|
|
|
pMcdState->McdRcInfo.viewportXAdjust = gengc->gc.constants.viewportXAdjust;
|
|
pMcdState->McdRcInfo.viewportYAdjust = gengc->gc.constants.viewportYAdjust;
|
|
|
|
if (!gengc->gsurf.pfd.cDepthBits || (gengc->gsurf.pfd.cDepthBits >= 32))
|
|
pMcdState->McdRcInfo.depthBufferMax = ~((ULONG)0);
|
|
else
|
|
pMcdState->McdRcInfo.depthBufferMax = (1 << gengc->gsurf.pfd.cDepthBits) - 1;
|
|
|
|
//!!!
|
|
//!!! This is broken since we can't use the full z-buffer range!
|
|
//!!!
|
|
|
|
pMcdState->McdRcInfo.depthBufferMax >>= 1;
|
|
|
|
pMcdState->McdRcInfo.zScale = (MCDDOUBLE)pMcdState->McdRcInfo.depthBufferMax;
|
|
|
|
//
|
|
// This is also computed by initCi/initRGB, but this function
|
|
// is called before the color buffers are initialized:
|
|
//
|
|
|
|
if (gc->modes.colorIndexMode)
|
|
{
|
|
pMcdState->McdRcInfo.redScale = (MCDFLOAT)1.0;
|
|
pMcdState->McdRcInfo.greenScale = (MCDFLOAT)1.0;
|
|
pMcdState->McdRcInfo.blueScale = (MCDFLOAT)1.0;
|
|
pMcdState->McdRcInfo.alphaScale = (MCDFLOAT)1.0;
|
|
}
|
|
else
|
|
{
|
|
pMcdState->McdRcInfo.redScale = (MCDFLOAT)((1 << gc->modes.redBits) - 1);
|
|
pMcdState->McdRcInfo.greenScale = (MCDFLOAT)((1 << gc->modes.greenBits) - 1);
|
|
pMcdState->McdRcInfo.blueScale = (MCDFLOAT)((1 << gc->modes.blueBits) - 1);
|
|
pMcdState->McdRcInfo.alphaScale = (MCDFLOAT)((1 << gc->modes.redBits) - 1);
|
|
}
|
|
|
|
dwFlags = 0;
|
|
|
|
// Consider - Extract clipper-associated hwnds? Whole clipping
|
|
// scheme is broken until clipper data can be accessed in kernel.
|
|
if ((gengc->gsurf.dwFlags & GLSURF_DIRECTDRAW) == 0)
|
|
{
|
|
dwFlags |= MCDSURFACE_HWND;
|
|
}
|
|
else
|
|
{
|
|
// Cache kernel-mode surface handles for DirectDraw
|
|
// This must occur before the call to MCDCreateContext
|
|
pMcdState->hDdColor = (HANDLE)
|
|
((LPDDRAWI_DDRAWSURFACE_INT)gengc->gsurf.dd.gddsFront.pdds)->
|
|
lpLcl->hDDSurface;
|
|
if (gengc->gsurf.dd.gddsZ.pdds != NULL)
|
|
{
|
|
pMcdState->hDdDepth = (HANDLE)
|
|
((LPDDRAWI_DDRAWSURFACE_INT)gengc->gsurf.dd.gddsZ.pdds)->
|
|
lpLcl->hDDSurface;
|
|
}
|
|
}
|
|
|
|
if (SUPPORTS_DIRECT())
|
|
{
|
|
dwFlags |= MCDSURFACE_DIRECT;
|
|
}
|
|
|
|
mriPriv.mri = pMcdState->McdRcInfo;
|
|
if (!(gpMcdTable->pMCDCreateContext)(&pMcdState->McdContext,
|
|
&mriPriv,
|
|
&gengc->gsurf,
|
|
pwnd->ipfd - pwnd->ipfdDevMax,
|
|
dwFlags))
|
|
{
|
|
WARNING("bInitMcdContext: MCDCreateContext failed\n");
|
|
goto bInitMcdContext_exit;
|
|
}
|
|
|
|
pMcdState->McdRcInfo = mriPriv.mri;
|
|
|
|
//
|
|
// Get MCDPIXELFORMAT and cache in GENMCDSTATE.
|
|
//
|
|
|
|
if (gengc->gsurf.dwFlags & GLSURF_DIRECTDRAW)
|
|
{
|
|
McdPixelFormatFromPfd(&gengc->gsurf.pfd, &pMcdState->McdPixelFmt);
|
|
}
|
|
else if (!(gpMcdTable->pMCDDescribeMcdPixelFormat)
|
|
(gengc->gsurf.hdc,
|
|
pwnd->ipfd - pwnd->ipfdDevMax,
|
|
&pMcdState->McdPixelFmt))
|
|
{
|
|
WARNING("bInitMcdContext: MCDDescribeMcdPixelFormat failed\n");
|
|
goto bInitMcdContext_exit;
|
|
}
|
|
|
|
//
|
|
// Allocate cmd/state buffer.
|
|
//
|
|
|
|
//!!!mcd -- How much memory should be allocated for cmd buffer?
|
|
//!!!mcd Use a page (4K) for now...
|
|
ulBytes = 4096;
|
|
pMcdState->McdCmdBatch.size = ulBytes;
|
|
pMcdState->McdCmdBatch.pv =
|
|
(gpMcdTable->pMCDAlloc)(&pMcdState->McdContext, ulBytes,
|
|
&pMcdState->McdCmdBatch.hmem, 0);
|
|
|
|
if (!pMcdState->McdCmdBatch.pv)
|
|
{
|
|
WARNING("bInitMcdContext: state buf MCDAlloc failed\n");
|
|
goto bInitMcdContext_exit;
|
|
}
|
|
|
|
//
|
|
// Determine size of vertex buffer we should use with MCD driver.
|
|
// This is calculated by taking the size the MCD driver requests
|
|
// and computing the number of POLYDATA structure that will fit.
|
|
// If the result is less than the minimum size required by the
|
|
// generic software implementation, bump it up to the minimum.
|
|
//
|
|
|
|
ulBytes = McdDriverInfo.mcdDriverInfo.drvBatchMemSizeMax;
|
|
nVertices = ulBytes / sizeof(POLYDATA);
|
|
|
|
if (nVertices < MINIMUM_POLYDATA_BUFFER_SIZE)
|
|
{
|
|
ulBytes = MINIMUM_POLYDATA_BUFFER_SIZE * sizeof(POLYDATA);
|
|
nVertices = MINIMUM_POLYDATA_BUFFER_SIZE;
|
|
}
|
|
|
|
//
|
|
// Only n-1 vertices are used for the buffer. The "extra" is
|
|
// reserved for use by the polyarray code (see PolyArrayAllocBuf
|
|
// in so_prim.c).
|
|
//
|
|
|
|
pdBufSize = nVertices - 1;
|
|
|
|
//
|
|
// Allocate vertex buffers.
|
|
//
|
|
|
|
if (McdDriverInfo.mcdDriverInfo.drvMemFlags & MCDRV_MEM_DMA)
|
|
{
|
|
pMcdState->McdBuf2.size = ulBytes;
|
|
pMcdState->McdBuf2.pv =
|
|
(gpMcdTable->pMCDAlloc)(&pMcdState->McdContext, ulBytes,
|
|
&pMcdState->McdBuf2.hmem, 0);
|
|
|
|
if (pMcdState->McdBuf2.pv)
|
|
{
|
|
//
|
|
// Configure memory buffer as a POLYDATA buffer.
|
|
//
|
|
|
|
vInitPolyArrayBuffer(gc, (POLYDATA *) pMcdState->McdBuf2.pv,
|
|
ulBytes, pdBufSize);
|
|
}
|
|
else
|
|
{
|
|
WARNING("bInitMcdContext: 2nd MCDAlloc failed\n");
|
|
goto bInitMcdContext_exit;
|
|
}
|
|
}
|
|
|
|
pMcdState->McdBuf1.size = ulBytes;
|
|
pMcdState->McdBuf1.pv =
|
|
(gpMcdTable->pMCDAlloc)(&pMcdState->McdContext, ulBytes,
|
|
&pMcdState->McdBuf1.hmem, 0);
|
|
|
|
if (pMcdState->McdBuf1.pv)
|
|
{
|
|
pMcdState->pMcdPrimBatch = &pMcdState->McdBuf1;
|
|
|
|
//
|
|
// Configure memory buffer as a POLYDATA buffer.
|
|
//
|
|
|
|
vInitPolyArrayBuffer(gc, (POLYDATA *) pMcdState->McdBuf1.pv,
|
|
ulBytes, pdBufSize);
|
|
|
|
//
|
|
// Free current poly array buffer.
|
|
//
|
|
// If we fail after this, we must call PolyArrayAllocBuffer to
|
|
// restore the poly array buffer. Luckily, at this point we
|
|
// are guaranteed not fail.
|
|
//
|
|
|
|
PolyArrayFreeBuffer(gc);
|
|
|
|
//
|
|
// Set poly array buffer to memory allocated by MCD.
|
|
//
|
|
|
|
gc->vertex.pdBuf = (POLYDATA *) pMcdState->pMcdPrimBatch->pv;
|
|
gc->vertex.pdBufSizeBytes = ulBytes;
|
|
gc->vertex.pdBufSize = pdBufSize;
|
|
}
|
|
else
|
|
{
|
|
WARNING("bInitMcdContext: MCDAlloc failed\n");
|
|
goto bInitMcdContext_exit;
|
|
}
|
|
|
|
if (pwnd->dwMcdWindow == 0)
|
|
{
|
|
//
|
|
// Save MCD server-side window handle in the GENwindow
|
|
//
|
|
|
|
pwnd->dwMcdWindow = mriPriv.dwMcdWindow;
|
|
}
|
|
else
|
|
{
|
|
ASSERTOPENGL(pwnd->dwMcdWindow == mriPriv.dwMcdWindow,
|
|
"dwMcdWindow mismatch\n");
|
|
}
|
|
|
|
//
|
|
// Finally, success.
|
|
//
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
bInitMcdContext_exit:
|
|
|
|
//
|
|
// If function failed, cleanup allocated resources.
|
|
//
|
|
|
|
if (!bRet)
|
|
{
|
|
if (pMcdState)
|
|
{
|
|
if (pMcdState->McdBuf1.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&pMcdState->McdContext, pMcdState->McdBuf1.pv);
|
|
}
|
|
|
|
if (pMcdState->McdBuf2.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&pMcdState->McdContext, pMcdState->McdBuf2.pv);
|
|
}
|
|
|
|
if (pMcdState->McdCmdBatch.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&pMcdState->McdContext, pMcdState->McdCmdBatch.pv);
|
|
}
|
|
|
|
if (pMcdState->McdContext.hMCDContext)
|
|
{
|
|
(gpMcdTable->pMCDDeleteContext)(&pMcdState->McdContext);
|
|
}
|
|
|
|
FREE(pMcdState);
|
|
}
|
|
gengc->_pMcdState = (GENMCDSTATE *) NULL;
|
|
}
|
|
else
|
|
{
|
|
gengc->_pMcdState = pMcdState;
|
|
|
|
//
|
|
// For generic formats, the depth resolution (i.e., number of
|
|
// active depth bits) and the depth "pixel stride" are the same.
|
|
// So GetContextModes, which sets modes.depthBits, can use the
|
|
// PIXELFORMATDESCRIPTOR.cDepthBits for generic pixel formats.
|
|
//
|
|
// However, these two quantities can differ for MCD, so we need
|
|
// to set it to cDepthBufferBits once we know that this is an
|
|
// MCD context.
|
|
//
|
|
|
|
if (gengc->_pMcdState)
|
|
gengc->gc.modes.depthBits = gengc->_pMcdState->McdPixelFmt.cDepthBufferBits;
|
|
}
|
|
|
|
gengc->pMcdState = (GENMCDSTATE *) NULL;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bInitMcdSurface
|
|
*
|
|
* Allocate and initialize the GENMCDSURFACE structure. This includes
|
|
* creating shared span buffers to read/write the MCD front, back and depth
|
|
* buffers.
|
|
*
|
|
* The MCDBUFFERS structure, which describes the location of the MCD buffers
|
|
* (if directly accessible), is left zero-initialized. The contents of this
|
|
* structure are only valid when the screen lock is held and must be reset each
|
|
* time direct screen access is started.
|
|
*
|
|
* This function, if successful, will also bind the MCD context to the MCD
|
|
* surface.
|
|
*
|
|
* This state exists per-window.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
* In addition, the gengc->pMcdState is valid IFF successful.
|
|
*
|
|
* History:
|
|
* 05-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL bInitMcdSurface(__GLGENcontext *gengc, GLGENwindow *pwnd,
|
|
__GLGENbuffers *buffers)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
__GLcontext *gc = &gengc->gc;
|
|
GENMCDSTATE *pMcdState;
|
|
GENMCDSURFACE *pMcdSurf = (GENMCDSURFACE *) NULL;
|
|
ULONG ulBytes;
|
|
UINT nVertices;
|
|
POLYDATA *pd;
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "bInitMcdSurface: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Fail if no MCD context.
|
|
//
|
|
|
|
if (!(pMcdState = gengc->_pMcdState))
|
|
{
|
|
goto bInitMcdSurface_exit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for our MCD surface.
|
|
//
|
|
|
|
pMcdSurf = (GENMCDSURFACE *)ALLOCZ(sizeof(*buffers->pMcdSurf));
|
|
|
|
if (pMcdSurf)
|
|
{
|
|
//
|
|
// Remember the window this surface is bound to.
|
|
//
|
|
|
|
pMcdSurf->pwnd = pwnd;
|
|
|
|
//
|
|
// Allocate scanline depth buffer. Used to read/write depth buffer
|
|
// spans.
|
|
//
|
|
|
|
if (pMcdState->McdPixelFmt.cDepthBits)
|
|
{
|
|
pMcdSurf->McdDepthBuf.size =
|
|
MCD_MAX_SCANLINE * ((pMcdState->McdPixelFmt.cDepthBufferBits + 7) >> 3);
|
|
pMcdSurf->McdDepthBuf.pv =
|
|
(gpMcdTable->pMCDAlloc)(&pMcdState->McdContext,
|
|
pMcdSurf->McdDepthBuf.size,
|
|
&pMcdSurf->McdDepthBuf.hmem, 0);
|
|
|
|
if (!pMcdSurf->McdDepthBuf.pv)
|
|
{
|
|
WARNING("bInitMcdSurface: MCDAlloc depth buf failed\n");
|
|
goto bInitMcdSurface_exit;
|
|
}
|
|
|
|
//
|
|
// A 32-bit depth span is required by generic implementation for
|
|
// simulations. If cDepthBufferBits < 32, then we need to allocate
|
|
// a separate buffer to do the conversion.
|
|
//
|
|
|
|
if (pMcdState->McdPixelFmt.cDepthBufferBits < 32)
|
|
{
|
|
pMcdSurf->pDepthSpan =
|
|
(__GLzValue *)ALLOC(sizeof(__GLzValue) * MCD_MAX_SCANLINE);
|
|
|
|
if (!pMcdSurf->pDepthSpan)
|
|
{
|
|
WARNING("bInitMcdSurface: malloc depth buf failed\n");
|
|
goto bInitMcdSurface_exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pMcdSurf->pDepthSpan = (__GLzValue *) pMcdSurf->McdDepthBuf.pv;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pMcdSurf->McdDepthBuf.pv = (PVOID) NULL;
|
|
pMcdSurf->pDepthSpan = (PVOID) NULL;
|
|
}
|
|
|
|
pMcdSurf->depthBitMask = (~0) << (32 - pMcdState->McdPixelFmt.cDepthBits);
|
|
|
|
//
|
|
// Allocate scanline color buffer. Used to read/write front/back
|
|
// buffer spans.
|
|
//
|
|
|
|
pMcdSurf->McdColorBuf.size =
|
|
MCD_MAX_SCANLINE * ((pMcdState->McdPixelFmt.cColorBits + 7) >> 3);
|
|
pMcdSurf->McdColorBuf.pv =
|
|
(gpMcdTable->pMCDAlloc)(&pMcdState->McdContext,
|
|
pMcdSurf->McdColorBuf.size,
|
|
&pMcdSurf->McdColorBuf.hmem, 0);
|
|
|
|
if (!pMcdSurf->McdColorBuf.pv)
|
|
{
|
|
WARNING("bInitMcdSurface: MCDAlloc color buf failed\n");
|
|
goto bInitMcdSurface_exit;
|
|
}
|
|
|
|
//
|
|
// Finally, success.
|
|
//
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
bInitMcdSurface_exit:
|
|
|
|
//
|
|
// If function failed, cleanup allocated resources.
|
|
//
|
|
|
|
if (!bRet)
|
|
{
|
|
if (pMcdSurf)
|
|
{
|
|
if (pMcdSurf->McdColorBuf.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&pMcdState->McdContext, pMcdSurf->McdColorBuf.pv);
|
|
}
|
|
|
|
if (pMcdSurf->pDepthSpan != pMcdSurf->McdDepthBuf.pv)
|
|
{
|
|
FREE(pMcdSurf->pDepthSpan);
|
|
}
|
|
|
|
if (pMcdSurf->McdDepthBuf.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&pMcdState->McdContext, pMcdSurf->McdDepthBuf.pv);
|
|
}
|
|
|
|
FREE(pMcdSurf);
|
|
buffers->pMcdSurf = (GENMCDSURFACE *) NULL;
|
|
pMcdState->pMcdSurf = (GENMCDSURFACE *) NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Surface created. Save it in the __GLGENbuffers.
|
|
//
|
|
|
|
buffers->pMcdSurf = pMcdSurf;
|
|
|
|
//
|
|
// Bind the context to the surface.
|
|
// Sounds fancy, but it really just means save a copy of pointer
|
|
// (and a copy of the pDepthSpan for convenience).
|
|
//
|
|
|
|
pMcdState->pMcdSurf = pMcdSurf;
|
|
pMcdState->pDepthSpan = pMcdSurf->pDepthSpan;
|
|
|
|
//
|
|
// MCD state is now fully created and bound to a surface.
|
|
// OK to connect pMcdState to the _pMcdState.
|
|
//
|
|
|
|
gengc->pMcdState = gengc->_pMcdState;
|
|
gengc->pMcdState->mcdFlags |= (MCD_STATE_FORCEPICK | MCD_STATE_FORCERESIZE);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdDeleteContext
|
|
*
|
|
* Delete the resources belonging to the MCD context (including the context).
|
|
*
|
|
* History:
|
|
* 16-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdDeleteContext(GENMCDSTATE *pMcdState)
|
|
{
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdDeleteContext: mcd32.dll not initialized\n");
|
|
|
|
if (pMcdState)
|
|
{
|
|
if (pMcdState->McdBuf1.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&pMcdState->McdContext, pMcdState->McdBuf1.pv);
|
|
}
|
|
|
|
if (pMcdState->McdBuf2.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&pMcdState->McdContext, pMcdState->McdBuf2.pv);
|
|
}
|
|
|
|
if (pMcdState->McdCmdBatch.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&pMcdState->McdContext, pMcdState->McdCmdBatch.pv);
|
|
}
|
|
|
|
if (pMcdState->McdContext.hMCDContext)
|
|
{
|
|
(gpMcdTable->pMCDDeleteContext)(&pMcdState->McdContext);
|
|
}
|
|
|
|
FREE(pMcdState);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdDeleteSurface
|
|
*
|
|
* Delete the resources belonging to the MCD surface.
|
|
*
|
|
* History:
|
|
* 16-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdDeleteSurface(GENMCDSURFACE *pMcdSurf)
|
|
{
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdDeleteSurface: mcd32.dll not initialized\n");
|
|
|
|
if (pMcdSurf)
|
|
{
|
|
MCDCONTEXT McdContext;
|
|
|
|
//
|
|
// If a separate depth interchange buffer was allocated, delete it.
|
|
//
|
|
|
|
if (pMcdSurf->pDepthSpan != pMcdSurf->McdDepthBuf.pv)
|
|
{
|
|
FREE(pMcdSurf->pDepthSpan);
|
|
}
|
|
|
|
//
|
|
// A valid McdContext is not guaranteed to exist at the time this function
|
|
// is called. Therefore, need to fake up an McdContext with which to call
|
|
// MCDFree. Currently, the only thing in the McdContext that needs to be
|
|
// valid in order to call MCDFree is the hdc field.
|
|
//
|
|
|
|
memset(&McdContext, 0, sizeof(McdContext));
|
|
|
|
if (pMcdSurf->pwnd->gwid.iType == GLWID_DDRAW)
|
|
{
|
|
McdContext.hdc = pMcdSurf->pwnd->gwid.hdc;
|
|
}
|
|
else
|
|
{
|
|
McdContext.hdc = GetDC(pMcdSurf->pwnd->gwid.hwnd);
|
|
}
|
|
if (McdContext.hdc)
|
|
{
|
|
if (pMcdSurf->McdColorBuf.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&McdContext, pMcdSurf->McdColorBuf.pv);
|
|
}
|
|
|
|
if (pMcdSurf->McdDepthBuf.pv)
|
|
{
|
|
(gpMcdTable->pMCDFree)(&McdContext, pMcdSurf->McdDepthBuf.pv);
|
|
}
|
|
|
|
if (pMcdSurf->pwnd->gwid.iType != GLWID_DDRAW)
|
|
{
|
|
ReleaseDC(pMcdSurf->pwnd->gwid.hwnd, McdContext.hdc);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete the GENMCDSURFACE structure.
|
|
//
|
|
|
|
FREE(pMcdSurf);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdMakeCurrent
|
|
*
|
|
* Call MCD driver to bind specified context to window.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* History:
|
|
* 03-Apr-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdMakeCurrent(__GLGENcontext *gengc, GLGENwindow *pwnd)
|
|
{
|
|
BOOL bRet;
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdMakeCurrent: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdMakeCurrent: mcd32.dll not initialized\n");
|
|
|
|
bRet = (gpMcdTable->pMCDBindContext)(&pMcdState->McdContext,
|
|
gengc->gwidCurrent.hdc, pwnd);
|
|
|
|
//
|
|
// Fake up some of the __GLGENbitmap information. The WNDOBJ is required
|
|
// for clipping of the hardware back buffer. The hdc is required to
|
|
// retrieve drawing data from GDI.
|
|
//
|
|
|
|
if (gengc->gc.modes.doubleBufferMode)
|
|
{
|
|
__GLGENbitmap *genBm = gengc->gc.back->bitmap;
|
|
|
|
ASSERT_WINCRIT(gengc->pwndLocked);
|
|
genBm->pwnd = gengc->pwndLocked;
|
|
genBm->hdc = gengc->gwidCurrent.hdc;
|
|
}
|
|
|
|
#if DBG
|
|
if (!bRet)
|
|
{
|
|
WARNING2("GenMcdMakeCurrent: MCDBindContext failed\n"
|
|
"\tpMcdCx = 0x%08lx, pwnd = 0x%08lx\n",
|
|
&pMcdState->McdContext, pwnd);
|
|
}
|
|
#endif
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdClear
|
|
*
|
|
* Call MCD driver to clear specified buffers. The buffers are specified by
|
|
* the masked pointed to by pClearMask.
|
|
*
|
|
* There is no function return value, but the function will clear the mask
|
|
* bits of the buffers it successfully cleared.
|
|
*
|
|
* History:
|
|
* 06-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdClear(__GLGENcontext *gengc, ULONG *pClearMask)
|
|
{
|
|
RECTL rcl;
|
|
ULONG mask;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdClear: null pMcdState\n");
|
|
|
|
//
|
|
// If MCD format supports stencil, include GL_STENCIL_BUFFER_BIT in
|
|
// the mask.
|
|
//
|
|
|
|
if (gengc->pMcdState->McdPixelFmt.cStencilBits)
|
|
{
|
|
mask = *pClearMask & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
|
|
GL_STENCIL_BUFFER_BIT);
|
|
}
|
|
else
|
|
{
|
|
mask = *pClearMask & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdClear: mcd32.dll not initialized\n");
|
|
|
|
if ( mask )
|
|
{
|
|
GLGENwindow *pwnd = gengc->pwndLocked;
|
|
|
|
//
|
|
// Determine the clear rectangle. If there is any window clipping
|
|
// or scissoring, the driver will have to handle it.
|
|
//
|
|
|
|
rcl.left = 0;
|
|
rcl.top = 0;
|
|
rcl.right = pwnd->rclClient.right - pwnd->rclClient.left;
|
|
rcl.bottom = pwnd->rclClient.bottom - pwnd->rclClient.top;
|
|
|
|
if ((rcl.left != rcl.right) && (rcl.top != rcl.bottom))
|
|
{
|
|
//
|
|
// Before calling MCD to draw, flush state.
|
|
//
|
|
|
|
vFlushDirtyState(gengc);
|
|
|
|
if ( (gpMcdTable->pMCDClear)(&gengc->pMcdState->McdContext, rcl,
|
|
mask) )
|
|
{
|
|
//
|
|
// Successful, so clear the bits of the buffers we
|
|
// handled.
|
|
//
|
|
|
|
*pClearMask &= ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
//
|
|
// Stencil buffer is supplied by generic if MCD does not
|
|
// support it. Therefore, clear this bit if and only if
|
|
// supported by MCD.
|
|
//
|
|
|
|
if (gengc->pMcdState->McdPixelFmt.cStencilBits)
|
|
*pClearMask &= ~GL_STENCIL_BUFFER_BIT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdCopyPixels
|
|
*
|
|
* Copy span scanline buffer to/from display. Direction is determined by
|
|
* the flag bIn (if bIn is TRUE, copy from color span buffer to display;
|
|
* otherwise, copy from display to color span buffer).
|
|
*
|
|
* History:
|
|
* 14-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void GenMcdCopyPixels(__GLGENcontext *gengc, __GLcolorBuffer *cfb,
|
|
GLint x, GLint y, GLint cx, BOOL bIn)
|
|
{
|
|
GENMCDSTATE *pMcdState;
|
|
GENMCDSURFACE *pMcdSurf;
|
|
ULONG ulType;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdCopyPixels: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdCopyPixels: mcd32.dll not initialized\n");
|
|
|
|
pMcdState = gengc->pMcdState;
|
|
pMcdSurf = pMcdState->pMcdSurf;
|
|
|
|
//
|
|
// Clip the length of the span to the scanline buffer size.
|
|
//
|
|
|
|
//!!!mcd -- should we just enforce the buffer limit?
|
|
//cx = min(cx, MCD_MAX_SCANLINE);
|
|
#if DBG
|
|
if (cx > gengc->gc.constants.width)
|
|
WARNING2("GenMcdCopyPixels: cx (%ld) bigger than window width (%ld)\n", cx, gengc->gc.constants.width);
|
|
ASSERTOPENGL(cx <= MCD_MAX_SCANLINE, "GenMcdCopyPixels: cx exceeds buffer width\n");
|
|
#endif
|
|
|
|
//
|
|
// Convert screen coordinates to window coordinates.
|
|
//
|
|
|
|
if (cfb == gengc->gc.front)
|
|
{
|
|
ulType = MCDSPAN_FRONT;
|
|
x -= gengc->gc.frontBuffer.buf.xOrigin;
|
|
y -= gengc->gc.frontBuffer.buf.yOrigin;
|
|
}
|
|
else
|
|
{
|
|
ulType = MCDSPAN_BACK;
|
|
x -= gengc->gc.backBuffer.buf.xOrigin;
|
|
y -= gengc->gc.backBuffer.buf.yOrigin;
|
|
}
|
|
|
|
//
|
|
// If bIn, copy from the scanline buffer to the MCD buffer.
|
|
// Otherwise, copy from the MCD buffer into the scanline buffer.
|
|
//
|
|
|
|
if ( bIn )
|
|
{
|
|
if ( !(gpMcdTable->pMCDWriteSpan)(&pMcdState->McdContext,
|
|
pMcdSurf->McdColorBuf.pv,
|
|
x, y, cx, ulType) )
|
|
{
|
|
WARNING3("GenMcdCopyPixels: MCDWriteSpan failed (%ld, %ld) %ld\n", x, y, cx);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !(gpMcdTable->pMCDReadSpan)(&pMcdState->McdContext,
|
|
pMcdSurf->McdColorBuf.pv,
|
|
x, y, cx, ulType) )
|
|
{
|
|
WARNING3("GenMcdCopyPixels: MCDReadSpan failed (%ld, %ld) %ld\n", x, y, cx);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateRenderState
|
|
*
|
|
* Update MCD render state from the OpenGL state.
|
|
*
|
|
* This call only adds a state structure to the current state command.
|
|
* It is assumed that the caller has already called MCDBeginState and
|
|
* will call MCDFlushState.
|
|
*
|
|
* History:
|
|
* 08-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdUpdateRenderState(__GLGENcontext *gengc)
|
|
{
|
|
__GLcontext *gc = &gengc->gc;
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
MCDRENDERSTATE McdRenderState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdUpdateRenderState: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdateRenderState: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Compute MCD state from the current OpenGL context state.
|
|
//
|
|
|
|
//
|
|
// -=<< State Enables >>=-
|
|
//
|
|
|
|
McdRenderState.enables = gc->state.enables.general;
|
|
|
|
//
|
|
// -=<< Texture State >>=-
|
|
//
|
|
|
|
McdRenderState.textureEnabled = gc->texture.textureEnabled;
|
|
|
|
//
|
|
// -=<< Fog State >>=-
|
|
//
|
|
|
|
*((__GLcolor *) &McdRenderState.fogColor) = gc->state.fog.color;
|
|
McdRenderState.fogIndex = gc->state.fog.index;
|
|
McdRenderState.fogDensity = gc->state.fog.density;
|
|
McdRenderState.fogStart = gc->state.fog.start;
|
|
McdRenderState.fogEnd = gc->state.fog.end;
|
|
McdRenderState.fogMode = gc->state.fog.mode;
|
|
|
|
//
|
|
// -=<< Shading Model State >>=-
|
|
//
|
|
|
|
McdRenderState.shadeModel = gc->state.light.shadingModel;
|
|
|
|
//
|
|
// -=<< Point Drawing State >>=-
|
|
//
|
|
|
|
McdRenderState.pointSize = gc->state.point.requestedSize;
|
|
|
|
//
|
|
// -=<< Line Drawing State >>=-
|
|
//
|
|
|
|
McdRenderState.lineWidth = gc->state.line.requestedWidth;
|
|
McdRenderState.lineStipplePattern = gc->state.line.stipple;
|
|
McdRenderState.lineStippleRepeat = gc->state.line.stippleRepeat;
|
|
|
|
//
|
|
// -=<< Polygon Drawing State >>=-
|
|
//
|
|
|
|
McdRenderState.cullFaceMode = gc->state.polygon.cull;
|
|
McdRenderState.frontFace = gc->state.polygon.frontFaceDirection;
|
|
McdRenderState.polygonModeFront = gc->state.polygon.frontMode;
|
|
McdRenderState.polygonModeBack = gc->state.polygon.backMode;
|
|
memcpy(&McdRenderState.polygonStipple, &gc->state.polygonStipple.stipple,
|
|
sizeof(McdRenderState.polygonStipple));
|
|
McdRenderState.zOffsetFactor = gc->state.polygon.factor;
|
|
McdRenderState.zOffsetUnits = gc->state.polygon.units;
|
|
|
|
//
|
|
// -=<< Stencil Test State >>=-
|
|
//
|
|
|
|
McdRenderState.stencilTestFunc = gc->state.stencil.testFunc;
|
|
McdRenderState.stencilMask = (USHORT) gc->state.stencil.mask;
|
|
McdRenderState.stencilRef = (USHORT) gc->state.stencil.reference;
|
|
McdRenderState.stencilFail = gc->state.stencil.fail;
|
|
McdRenderState.stencilDepthFail = gc->state.stencil.depthFail;
|
|
McdRenderState.stencilDepthPass = gc->state.stencil.depthPass;
|
|
|
|
//
|
|
// -=<< Alpha Test State >>=-
|
|
//
|
|
|
|
McdRenderState.alphaTestFunc = gc->state.raster.alphaFunction;
|
|
McdRenderState.alphaTestRef = gc->state.raster.alphaReference;
|
|
|
|
//
|
|
// -=<< Depth Test State >>=-
|
|
//
|
|
|
|
McdRenderState.depthTestFunc = gc->state.depth.testFunc;
|
|
|
|
//
|
|
// -=<< Blend State >>=-
|
|
//
|
|
|
|
McdRenderState.blendSrc = gc->state.raster.blendSrc;
|
|
McdRenderState.blendDst = gc->state.raster.blendDst;
|
|
|
|
//
|
|
// -=<< Logic Op State >>=-
|
|
//
|
|
|
|
McdRenderState.logicOpMode = gc->state.raster.logicOp;
|
|
|
|
//
|
|
// -=<< Frame Buffer Control State >>=-
|
|
//
|
|
|
|
McdRenderState.drawBuffer = gc->state.raster.drawBuffer;
|
|
McdRenderState.indexWritemask = gc->state.raster.writeMask;
|
|
McdRenderState.colorWritemask[0] = gc->state.raster.rMask;
|
|
McdRenderState.colorWritemask[1] = gc->state.raster.gMask;
|
|
McdRenderState.colorWritemask[2] = gc->state.raster.bMask;
|
|
McdRenderState.colorWritemask[3] = gc->state.raster.aMask;
|
|
McdRenderState.depthWritemask = gc->state.depth.writeEnable;
|
|
|
|
// To be consistent, we will scale the clear color to whatever
|
|
// the MCD driver specified:
|
|
|
|
McdRenderState.colorClearValue.r = gc->state.raster.clear.r * gc->redVertexScale;
|
|
McdRenderState.colorClearValue.g = gc->state.raster.clear.g * gc->greenVertexScale;
|
|
McdRenderState.colorClearValue.b = gc->state.raster.clear.b * gc->blueVertexScale;
|
|
McdRenderState.colorClearValue.a = gc->state.raster.clear.a * gc->alphaVertexScale;
|
|
|
|
McdRenderState.indexClearValue = gc->state.raster.clearIndex;
|
|
McdRenderState.stencilClearValue = (USHORT) gc->state.stencil.clear;
|
|
|
|
McdRenderState.depthClearValue = (MCDDOUBLE) (gc->state.depth.clear *
|
|
gengc->genAccel.zDevScale);
|
|
|
|
//
|
|
// -=<< Lighting >>=-
|
|
//
|
|
|
|
McdRenderState.twoSided = gc->state.light.model.twoSided;
|
|
|
|
//
|
|
// -=<< Clipping Control >>=-
|
|
//
|
|
|
|
memset(McdRenderState.userClipPlanes, 0, sizeof(McdRenderState.userClipPlanes));
|
|
{
|
|
ULONG i, mask, numClipPlanes;
|
|
|
|
//
|
|
// Number of user defined clip planes should match. However,
|
|
// rather than assume this, let's take the min and be robust.
|
|
//
|
|
|
|
ASSERTOPENGL(sizeof(__GLcoord) == sizeof(MCDCOORD),
|
|
"GenMcdUpdateRenderState: coord struct mismatch\n");
|
|
|
|
ASSERTOPENGL(MCD_MAX_USER_CLIP_PLANES == gc->constants.numberOfClipPlanes,
|
|
"GenMcdUpdateRenderState: num clip planes mismatch\n");
|
|
|
|
numClipPlanes = min(MCD_MAX_USER_CLIP_PLANES, gc->constants.numberOfClipPlanes);
|
|
|
|
for (i = 0, mask = 1; i < numClipPlanes; i++, mask <<= 1)
|
|
{
|
|
if (mask & gc->state.enables.clipPlanes)
|
|
{
|
|
McdRenderState.userClipPlanes[i] =
|
|
*(MCDCOORD *)&gc->state.transform.eyeClipPlanes[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// -=<< Hints >>=-
|
|
//
|
|
|
|
McdRenderState.perspectiveCorrectionHint = gc->state.hints.perspectiveCorrection;
|
|
McdRenderState.pointSmoothHint = gc->state.hints.pointSmooth;
|
|
McdRenderState.lineSmoothHint = gc->state.hints.lineSmooth;
|
|
McdRenderState.polygonSmoothHint = gc->state.hints.polygonSmooth;
|
|
McdRenderState.fogHint = gc->state.hints.fog;
|
|
|
|
//
|
|
// Now that the complete MCD state is computed, add it to the state cmd.
|
|
//
|
|
|
|
(gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_RENDER_STATE,
|
|
&McdRenderState,
|
|
sizeof(McdRenderState));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdViewport
|
|
*
|
|
* Set the viewport from the OpenGL state.
|
|
*
|
|
* History:
|
|
* 09-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdViewport(__GLGENcontext *gengc)
|
|
{
|
|
MCDVIEWPORT mcdVP;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdViewport: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdViewport: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// We can copy directly from &viewport.xScale to a MCDVIEWPORT because the
|
|
// structures are the same. To be safe, assert the structure ordering.
|
|
//
|
|
|
|
ASSERTOPENGL(
|
|
offsetof(MCDVIEWPORT, xCenter) ==
|
|
(offsetof(__GLviewport, xCenter) - offsetof(__GLviewport, xScale))
|
|
&& offsetof(MCDVIEWPORT, yCenter) ==
|
|
(offsetof(__GLviewport, yCenter) - offsetof(__GLviewport, xScale))
|
|
&& offsetof(MCDVIEWPORT, zCenter) ==
|
|
(offsetof(__GLviewport, zCenter) - offsetof(__GLviewport, xScale))
|
|
&& offsetof(MCDVIEWPORT, yScale) ==
|
|
(offsetof(__GLviewport, yScale) - offsetof(__GLviewport, xScale))
|
|
&& offsetof(MCDVIEWPORT, zScale) ==
|
|
(offsetof(__GLviewport, zScale) - offsetof(__GLviewport, xScale)),
|
|
"GenMcdViewport: structure mismatch\n");
|
|
|
|
memcpy(&mcdVP.xScale, &gengc->gc.state.viewport.xScale,
|
|
sizeof(MCDVIEWPORT));
|
|
|
|
(gpMcdTable->pMCDSetViewport)(&gengc->pMcdState->McdContext,
|
|
gengc->pMcdState->McdCmdBatch.pv, &mcdVP);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdScissor
|
|
*
|
|
* Set the scissor rectangle from the OpenGL state.
|
|
*
|
|
* History:
|
|
* 06-Mar-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
static void FASTCALL vGetScissor(__GLGENcontext *gengc, RECTL *prcl)
|
|
{
|
|
prcl->left = gengc->gc.state.scissor.scissorX;
|
|
prcl->right = gengc->gc.state.scissor.scissorX + gengc->gc.state.scissor.scissorWidth;
|
|
|
|
if (gengc->gc.constants.yInverted)
|
|
{
|
|
prcl->bottom = gengc->gc.constants.height -
|
|
gengc->gc.state.scissor.scissorY;
|
|
prcl->top = gengc->gc.constants.height -
|
|
(gengc->gc.state.scissor.scissorY + gengc->gc.state.scissor.scissorHeight);
|
|
}
|
|
else
|
|
{
|
|
prcl->top = gengc->gc.state.scissor.scissorY;
|
|
prcl->bottom = gengc->gc.state.scissor.scissorY + gengc->gc.state.scissor.scissorHeight;
|
|
}
|
|
}
|
|
|
|
void FASTCALL GenMcdScissor(__GLGENcontext *gengc)
|
|
{
|
|
BOOL bEnabled;
|
|
RECTL rcl;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdScissor: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdScissor: mcd32.dll not initialized\n");
|
|
|
|
vGetScissor(gengc, &rcl);
|
|
|
|
bEnabled = (gengc->gc.state.enables.general & __GL_SCISSOR_TEST_ENABLE)
|
|
? TRUE : FALSE;
|
|
|
|
(gpMcdTable->pMCDSetScissorRect)(&gengc->pMcdState->McdContext, &rcl,
|
|
bEnabled);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateScissorState
|
|
*
|
|
* Update MCD scissor state from the OpenGL state.
|
|
*
|
|
* This call only adds a state structure to the current state command.
|
|
* It is assumed that the caller has already called MCDBeginState and
|
|
* will call MCDFlushState.
|
|
*
|
|
* This is similar to but not quite the same as GenMcdScissor. The
|
|
* GenMcdScissor only sets the scissor rect in the MCDSRV32.DLL to
|
|
* compute the scissored clip list it maintains. This call is used
|
|
* to update the scissor rectangle state in the (MCD) display driver.
|
|
*
|
|
* History:
|
|
* 27-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdUpdateScissorState(__GLGENcontext *gengc)
|
|
{
|
|
__GLcontext *gc = &gengc->gc;
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
RECTL rcl;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdUpdateScissorState: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdateScissorState: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Get the scissor rect.
|
|
//
|
|
|
|
vGetScissor(gengc, &rcl);
|
|
|
|
//
|
|
// Add MCDPIXELSTATE to the state cmd.
|
|
//
|
|
|
|
(gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_SCISSOR_RECT_STATE,
|
|
&rcl,
|
|
sizeof(rcl));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateTexEnvState
|
|
*
|
|
* Update MCD texture environment state from the OpenGL state.
|
|
*
|
|
* This call only adds a state structure to the current state command.
|
|
* It is assumed that the caller has already called MCDBeginState and
|
|
* will call MCDFlushState.
|
|
*
|
|
* History:
|
|
* 21-Oct-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdUpdateTexEnvState(__GLGENcontext *gengc)
|
|
{
|
|
__GLcontext *gc = &gengc->gc;
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
MCDTEXENVSTATE McdTexEnvState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdUpdateTexEnvState: "
|
|
"null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdateTexEnvState: "
|
|
"mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// The texture environment array should have been initialized in
|
|
// __glEarlyInitTextureState, but it does not have an error return
|
|
// so it is possible that the array is NULL.
|
|
//
|
|
|
|
if (!gengc->gc.state.texture.env)
|
|
{
|
|
WARNING("GenMcdUpdateTexEnvState: null texture environment\n");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// There is only one texture environment per-context.
|
|
//
|
|
// If multiple textures are added to a future version of OpenGL,
|
|
// then we can define a new state structure for each new texture.
|
|
// Or we can add a separate MCDTEXENVSTATE structure to the state
|
|
// batch for each supported texture environment. The first structure
|
|
// is for the first environment, the second structure is for the
|
|
// second environment, etc. The driver can ignore any structures
|
|
// over the number of texture environments it supports. Of course,
|
|
// these are just suggestions. Depending on how multiple textures
|
|
// are spec'd, we might have to do something totally different.
|
|
//
|
|
|
|
McdTexEnvState.texEnvMode = gengc->gc.state.texture.env[0].mode;
|
|
*((__GLcolor *) &McdTexEnvState.texEnvColor) = gengc->gc.state.texture.env[0].color;
|
|
|
|
//
|
|
// Add MCDPIXELSTATE to the state cmd.
|
|
//
|
|
|
|
(gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_TEXENV_STATE,
|
|
&McdTexEnvState,
|
|
sizeof(McdTexEnvState));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdDrawPrim
|
|
*
|
|
* Draw the primitives in the POLYARRAY/POLYDATA array pointed to by pa.
|
|
* The primitives are chained together as a linked list terminated by a
|
|
* NULL. The return value is a pointer to the first unhandled primitive
|
|
* (NULL if the entire chain is successfully processed).
|
|
*
|
|
* Returns:
|
|
* NULL if entire batch is processed; otherwise, return value is a pointer
|
|
* to the unhandled portion of the chain.
|
|
*
|
|
* History:
|
|
* 09-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
POLYARRAY * FASTCALL GenMcdDrawPrim(__GLGENcontext *gengc, POLYARRAY *pa)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
int levels;
|
|
LPDIRECTDRAWSURFACE *pdds;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdDrawPrim: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdDrawPrim: mcd32.dll not initialized\n");
|
|
|
|
#if DBG
|
|
{
|
|
LONG lOffset;
|
|
|
|
lOffset = (LONG) ((BYTE *) pa - (BYTE *) pMcdState->pMcdPrimBatch->pv);
|
|
|
|
ASSERTOPENGL(
|
|
(lOffset >= 0) &&
|
|
(lOffset < (LONG) pMcdState->pMcdPrimBatch->size),
|
|
"GenMcdDrawPrim: pa not in shared mem window\n");
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Before calling MCD to draw, flush state.
|
|
//
|
|
|
|
vFlushDirtyState(gengc);
|
|
|
|
#ifdef AUTOMATIC_SURF_LOCK
|
|
levels = gengc->gc.texture.ddtex.levels;
|
|
if (levels > 0 &&
|
|
gengc->gc.texture.ddtex.texobj.loadKey != 0)
|
|
{
|
|
pdds = gengc->gc.texture.ddtex.pdds;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
levels = 0;
|
|
pdds = NULL;
|
|
}
|
|
|
|
return (POLYARRAY *)
|
|
(gpMcdTable->pMCDProcessBatch)(&pMcdState->McdContext,
|
|
pMcdState->pMcdPrimBatch->pv,
|
|
pMcdState->pMcdPrimBatch->size,
|
|
(PVOID) pa,
|
|
levels, pdds);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdSwapBatch
|
|
*
|
|
* If the MCD driver uses DMA, then as part of context creation TWO vertex
|
|
* buffers we allocated so that we could ping-pong or double buffer between
|
|
* the two buffers (i.e., while the MCD driver is busy processing the
|
|
* data in one vertex buffer, OpenGL can start filling the other vertex
|
|
* buffer).
|
|
*
|
|
* This function switches the MCD state and OpenGL context to the other
|
|
* buffer. If the new buffer is still being processed by the MCD driver,
|
|
* we will periodically poll the status of the buffer until it becomes
|
|
* available.
|
|
*
|
|
* History:
|
|
* 08-Mar-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdSwapBatch(__GLGENcontext *gengc)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
GENMCDBUF *pNewBuf;
|
|
ULONG ulMemStatus;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdSwapBatch: null pMcdState\n");
|
|
|
|
ASSERTOPENGL(McdDriverInfo.mcdDriverInfo.drvMemFlags & MCDRV_MEM_DMA,
|
|
"GenMcdSwapBatch: error -- not using DMA\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdSwapBatch: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Determine which of McdBuf1 and McdBuf2 is the current buffer and
|
|
// which is the new buffer.
|
|
//
|
|
|
|
if (pMcdState->pMcdPrimBatch == &pMcdState->McdBuf1)
|
|
pNewBuf = &pMcdState->McdBuf2;
|
|
else
|
|
pNewBuf = &pMcdState->McdBuf1;
|
|
|
|
//
|
|
// Poll memory status of the new buffer until it is available.
|
|
//
|
|
|
|
do
|
|
{
|
|
ulMemStatus = (gpMcdTable->pMCDQueryMemStatus)(pNewBuf->pv);
|
|
|
|
//
|
|
// If status of the new buffer is MCD_MEM_READY, set it as the
|
|
// current vertex buffer (both in the pMcdState and in the gengc.
|
|
//
|
|
|
|
if (ulMemStatus == MCD_MEM_READY)
|
|
{
|
|
pMcdState->pMcdPrimBatch = pNewBuf;
|
|
gengc->gc.vertex.pdBuf = (POLYDATA *) pMcdState->pMcdPrimBatch->pv;
|
|
}
|
|
else if (ulMemStatus == MCD_MEM_INVALID)
|
|
{
|
|
//
|
|
// This should not be possible, but to be robust let's handle
|
|
// the case in which the new buffer has somehow become invalid
|
|
// (in other words, "Beware of bad drivers!").
|
|
//
|
|
// We handle this by abandoning double buffering and simply
|
|
// wait for the current buffer to become available again.
|
|
// Not very efficient, but at least we recover gracefully.
|
|
//
|
|
|
|
RIP("GenMcdSwapBatch: vertex buffer invalid!\n");
|
|
|
|
do
|
|
{
|
|
ulMemStatus = (gpMcdTable->pMCDQueryMemStatus)(pMcdState->pMcdPrimBatch->pv);
|
|
|
|
//
|
|
// The current buffer definitely should not become invalid!
|
|
//
|
|
|
|
ASSERTOPENGL(ulMemStatus != MCD_MEM_INVALID,
|
|
"GenMcdSwapBatch: current vertex buffer invalid!\n");
|
|
|
|
} while (ulMemStatus == MCD_MEM_BUSY);
|
|
}
|
|
|
|
} while (ulMemStatus == MCD_MEM_BUSY);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdSwapBuffers
|
|
*
|
|
* Invoke the MCD swap buffers command.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* History:
|
|
* 19-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdSwapBuffers(HDC hdc, GLGENwindow *pwnd)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
MCDCONTEXT McdContextTmp;
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdSwapBuffers: mcd32.dll not initialized\n");
|
|
|
|
McdContextTmp.hdc = hdc;
|
|
McdContextTmp.hMCDContext = NULL;
|
|
McdContextTmp.dwMcdWindow = pwnd->dwMcdWindow;
|
|
|
|
bRet = (gpMcdTable->pMCDSwap)(&McdContextTmp, 0);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdResizeBuffers
|
|
*
|
|
* Resize the buffers (front, back, and depth) associated with the MCD
|
|
* context bound to the specified GL context.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* Note: If this functions fails, then MCD drawing for the MCD context
|
|
* will fail. Other MCD contexts are unaffected.
|
|
*
|
|
* History:
|
|
* 20-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdResizeBuffers(__GLGENcontext *gengc)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdResizeBuffers: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdResizeBuffers: mcd32.dll not initialized\n");
|
|
|
|
bRet = (gpMcdTable->pMCDAllocBuffers)(&gengc->pMcdState->McdContext,
|
|
&gengc->pwndLocked->rclClient);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateBufferInfo
|
|
*
|
|
* This function must be called on every screen access start to synchronize
|
|
* the GENMCDSURFACE to the current framebuffer pointer and stride.
|
|
*
|
|
* If we have direct access to any of the MCD buffers (front, back, depth),
|
|
* then setup pointers to the buffer and set flags indicating that they are
|
|
* accessible.
|
|
*
|
|
* Otherwise, mark them as inaccessible (which will force us to use
|
|
* MCDReadSpan or MCDWriteSpan to access the buffers).
|
|
*
|
|
* History:
|
|
* 20-Feb-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdUpdateBufferInfo(__GLGENcontext *gengc)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
__GLcontext *gc = (__GLcontext *) gengc;
|
|
__GLGENbuffers *buffers = gengc->pwndLocked->buffers;
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
MCDRECTBUFFERS McdBuffers;
|
|
BOOL bForceValidate = FALSE;
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdateBufferInfo: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Does the flag in pMcdState indicate that a pick should be forced?
|
|
// This is required, for example, for the first batch after an MCD
|
|
// context has been made current.
|
|
//
|
|
|
|
if (pMcdState->mcdFlags & MCD_STATE_FORCEPICK)
|
|
{
|
|
bForceValidate = TRUE;
|
|
pMcdState->mcdFlags &= ~MCD_STATE_FORCEPICK;
|
|
}
|
|
|
|
//
|
|
// This is the currently active context. Set the pointer in the
|
|
// shared surface info.
|
|
//
|
|
|
|
buffers->pMcdState = pMcdState;
|
|
|
|
#ifdef MCD95
|
|
//
|
|
// Set the request flags.
|
|
//
|
|
|
|
McdBuffers.mcdRequestFlags = MCDBUF_REQ_MCDBUFINFO;
|
|
#endif
|
|
|
|
if (gengc->dwCurrentFlags & GLSURF_DIRECTDRAW)
|
|
{
|
|
// Nothing to do
|
|
}
|
|
else if ((gengc->fsLocks & LOCKFLAG_FRONT_BUFFER)
|
|
&& (gpMcdTable->pMCDGetBuffers)(&pMcdState->McdContext, &McdBuffers))
|
|
{
|
|
BYTE *pbVideoBase;
|
|
|
|
// If we're in this code block it shouldn't be possible
|
|
// to have the DD_DEPTH lock since that should only
|
|
// occur if the current surface is a DDraw surface.
|
|
ASSERTOPENGL((gengc->fsLocks & LOCKFLAG_DD_DEPTH) == 0,
|
|
"DD_DEPTH lock unexpected\n");
|
|
|
|
#ifdef MCD95
|
|
pbVideoBase = (BYTE *) McdBuffers.pvFrameBuf;
|
|
#else
|
|
//
|
|
// In order to compute the buffer pointers from the offsets returned by
|
|
// MCDGetBuffers, we need to know the frame buffer pointer.
|
|
// This implies direct screen access must be enabled.
|
|
//
|
|
|
|
if (gengc->pgddsFront != NULL)
|
|
{
|
|
pbVideoBase = (BYTE *)GLSCREENINFO->gdds.ddsd.lpSurface;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Front buffer.
|
|
//
|
|
|
|
if (McdBuffers.mcdFrontBuf.bufFlags & MCDBUF_ENABLED)
|
|
{
|
|
gc->frontBuffer.buf.xOrigin = gengc->pwndLocked->rclClient.left;
|
|
gc->frontBuffer.buf.yOrigin = gengc->pwndLocked->rclClient.top;
|
|
|
|
//
|
|
// Since clipping is in screen coordinates, offset buffer pointer
|
|
// by the buffer origin.
|
|
//
|
|
gc->frontBuffer.buf.base =
|
|
(PVOID) (pbVideoBase + McdBuffers.mcdFrontBuf.bufOffset
|
|
- (McdBuffers.mcdFrontBuf.bufStride * gc->frontBuffer.buf.yOrigin)
|
|
- (gc->frontBuffer.buf.xOrigin * ((gengc->gsurf.pfd.cColorBits + 7) >> 3)));
|
|
gc->frontBuffer.buf.outerWidth = McdBuffers.mcdFrontBuf.bufStride;
|
|
gc->frontBuffer.buf.flags |= DIB_FORMAT;
|
|
}
|
|
else
|
|
{
|
|
gc->frontBuffer.buf.xOrigin = 0;
|
|
gc->frontBuffer.buf.yOrigin = 0;
|
|
|
|
gc->frontBuffer.buf.base = NULL;
|
|
gc->frontBuffer.buf.flags &= ~DIB_FORMAT;
|
|
}
|
|
|
|
//
|
|
// Back buffer.
|
|
//
|
|
|
|
if (McdBuffers.mcdBackBuf.bufFlags & MCDBUF_ENABLED)
|
|
{
|
|
gc->backBuffer.buf.xOrigin = gengc->pwndLocked->rclClient.left;
|
|
gc->backBuffer.buf.yOrigin = gengc->pwndLocked->rclClient.top;
|
|
|
|
//
|
|
// Since clipping is in screen coordinates, offset buffer pointer
|
|
// by the buffer origin.
|
|
//
|
|
gc->backBuffer.buf.base =
|
|
(PVOID) (pbVideoBase + McdBuffers.mcdBackBuf.bufOffset
|
|
- (McdBuffers.mcdBackBuf.bufStride * gc->backBuffer.buf.yOrigin)
|
|
- (gc->backBuffer.buf.xOrigin * ((gengc->gsurf.pfd.cColorBits + 7) >> 3)));
|
|
gc->backBuffer.buf.outerWidth = McdBuffers.mcdBackBuf.bufStride;
|
|
gc->backBuffer.buf.flags |= DIB_FORMAT;
|
|
}
|
|
else
|
|
{
|
|
gc->backBuffer.buf.xOrigin = 0;
|
|
gc->backBuffer.buf.yOrigin = 0;
|
|
|
|
gc->backBuffer.buf.base = (PVOID) NULL;
|
|
gc->backBuffer.buf.flags &= ~DIB_FORMAT;
|
|
}
|
|
if (McdBuffers.mcdBackBuf.bufFlags & MCDBUF_NOCLIP)
|
|
gc->backBuffer.buf.flags |= NO_CLIP;
|
|
else
|
|
gc->backBuffer.buf.flags &= ~NO_CLIP;
|
|
|
|
UpdateSharedBuffer(&buffers->backBuffer , &gc->backBuffer.buf);
|
|
|
|
//
|
|
// Depth buffer.
|
|
//
|
|
|
|
//!!!mcd -- No depth buffer clipping code, so if we have to clip
|
|
//!!!mcd depth buffer we need to revert back to span code.
|
|
|
|
if ((McdBuffers.mcdDepthBuf.bufFlags & MCDBUF_ENABLED) &&
|
|
(McdBuffers.mcdDepthBuf.bufFlags & MCDBUF_NOCLIP))
|
|
{
|
|
gc->depthBuffer.buf.xOrigin = 0;
|
|
gc->depthBuffer.buf.yOrigin = 0;
|
|
|
|
gc->depthBuffer.buf.base =
|
|
(PVOID) (pbVideoBase + McdBuffers.mcdDepthBuf.bufOffset);
|
|
|
|
//
|
|
// Depth code expects stride as a pixel count, not a byte count.
|
|
//
|
|
|
|
gc->depthBuffer.buf.outerWidth =
|
|
McdBuffers.mcdDepthBuf.bufStride /
|
|
((pMcdState->McdPixelFmt.cDepthBufferBits + 7) >> 3);
|
|
|
|
//!!!mcd dbug -- span code sets element size to 32bit. should we
|
|
//!!!mcd dbug set according to cDepthBits when direct access is used?!?
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If we ended up here because clipping is required, buffer
|
|
// could still be marked as accessible. We want the state change
|
|
// detection code to treat this as an inaccessible buffer case,
|
|
// so force the flags to 0.
|
|
//
|
|
|
|
McdBuffers.mcdDepthBuf.bufFlags = 0;
|
|
|
|
gc->depthBuffer.buf.xOrigin = 0;
|
|
gc->depthBuffer.buf.yOrigin = 0;
|
|
|
|
gc->depthBuffer.buf.base = (PVOID) pMcdState->pDepthSpan;
|
|
|
|
//!!!mcd dbug -- always force pick procs if no zbuf access
|
|
//bForceValidate = TRUE;
|
|
}
|
|
|
|
UpdateSharedBuffer(&buffers->depthBuffer , &gc->depthBuffer.buf);
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// MCDGetBuffers normally shouldn't fail. However, let's gracefully
|
|
// handle this odd case by falling back to the span buffer code.
|
|
//
|
|
|
|
gc->frontBuffer.buf.xOrigin = 0;
|
|
gc->frontBuffer.buf.yOrigin = 0;
|
|
gc->frontBuffer.buf.base = (PVOID) NULL;
|
|
gc->frontBuffer.buf.flags &= ~DIB_FORMAT;
|
|
|
|
gc->backBuffer.buf.xOrigin = 0;
|
|
gc->backBuffer.buf.yOrigin = 0;
|
|
gc->backBuffer.buf.base = (PVOID) NULL;
|
|
gc->backBuffer.buf.flags &= ~DIB_FORMAT;
|
|
|
|
gc->depthBuffer.buf.xOrigin = 0;
|
|
gc->depthBuffer.buf.yOrigin = 0;
|
|
gc->depthBuffer.buf.base = (PVOID) pMcdState->pDepthSpan;
|
|
|
|
//
|
|
// Extra paranoid code. Zero out structure in case MCD driver
|
|
// partially initialized McdBuffers.
|
|
//
|
|
|
|
memset(&McdBuffers, 0, sizeof(McdBuffers));
|
|
}
|
|
|
|
//
|
|
// If state changed (i.e., access to any of the buffers gained or lost),
|
|
// need to force pick procs.
|
|
//
|
|
|
|
if ( (pMcdState->McdBuffers.mcdFrontBuf.bufFlags !=
|
|
McdBuffers.mcdFrontBuf.bufFlags)
|
|
|| (pMcdState->McdBuffers.mcdBackBuf.bufFlags !=
|
|
McdBuffers.mcdBackBuf.bufFlags)
|
|
|| (pMcdState->McdBuffers.mcdDepthBuf.bufFlags !=
|
|
McdBuffers.mcdDepthBuf.bufFlags) )
|
|
{
|
|
bForceValidate = TRUE;
|
|
}
|
|
|
|
//
|
|
// Save a copy of current MCD buffers.
|
|
//
|
|
|
|
pMcdState->McdBuffers = McdBuffers;
|
|
|
|
//
|
|
// If needed, do pick procs.
|
|
//
|
|
|
|
if (bForceValidate)
|
|
{
|
|
gc->dirtyMask |= __GL_DIRTY_ALL;
|
|
(*gc->procs.validate)(gc);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdSynchronize
|
|
*
|
|
* This function synchronizes to the MCD driver; i.e., it waits until the
|
|
* hardware is ready for direct access to the framebuffer and/or more
|
|
* hardware-accelerated operations. This is needed because some (most?) 2D
|
|
* and 3D accelerator chips do not support simultaneous hardware operations
|
|
* and framebuffer access.
|
|
*
|
|
* This function must be called by any GL API that potentially touches any
|
|
* of the MCD buffers (front, back, or depth) without giving MCD first crack.
|
|
* For example, clears always go to MCDClear before the software clear is
|
|
* given a chance; therefore, glClear does not need to call GenMcdSychronize.
|
|
* On the other hand, glReadPixels does not have an equivalent MCD function
|
|
* so it immediately goes to the software implementation; therefore,
|
|
* glReadPixels does need to call GenMcdSynchronize.
|
|
*
|
|
* History:
|
|
* 20-Mar-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdSynchronize(__GLGENcontext *gengc)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdSynchronize: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdSynchronize: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Note: MCDSync returns a BOOL indicating success or failure. This
|
|
// is actually for future expansion. Currently, the function is defined
|
|
// to WAIT until the hardware is ready and then return success. The
|
|
// specification of the function behavior allows us to ignore the return
|
|
// value for now.
|
|
//
|
|
// In the future, we may change this to a query function. In which case
|
|
// we should call this in a while loop. I'd rather not do this at this
|
|
// time though, as it leaves us vulnerable to an infinitely loop problem
|
|
// if we have a bad MCD driver.
|
|
//
|
|
|
|
(gpMcdTable->pMCDSync)(&pMcdState->McdContext);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdConvertContext
|
|
*
|
|
* Convert the context from an MCD-based one to a generic one.
|
|
*
|
|
* This requires creating the buffers, etc. that are required for a generic
|
|
* context and releasing the MCD resources.
|
|
*
|
|
* IMPORTANT NOTE:
|
|
* Because we modify the buffers struct, the WNDOBJ semaphore
|
|
* should be held while calling this function.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* Side effects:
|
|
* If successful, the MCD surface is freed and the context will use
|
|
* only generic code. However, the gengc->_pMcdState will still point to
|
|
* a valid (but quiescent as gengc->pMcdState is disconnected) GENMCDSTATE
|
|
* structure that needs to be deleted when the GLGENcontext is deleted.
|
|
*
|
|
* If it fails, then the MCD resources are left allocated meaning that
|
|
* we can try to realloc the MCD buffers later. However, for the current
|
|
* batch, drawing may not be possible (presumedly we were called because
|
|
* GenMcdResizeBuffers failed).
|
|
*
|
|
* History:
|
|
* 18-Apr-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdConvertContext(__GLGENcontext *gengc,
|
|
__GLGENbuffers *buffers)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
__GLcontext *gc = &gengc->gc;
|
|
GENMCDSTATE *pMcdStateSAVE;
|
|
GENMCDSTATE *_pMcdStateSAVE;
|
|
GENMCDSTATE *buffers_pMcdStateSAVE;
|
|
GENMCDSURFACE *pMcdSurfSAVE;
|
|
BOOL bConvertContext, bConvertSurface;
|
|
|
|
ASSERTOPENGL(gengc->_pMcdState,
|
|
"GenMcdConvertContext: not an MCD context\n");
|
|
|
|
//
|
|
// Do not support conversion if not compatible with generic code.
|
|
//
|
|
|
|
if (!(gengc->flags & GENGC_GENERIC_COMPATIBLE_FORMAT))
|
|
return FALSE;
|
|
|
|
//
|
|
// Determine if context needs conversion. Do not need to create
|
|
// scanline buffers if already converted.
|
|
//
|
|
|
|
if (gengc->flags & GLGEN_MCD_CONVERTED_TO_GENERIC)
|
|
bConvertContext = FALSE;
|
|
else
|
|
bConvertContext = TRUE;
|
|
|
|
//
|
|
// Determine if surface needs conversion. Do not need to create
|
|
// the generic shared buffers or destroy MCD surface if already
|
|
// converted.
|
|
//
|
|
|
|
if (buffers->flags & GLGENBUF_MCD_LOST)
|
|
bConvertSurface = FALSE;
|
|
else
|
|
bConvertSurface = TRUE;
|
|
|
|
//
|
|
// Early out if neither context or surface needs conversion.
|
|
//
|
|
|
|
//!!!SP1 -- should be able to early out, but risky for NT4.0
|
|
//if (!bConvertContext && !bConvertSurface)
|
|
//{
|
|
// return TRUE;
|
|
//}
|
|
|
|
//
|
|
// Save current MCD context and surface info.
|
|
//
|
|
// Note that we grab the surface info from the buffers struct.
|
|
// The copy in gengc->pMcdState->pMcdSurf is potentially stale
|
|
// (i.e., may point to a surface already deleted by an earlier
|
|
// call to GenMcdConvertContext for a context that shares the
|
|
// same buffers struct).
|
|
//
|
|
// This allows us to use pMcdSurfSAVE as a flag. If it is
|
|
// NULL, we know that the MCD surface has already been deleted.
|
|
//
|
|
|
|
pMcdSurfSAVE = buffers->pMcdSurf;
|
|
buffers_pMcdStateSAVE = buffers->pMcdState;
|
|
|
|
pMcdStateSAVE = gengc->pMcdState;
|
|
_pMcdStateSAVE = gengc->_pMcdState;
|
|
|
|
//
|
|
// First, remove the MCD information from the context and buffers structs.
|
|
//
|
|
|
|
buffers->pMcdSurf = NULL;
|
|
buffers->pMcdState = NULL;
|
|
|
|
gengc->pMcdState = NULL;
|
|
gengc->_pMcdState = NULL;
|
|
|
|
//
|
|
// Create required buffers; initialize buffer info structs.
|
|
//
|
|
|
|
if (bConvertContext)
|
|
{
|
|
if (!wglCreateScanlineBuffers(gengc))
|
|
{
|
|
WARNING("GenMcdConvertContext: wglCreateScanlineBuffers failed\n");
|
|
goto GenMcdConvertContext_exit;
|
|
}
|
|
wglInitializeColorBuffers(gengc);
|
|
wglInitializeDepthBuffer(gengc);
|
|
wglInitializePixelCopyFuncs(gengc);
|
|
}
|
|
|
|
//
|
|
// *******************************************************************
|
|
// None of the subsequent operations have failure cases, so at this
|
|
// point success is guaranteed. We no longer need to worry about
|
|
// saving current values so that they can be restored in the failure
|
|
// case.
|
|
//
|
|
// If code is added that may fail, it must be added before this point.
|
|
// Otherwise, it is acceptable to add the code afterwards.
|
|
// *******************************************************************
|
|
//
|
|
|
|
bRet = TRUE;
|
|
|
|
//
|
|
// Invalidate the context's depth buffer.
|
|
//
|
|
|
|
if (bConvertContext)
|
|
{
|
|
gc->modes.haveDepthBuffer = GL_FALSE;
|
|
gc->depthBuffer.buf.base = 0;
|
|
gc->depthBuffer.buf.size = 0;
|
|
gc->depthBuffer.buf.outerWidth = 0;
|
|
}
|
|
|
|
//
|
|
// Generic backbuffer doesn't care about the WNDOBJ, so connect the
|
|
// backbuffer to the dummy backbuffer WNDOBJ rather than the real one.
|
|
//
|
|
|
|
if (gc->modes.doubleBufferMode)
|
|
{
|
|
gc->backBuffer.bitmap = &buffers->backBitmap;
|
|
buffers->backBitmap.pwnd = &buffers->backBitmap.wnd;
|
|
}
|
|
|
|
//
|
|
// Generic back buffers have origin of (0,0).
|
|
//
|
|
|
|
gc->backBuffer.buf.xOrigin = 0;
|
|
gc->backBuffer.buf.yOrigin = 0;
|
|
buffers->backBuffer.xOrigin = 0;
|
|
buffers->backBuffer.yOrigin = 0;
|
|
|
|
GenMcdConvertContext_exit:
|
|
|
|
if (bRet)
|
|
{
|
|
//
|
|
// Delete MCD surface.
|
|
//
|
|
|
|
if (bConvertSurface && pMcdSurfSAVE)
|
|
{
|
|
GenMcdDeleteSurface(pMcdSurfSAVE);
|
|
|
|
//
|
|
// Invalidate the shared depth buffer.
|
|
// Set depth resize routine to the generic version.
|
|
//
|
|
|
|
buffers->depthBuffer.base = 0;
|
|
buffers->depthBuffer.size = 0;
|
|
buffers->depthBuffer.outerWidth = 0;
|
|
buffers->resizeDepth = ResizeAncillaryBuffer;
|
|
|
|
//
|
|
// Since we deleted MCD surface, we get to create the generic
|
|
// buffers to replace it.
|
|
//
|
|
|
|
wglResizeBuffers(gengc, buffers->width, buffers->height);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Didn't need to create generic buffers, but we do need to
|
|
// update the buffer info in the context.
|
|
//
|
|
|
|
wglUpdateBuffers(gengc, buffers);
|
|
}
|
|
|
|
//
|
|
// Reconnect _pMcdState; it and the MCD context resources
|
|
// will be deleted when the GLGENcontext is deleted
|
|
// (but note that pMcdState remains NULL!).
|
|
//
|
|
// We need to keep it around because we are going to continue
|
|
// to use the MCD allocated POLYARRAY buffer.
|
|
//
|
|
|
|
gengc->_pMcdState = _pMcdStateSAVE;
|
|
gengc->_pMcdState->pMcdSurf = (GENMCDSURFACE *) NULL;
|
|
gengc->_pMcdState->pDepthSpan = (__GLzValue *) NULL;
|
|
|
|
//
|
|
// Mark buffers struct so that other contexts will know that the
|
|
// MCD resources are gone.
|
|
//
|
|
|
|
buffers->flags |= GLGENBUF_MCD_LOST;
|
|
|
|
//
|
|
// Mark context as converted so we don't do it again.
|
|
//
|
|
|
|
gengc->flags |= GLGEN_MCD_CONVERTED_TO_GENERIC;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Delete generic resources if neccessary.
|
|
//
|
|
|
|
wglDeleteScanlineBuffers(gengc);
|
|
|
|
//
|
|
// Restore the MCD information.
|
|
//
|
|
|
|
buffers->pMcdSurf = pMcdSurfSAVE;
|
|
buffers->pMcdState = buffers_pMcdStateSAVE;
|
|
|
|
gengc->pMcdState = pMcdStateSAVE;
|
|
gengc->_pMcdState = _pMcdStateSAVE;
|
|
|
|
//
|
|
// Resetting the MCD information requires that we
|
|
// reinitialization the color, depth, and pixel copy
|
|
// funcs.
|
|
//
|
|
|
|
wglInitializeColorBuffers(gengc);
|
|
wglInitializeDepthBuffer(gengc);
|
|
wglInitializePixelCopyFuncs(gengc);
|
|
|
|
if (gengc->pMcdState && gengc->pMcdState->pDepthSpan)
|
|
{
|
|
gc->depthBuffer.buf.base = gengc->pMcdState->pDepthSpan;
|
|
buffers->depthBuffer.base = gengc->pMcdState->pDepthSpan;
|
|
buffers->resizeDepth = ResizeUnownedDepthBuffer;
|
|
}
|
|
|
|
__glSetErrorEarly(gc, GL_OUT_OF_MEMORY);
|
|
}
|
|
|
|
//
|
|
// Success or failure, we've messed around with enough data to
|
|
// require revalidation.
|
|
//
|
|
|
|
(*gc->procs.applyViewport)(gc);
|
|
//!!!SP1 -- GL_INVALIDATE (which only sets the __GL_DIRTY_GENERIC bit)
|
|
//!!!SP1 should suffice now that __glGenericPickAllProcs has been
|
|
//!!!SP1 modified to repick depth procs if GL_DIRTY_GENERIC is set.
|
|
//!!!SP1 However, we are too close to ship to get good stress coverage,
|
|
//!!!SP1 so leave it as is until after NT4.0 ships.
|
|
//__GL_INVALIDATE(gc);
|
|
gc->dirtyMask |= __GL_DIRTY_ALL;
|
|
gc->validateMask |= (__GL_VALIDATE_STENCIL_FUNC |
|
|
__GL_VALIDATE_STENCIL_OP);
|
|
(*gc->procs.validate)(gc);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdCreateTexture
|
|
*
|
|
* Invoke the MCD texture creation command.
|
|
*
|
|
* Returns:
|
|
* A non-NULL MCD handle if successful, NULL otherwise.
|
|
*
|
|
* History:
|
|
* 29-April-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
MCDHANDLE FASTCALL GenMcdCreateTexture(__GLGENcontext *gengc, __GLtexture *tex,
|
|
ULONG flags)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdCreateTexture: null pMcdState\n");
|
|
ASSERTOPENGL(tex, "GenMcdCreateTexture: null texture pointer\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdCreateTexture: mcd32.dll not initialized\n");
|
|
|
|
if ((flags & MCDTEXTURE_DIRECTDRAW_SURFACES) &&
|
|
!SUPPORTS_DIRECT())
|
|
{
|
|
// Don't pass DirectDraw texture surfaces to the driver if it
|
|
// doesn't support them.
|
|
return 0;
|
|
}
|
|
|
|
return (gpMcdTable->pMCDCreateTexture)(&pMcdState->McdContext,
|
|
(MCDTEXTUREDATA *)&tex->params,
|
|
flags, NULL);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdDeleteTexture
|
|
*
|
|
* Invoke the MCD texture deletion command.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* History:
|
|
* 29-April-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdDeleteTexture(__GLGENcontext *gengc, MCDHANDLE texHandle)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdDeleteTexture: null pMcdState\n");
|
|
ASSERTOPENGL(texHandle, "GenMcdDeleteTexture: null texture handle\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdDeleteTexture: mcd32.dll not initialized\n");
|
|
|
|
return (BOOL)(gpMcdTable->pMCDDeleteTexture)(&pMcdState->McdContext,
|
|
(MCDHANDLE)texHandle);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateSubTexture
|
|
*
|
|
* Invoke the MCD subtexture update command.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* History:
|
|
* 29-April-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdUpdateSubTexture(__GLGENcontext *gengc, __GLtexture *tex,
|
|
MCDHANDLE texHandle, GLint lod,
|
|
GLint xoffset, GLint yoffset,
|
|
GLsizei w, GLsizei h)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
RECTL rect;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdUpdateSubTexture: null pMcdState\n");
|
|
|
|
ASSERTOPENGL(texHandle, "GenMcdUpdateSubTexture: null texture handle\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdateSubTexture: mcd32.dll not initialized\n");
|
|
|
|
rect.left = xoffset;
|
|
rect.top = yoffset;
|
|
rect.right = xoffset + w;
|
|
rect.bottom = yoffset + h;
|
|
|
|
return (BOOL)(gpMcdTable->pMCDUpdateSubTexture)(&pMcdState->McdContext,
|
|
(MCDTEXTUREDATA *)&tex->params, (MCDHANDLE)texHandle,
|
|
(ULONG)lod, &rect);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateTexturePalette
|
|
*
|
|
* Invoke the MCD texture palette update command.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* History:
|
|
* 29-April-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdUpdateTexturePalette(__GLGENcontext *gengc, __GLtexture *tex,
|
|
MCDHANDLE texHandle, GLsizei start,
|
|
GLsizei count)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdUpdateTexturePalette: null pMcdState\n");
|
|
ASSERTOPENGL(texHandle, "GenMcdUpdateTexturePalette: null texture handle\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdateTexturePalette: mcd32.dll not initialized\n");
|
|
|
|
return (BOOL)(gpMcdTable->pMCDUpdateTexturePalette)(&pMcdState->McdContext,
|
|
(MCDTEXTUREDATA *)&tex->params, (MCDHANDLE)texHandle,
|
|
(ULONG)start, (ULONG)count);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateTexturePriority
|
|
*
|
|
* Invoke the MCD texture priority command.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* History:
|
|
* 29-April-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdUpdateTexturePriority(__GLGENcontext *gengc, __GLtexture *tex,
|
|
MCDHANDLE texHandle)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdUpdateTexturePriority: null pMcdState\n");
|
|
ASSERTOPENGL(texHandle, "GenMcdUpdateTexturePriority: null texture handle\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdateTexturePriority: mcd32.dll not initialized\n");
|
|
|
|
return (BOOL)(gpMcdTable->pMCDUpdateTexturePriority)(&pMcdState->McdContext,
|
|
(MCDTEXTUREDATA *)&tex->params, (MCDHANDLE)texHandle);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdTextureStatus
|
|
*
|
|
* Invoke the MCD texture status command.
|
|
*
|
|
* Returns:
|
|
* The status for the specified texture.
|
|
*
|
|
* History:
|
|
* 29-April-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
DWORD FASTCALL GenMcdTextureStatus(__GLGENcontext *gengc, MCDHANDLE texHandle)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdTextureStatus: null pMcdState\n");
|
|
ASSERTOPENGL(texHandle, "GenMcdTextureStatus: null texture handle\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdTextureStatus: mcd32.dll not initialized\n");
|
|
|
|
return (DWORD)(gpMcdTable->pMCDTextureStatus)(&pMcdState->McdContext,
|
|
(MCDHANDLE)texHandle);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateTextureState
|
|
*
|
|
* Invoke the MCD texture state update command.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* History:
|
|
* 29-April-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdUpdateTextureState(__GLGENcontext *gengc, __GLtexture *tex,
|
|
MCDHANDLE texHandle)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdUpdateTextureState: null pMcdState\n");
|
|
ASSERTOPENGL(texHandle, "GenMcdUpdateTextureState: null texture handle\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdTextureStatus: mcd32.dll not initialized\n");
|
|
|
|
return (BOOL)(gpMcdTable->pMCDUpdateTextureState)(&pMcdState->McdContext,
|
|
(MCDTEXTUREDATA *)&tex->params, (MCDHANDLE)texHandle);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdTextureKey
|
|
*
|
|
* Invoke the MCD texture key command. Note that this call does not go to
|
|
* the display driver, but gets handled in the mcd server.
|
|
*
|
|
* Returns:
|
|
* The driver-owned key for the specified texture.
|
|
*
|
|
* History:
|
|
* 29-April-1996 -by- Otto Berkes [ottob]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
DWORD FASTCALL GenMcdTextureKey(__GLGENcontext *gengc, MCDHANDLE texHandle)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdTextureKey: null pMcdState\n");
|
|
ASSERTOPENGL(texHandle, "GenMcdTextureKey: null texture handle\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdTextureKey: mcd32.dll not initialized\n");
|
|
|
|
return (DWORD)(gpMcdTable->pMCDTextureKey)(&pMcdState->McdContext,
|
|
(MCDHANDLE)texHandle);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdDescribeLayerPlane
|
|
*
|
|
* Call the MCD driver to return information about the specified layer plane.
|
|
*
|
|
* History:
|
|
* 16-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdDescribeLayerPlane(HDC hdc, int iPixelFormat,
|
|
int iLayerPlane, UINT nBytes,
|
|
LPLAYERPLANEDESCRIPTOR plpd)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
//
|
|
// Cannot assume that MCD is intialized.
|
|
//
|
|
|
|
if (gpMcdTable || bInitMcd(hdc))
|
|
{
|
|
//
|
|
// Caller (wglDescribeLayerPlane in client\layer.c) validates
|
|
// size.
|
|
//
|
|
|
|
ASSERTOPENGL(nBytes >= sizeof(LAYERPLANEDESCRIPTOR),
|
|
"GenMcdDescribeLayerPlane: bad size\n");
|
|
|
|
bRet = (gpMcdTable->pMCDDescribeLayerPlane)(hdc, iPixelFormat,
|
|
iLayerPlane, plpd);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdSetLayerPaletteEntries
|
|
*
|
|
* Set the logical palette for the specified layer plane.
|
|
*
|
|
* The logical palette is cached in the GLGENwindow structure and is flushed
|
|
* to the driver when GenMcdRealizeLayerPalette is called.
|
|
*
|
|
* History:
|
|
* 16-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
int FASTCALL GenMcdSetLayerPaletteEntries(HDC hdc, int iLayerPlane,
|
|
int iStart, int cEntries,
|
|
CONST COLORREF *pcr)
|
|
{
|
|
int iRet = 0;
|
|
GLGENwindow *pwnd;
|
|
GLWINDOWID gwid;
|
|
|
|
if (!pcr)
|
|
return iRet;
|
|
|
|
//
|
|
// Need to find the window that has the layer palettes.
|
|
//
|
|
|
|
WindowIdFromHdc(hdc, &gwid);
|
|
pwnd = pwndGetFromID(&gwid);
|
|
if (pwnd)
|
|
{
|
|
GLGENlayerInfo *plyri;
|
|
|
|
ENTER_WINCRIT(pwnd);
|
|
|
|
//
|
|
// Get the layer plane information.
|
|
//
|
|
|
|
plyri = plyriGet(pwnd, hdc, iLayerPlane);
|
|
if (plyri)
|
|
{
|
|
//
|
|
// Set the palette information in the layer plane structure.
|
|
//
|
|
|
|
iRet = min(plyri->cPalEntries - iStart, cEntries);
|
|
memcpy(&plyri->pPalEntries[iStart], pcr, iRet * sizeof(COLORREF));
|
|
}
|
|
|
|
pwndUnlock(pwnd, NULL);
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdGetLayerPaletteEntries
|
|
*
|
|
* Get the logical palette from the specified layer plane.
|
|
*
|
|
* The logical palette is cached in the GLGENwindow structure and is flushed
|
|
* to the driver when GenMcdRealizeLayerPalette is called.
|
|
*
|
|
* History:
|
|
* 16-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
int FASTCALL GenMcdGetLayerPaletteEntries(HDC hdc, int iLayerPlane,
|
|
int iStart, int cEntries,
|
|
COLORREF *pcr)
|
|
{
|
|
int iRet = 0;
|
|
GLGENwindow *pwnd;
|
|
GLWINDOWID gwid;
|
|
|
|
if (!pcr)
|
|
return iRet;
|
|
|
|
//
|
|
// Need to find the window.
|
|
//
|
|
|
|
WindowIdFromHdc(hdc, &gwid);
|
|
pwnd = pwndGetFromID(&gwid);
|
|
if (pwnd)
|
|
{
|
|
GLGENlayerInfo *plyri;
|
|
|
|
ENTER_WINCRIT(pwnd);
|
|
|
|
//
|
|
// Get the layer plane information.
|
|
//
|
|
|
|
plyri = plyriGet(pwnd, hdc, iLayerPlane);
|
|
if (plyri)
|
|
{
|
|
//
|
|
// Get the palette information from the layer plane structure.
|
|
//
|
|
|
|
iRet = min(plyri->cPalEntries - iStart, cEntries);
|
|
memcpy(pcr, &plyri->pPalEntries[iStart], iRet * sizeof(COLORREF));
|
|
}
|
|
|
|
pwndUnlock(pwnd, NULL);
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdRealizeLayerPalette
|
|
*
|
|
* Send the logical palette of the specified layer plane to the MCD driver.
|
|
* If the bRealize flag is TRUE, the palette is mapped into the physical
|
|
* palette of the specified layer plane. Otherwise, this is a signal to the
|
|
* driver that the physical palette is no longer needed.
|
|
*
|
|
* History:
|
|
* 16-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
int FASTCALL GenMcdRealizeLayerPalette(HDC hdc, int iLayerPlane,
|
|
BOOL bRealize)
|
|
{
|
|
int iRet = 0;
|
|
GLWINDOWID gwid;
|
|
|
|
//
|
|
// Cannot assume that MCD is intialized.
|
|
//
|
|
|
|
if (gpMcdTable || bInitMcd(hdc))
|
|
{
|
|
GLGENwindow *pwnd;
|
|
|
|
//
|
|
// Need to find the window.
|
|
//
|
|
|
|
WindowIdFromHdc(hdc, &gwid);
|
|
pwnd = pwndGetFromID(&gwid);
|
|
if (pwnd)
|
|
{
|
|
GLGENlayerInfo *plyri;
|
|
|
|
ENTER_WINCRIT(pwnd);
|
|
|
|
//
|
|
// Get the layer plane information.
|
|
//
|
|
|
|
plyri = plyriGet(pwnd, hdc, iLayerPlane);
|
|
if (plyri)
|
|
{
|
|
//
|
|
// Set the palette from the logical palette stored
|
|
// in the layer plane structure.
|
|
//
|
|
|
|
iRet = (gpMcdTable->pMCDSetLayerPalette)
|
|
(hdc, iLayerPlane, bRealize,
|
|
plyri->cPalEntries,
|
|
&plyri->pPalEntries[0]);
|
|
}
|
|
|
|
pwndUnlock(pwnd, NULL);
|
|
}
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdSwapLayerBuffers
|
|
*
|
|
* Swap the individual layer planes specified in fuFlags.
|
|
*
|
|
* History:
|
|
* 16-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL FASTCALL GenMcdSwapLayerBuffers(HDC hdc, UINT fuFlags)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
GLGENwindow *pwnd;
|
|
GLWINDOWID gwid;
|
|
|
|
//
|
|
// Need the window.
|
|
//
|
|
|
|
WindowIdFromHdc(hdc, &gwid);
|
|
pwnd = pwndGetFromID(&gwid);
|
|
if (pwnd)
|
|
{
|
|
MCDCONTEXT McdContextTmp;
|
|
|
|
ENTER_WINCRIT(pwnd);
|
|
|
|
//
|
|
// From the window, we can get the buffers struct.
|
|
//
|
|
|
|
if (pwnd->buffers != NULL)
|
|
{
|
|
__GLGENbuffers *buffers = pwnd->buffers;
|
|
|
|
//
|
|
// Call MCDSwap if we can (MCD context is required).
|
|
//
|
|
|
|
if (buffers->pMcdSurf)
|
|
{
|
|
ASSERTOPENGL(gpMcdTable,
|
|
"GenMcdSwapLayerBuffers: "
|
|
"mcd32.dll not initialized\n");
|
|
|
|
McdContextTmp.hdc = hdc;
|
|
|
|
bRet = (gpMcdTable->pMCDSwap)(&McdContextTmp, fuFlags);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Release the window.
|
|
//
|
|
|
|
pwndUnlock(pwnd, NULL);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdatePixelState
|
|
*
|
|
* Update MCD pixel state from the OpenGL state.
|
|
*
|
|
* This call only adds a state structure to the current state command.
|
|
* It is assumed that the caller has already called MCDBeginState and
|
|
* will call MCDFlushState.
|
|
*
|
|
* Note: pixel maps (glPixelMap) are not updated by this function. Because
|
|
* they are not used often, they are delayed but rather flushed to the driver
|
|
* immediately.
|
|
*
|
|
* History:
|
|
* 27-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdUpdatePixelState(__GLGENcontext *gengc)
|
|
{
|
|
__GLcontext *gc = &gengc->gc;
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
MCDPIXELSTATE McdPixelState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdUpdatePixelState: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdatePixelState: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Compute MCD pixel state from the current OpenGL context state.
|
|
//
|
|
|
|
//
|
|
// Pixel transfer modes.
|
|
//
|
|
// MCDPIXELTRANSFER and __GLpixelTransferMode structures are the same.
|
|
//
|
|
|
|
McdPixelState.pixelTransferModes
|
|
= *((MCDPIXELTRANSFER *) &gengc->gc.state.pixel.transferMode);
|
|
|
|
//
|
|
// Pixel pack modes.
|
|
//
|
|
// MCDPIXELPACK and __GLpixelPackMode structures are the same.
|
|
//
|
|
|
|
McdPixelState.pixelPackModes
|
|
= *((MCDPIXELPACK *) &gengc->gc.state.pixel.packModes);
|
|
|
|
//
|
|
// Pixel unpack modes.
|
|
//
|
|
// MCDPIXELUNPACK and __GLpixelUnpackMode structures are the same.
|
|
//
|
|
|
|
McdPixelState.pixelUnpackModes
|
|
= *((MCDPIXELUNPACK *) &gengc->gc.state.pixel.unpackModes);
|
|
|
|
//
|
|
// Read buffer.
|
|
//
|
|
|
|
McdPixelState.readBuffer = gengc->gc.state.pixel.readBuffer;
|
|
|
|
//
|
|
// Current raster position.
|
|
//
|
|
|
|
McdPixelState.rasterPos = *((MCDCOORD *) &gengc->gc.state.current.rasterPos.window);
|
|
|
|
//
|
|
// Send MCDPIXELSTATE to the state cmd.
|
|
//
|
|
|
|
(gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_PIXEL_STATE,
|
|
&McdPixelState,
|
|
sizeof(McdPixelState));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdUpdateFineState
|
|
*
|
|
* Update fine-grained MCD state from the OpenGL state.
|
|
*
|
|
* This call only adds state structures to the current state command.
|
|
* It is assumed that the caller has already called MCDBeginState and
|
|
* will call MCDFlushState.
|
|
*
|
|
* History:
|
|
* 13-Mar-1997 -by- Drew Bliss [drewb]
|
|
* Created.
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdUpdateFineState(__GLGENcontext *gengc)
|
|
{
|
|
__GLcontext *gc = &gengc->gc;
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
MCDPIXELSTATE McdPixelState;
|
|
|
|
ASSERTOPENGL(pMcdState, "GenMcdUpdateFineState: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdUpdateFineState: "
|
|
"mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Compute MCD state from the current OpenGL context state.
|
|
//
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, ENABLES))
|
|
{
|
|
MCDENABLESTATE state;
|
|
|
|
state.enables = gc->state.enables.general;
|
|
(gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_ENABLE_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, TEXTURE))
|
|
{
|
|
MCDTEXTUREENABLESTATE state;
|
|
|
|
state.textureEnabled = gc->texture.textureEnabled;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_TEXTURE_ENABLE_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, FOG))
|
|
{
|
|
MCDFOGSTATE state;
|
|
|
|
*((__GLcolor *) &state.fogColor) = gc->state.fog.color;
|
|
state.fogIndex = gc->state.fog.index;
|
|
state.fogDensity = gc->state.fog.density;
|
|
state.fogStart = gc->state.fog.start;
|
|
state.fogEnd = gc->state.fog.end;
|
|
state.fogMode = gc->state.fog.mode;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_FOG_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, SHADEMODEL))
|
|
{
|
|
MCDSHADEMODELSTATE state;
|
|
|
|
state.shadeModel = gc->state.light.shadingModel;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_SHADEMODEL_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, POINTDRAW))
|
|
{
|
|
MCDPOINTDRAWSTATE state;
|
|
|
|
state.pointSize = gc->state.point.requestedSize;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_POINTDRAW_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, LINEDRAW))
|
|
{
|
|
MCDLINEDRAWSTATE state;
|
|
|
|
state.lineWidth = gc->state.line.requestedWidth;
|
|
state.lineStipplePattern = gc->state.line.stipple;
|
|
state.lineStippleRepeat = gc->state.line.stippleRepeat;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_LINEDRAW_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, POLYDRAW))
|
|
{
|
|
MCDPOLYDRAWSTATE state;
|
|
|
|
state.cullFaceMode = gc->state.polygon.cull;
|
|
state.frontFace = gc->state.polygon.frontFaceDirection;
|
|
state.polygonModeFront = gc->state.polygon.frontMode;
|
|
state.polygonModeBack = gc->state.polygon.backMode;
|
|
memcpy(&state.polygonStipple, &gc->state.polygonStipple.stipple,
|
|
sizeof(state.polygonStipple));
|
|
state.zOffsetFactor = gc->state.polygon.factor;
|
|
state.zOffsetUnits = gc->state.polygon.units;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_POLYDRAW_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, ALPHATEST))
|
|
{
|
|
MCDALPHATESTSTATE state;
|
|
|
|
state.alphaTestFunc = gc->state.raster.alphaFunction;
|
|
state.alphaTestRef = gc->state.raster.alphaReference;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_ALPHATEST_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, DEPTHTEST))
|
|
{
|
|
MCDDEPTHTESTSTATE state;
|
|
|
|
state.depthTestFunc = gc->state.depth.testFunc;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_DEPTHTEST_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, BLEND))
|
|
{
|
|
MCDBLENDSTATE state;
|
|
|
|
state.blendSrc = gc->state.raster.blendSrc;
|
|
state.blendDst = gc->state.raster.blendDst;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_BLEND_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, LOGICOP))
|
|
{
|
|
MCDLOGICOPSTATE state;
|
|
|
|
state.logicOpMode = gc->state.raster.logicOp;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_LOGICOP_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, FBUFCTRL))
|
|
{
|
|
MCDFRAMEBUFSTATE state;
|
|
|
|
state.drawBuffer = gc->state.raster.drawBuffer;
|
|
state.indexWritemask = gc->state.raster.writeMask;
|
|
state.colorWritemask[0] = gc->state.raster.rMask;
|
|
state.colorWritemask[1] = gc->state.raster.gMask;
|
|
state.colorWritemask[2] = gc->state.raster.bMask;
|
|
state.colorWritemask[3] = gc->state.raster.aMask;
|
|
state.depthWritemask = gc->state.depth.writeEnable;
|
|
|
|
// To be consistent, we will scale the clear color to whatever
|
|
// the MCD driver specified:
|
|
|
|
state.colorClearValue.r =
|
|
gc->state.raster.clear.r * gc->redVertexScale;
|
|
state.colorClearValue.g =
|
|
gc->state.raster.clear.g * gc->greenVertexScale;
|
|
state.colorClearValue.b =
|
|
gc->state.raster.clear.b * gc->blueVertexScale;
|
|
state.colorClearValue.a =
|
|
gc->state.raster.clear.a * gc->alphaVertexScale;
|
|
|
|
state.indexClearValue = gc->state.raster.clearIndex;
|
|
state.stencilClearValue = (USHORT) gc->state.stencil.clear;
|
|
|
|
state.depthClearValue = (MCDDOUBLE) (gc->state.depth.clear *
|
|
gengc->genAccel.zDevScale);
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_FRAMEBUF_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, LIGHTMODEL))
|
|
{
|
|
MCDLIGHTMODELSTATE state;
|
|
|
|
*((__GLcolor *)&state.ambient) = gc->state.light.model.ambient;
|
|
state.localViewer = gc->state.light.model.localViewer;
|
|
state.twoSided = gc->state.light.model.twoSided;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_LIGHT_MODEL_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, HINTS))
|
|
{
|
|
MCDHINTSTATE state;
|
|
|
|
state.perspectiveCorrectionHint =
|
|
gc->state.hints.perspectiveCorrection;
|
|
state.pointSmoothHint = gc->state.hints.pointSmooth;
|
|
state.lineSmoothHint = gc->state.hints.lineSmooth;
|
|
state.polygonSmoothHint = gc->state.hints.polygonSmooth;
|
|
state.fogHint = gc->state.hints.fog;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_HINT_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, CLIPCTRL))
|
|
{
|
|
MCDCLIPSTATE state;
|
|
ULONG i, mask, numClipPlanes;
|
|
|
|
memset(state.userClipPlanes, 0, sizeof(state.userClipPlanes));
|
|
memset(state.userClipPlanesInv, 0, sizeof(state.userClipPlanesInv));
|
|
|
|
//
|
|
// Number of user defined clip planes should match. However,
|
|
// rather than assume this, let's take the min and be robust.
|
|
//
|
|
|
|
ASSERTOPENGL(sizeof(__GLcoord) == sizeof(MCDCOORD),
|
|
"GenMcdUpdateFineState: coord struct mismatch\n");
|
|
|
|
ASSERTOPENGL(MCD_MAX_USER_CLIP_PLANES ==
|
|
gc->constants.numberOfClipPlanes,
|
|
"GenMcdUpdateFineState: num clip planes mismatch\n");
|
|
|
|
numClipPlanes = min(MCD_MAX_USER_CLIP_PLANES,
|
|
gc->constants.numberOfClipPlanes);
|
|
|
|
state.userClipEnables = gc->state.enables.clipPlanes;
|
|
|
|
for (i = 0, mask = 1; i < numClipPlanes; i++, mask <<= 1)
|
|
{
|
|
if (mask & gc->state.enables.clipPlanes)
|
|
{
|
|
state.userClipPlanes[i] =
|
|
*(MCDCOORD *)&gc->state.transform.eyeClipPlanesSet[i];
|
|
state.userClipPlanesInv[i] =
|
|
*(MCDCOORD *)&gc->state.transform.eyeClipPlanes[i];
|
|
}
|
|
}
|
|
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_CLIP_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, STENCILTEST))
|
|
{
|
|
MCDSTENCILTESTSTATE state;
|
|
|
|
state.stencilTestFunc = gc->state.stencil.testFunc;
|
|
state.stencilMask = (USHORT) gc->state.stencil.mask;
|
|
state.stencilRef = (USHORT) gc->state.stencil.reference;
|
|
state.stencilFail = gc->state.stencil.fail;
|
|
state.stencilDepthFail = gc->state.stencil.depthFail;
|
|
state.stencilDepthPass = gc->state.stencil.depthPass;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_STENCILTEST_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
//
|
|
// The rest of the state is only interesting to a 2.0 driver,
|
|
// so only send it to a 2.0 driver.
|
|
//
|
|
|
|
if (!SUPPORTS_20())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, TEXTRANSFORM))
|
|
{
|
|
MCDTEXTURETRANSFORMSTATE state;
|
|
|
|
ASSERTOPENGL(sizeof(gc->transform.texture->matrix) ==
|
|
sizeof(MCDMATRIX),
|
|
"Matrix size mismatch\n");
|
|
|
|
memcpy(&state.transform, &gc->transform.texture->matrix,
|
|
sizeof(state.transform));
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_TEXTURE_TRANSFORM_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, TEXGEN))
|
|
{
|
|
MCDTEXTUREGENERATIONSTATE state;
|
|
|
|
ASSERTOPENGL(sizeof(__GLtextureCoordState) ==
|
|
sizeof(MCDTEXTURECOORDGENERATION),
|
|
"MCDTEXTURECOORDGENERATION mismatch\n");
|
|
|
|
*(__GLtextureCoordState *)&state.s = gc->state.texture.s;
|
|
*(__GLtextureCoordState *)&state.t = gc->state.texture.t;
|
|
*(__GLtextureCoordState *)&state.r = gc->state.texture.r;
|
|
*(__GLtextureCoordState *)&state.q = gc->state.texture.q;
|
|
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_TEXTURE_GENERATION_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, MATERIAL))
|
|
{
|
|
MCDMATERIALSTATE state;
|
|
|
|
ASSERTOPENGL(sizeof(MCDMATERIAL) == sizeof(__GLmaterialState),
|
|
"Material size mismatch\n");
|
|
|
|
*(__GLmaterialState *)&state.materials[MCDVERTEX_FRONTFACE] =
|
|
gc->state.light.front;
|
|
*(__GLmaterialState *)&state.materials[MCDVERTEX_BACKFACE] =
|
|
gc->state.light.back;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_MATERIAL_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, LIGHTS))
|
|
{
|
|
// Extra light is to hold the MCDLIGHTSTATE
|
|
MCDLIGHT lights[MCD_MAX_LIGHTS+1];
|
|
MCDLIGHT *light;
|
|
MCDLIGHTSOURCESTATE *state;
|
|
__GLlightSourceState *lss;
|
|
ULONG bit;
|
|
|
|
ASSERTOPENGL(sizeof(MCDLIGHTSOURCESTATE) <= sizeof(MCDLIGHT),
|
|
"MCDLIGHTSTATE too large\n");
|
|
ASSERTOPENGL(gc->constants.numberOfLights <= MCD_MAX_LIGHTS,
|
|
"Too many lights\n");
|
|
ASSERTOPENGL(sizeof(__GLlightSourceState) >= sizeof(MCDLIGHT),
|
|
"__GLlightSourceState too small\n");
|
|
|
|
// We attempt to optimize this state request by only
|
|
// sending down the lights that have changed.
|
|
|
|
light = &lights[1];
|
|
state = (MCDLIGHTSOURCESTATE *)
|
|
((BYTE *)light - sizeof(MCDLIGHTSOURCESTATE));
|
|
|
|
state->enables = gc->state.enables.lights;
|
|
state->changed = gc->state.light.dirtyLights;
|
|
gc->state.light.dirtyLights = 0;
|
|
|
|
bit = 1;
|
|
lss = gc->state.light.source;
|
|
while (bit < (1UL << gc->constants.numberOfLights))
|
|
{
|
|
if (state->changed & bit)
|
|
{
|
|
// MCDLIGHT is a subset of __GLlightSourceState.
|
|
memcpy(light, lss, sizeof(MCDLIGHT));
|
|
light++;
|
|
}
|
|
|
|
bit <<= 1;
|
|
lss++;
|
|
}
|
|
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_LIGHT_SOURCE_STATE,
|
|
state, (ULONG)((BYTE *)light-(BYTE *)state));
|
|
}
|
|
|
|
if (MCD_STATE_DIRTYTEST(gengc, COLORMATERIAL))
|
|
{
|
|
MCDCOLORMATERIALSTATE state;
|
|
|
|
state.face = gc->state.light.colorMaterialFace;
|
|
state.mode = gc->state.light.colorMaterialParam;
|
|
(*gpMcdTable->pMCDAddStateStruct)(pMcdState->McdCmdBatch.pv,
|
|
MCD_COLOR_MATERIAL_STATE,
|
|
&state, sizeof(state));
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdDrawPix
|
|
*
|
|
* Stub to call MCDDrawPixels.
|
|
*
|
|
* History:
|
|
* 27-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
ULONG FASTCALL GenMcdDrawPix(__GLGENcontext *gengc, ULONG width,
|
|
ULONG height, ULONG format, ULONG type,
|
|
VOID *pPixels, BOOL packed)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdDrawPix: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdDrawPix: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Before calling MCD to draw, flush state.
|
|
//
|
|
|
|
vFlushDirtyState(gengc);
|
|
|
|
return (gpMcdTable->pMCDDrawPixels)(&gengc->pMcdState->McdContext,
|
|
width, height, format, type,
|
|
pPixels, packed);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdReadPix
|
|
*
|
|
* Stub to call MCDReadPixels.
|
|
*
|
|
* History:
|
|
* 27-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
ULONG FASTCALL GenMcdReadPix(__GLGENcontext *gengc, LONG x, LONG y,
|
|
ULONG width, ULONG height, ULONG format,
|
|
ULONG type, VOID *pPixels)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdReadPix: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdReadPix: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Before calling MCD to draw, flush state.
|
|
//
|
|
|
|
vFlushDirtyState(gengc);
|
|
|
|
return (gpMcdTable->pMCDReadPixels)(&gengc->pMcdState->McdContext,
|
|
x, y, width, height, format, type,
|
|
pPixels);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdCopyPix
|
|
*
|
|
* Stub to call MCDCopyPixels.
|
|
*
|
|
* History:
|
|
* 27-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
ULONG FASTCALL GenMcdCopyPix(__GLGENcontext *gengc, LONG x, LONG y,
|
|
ULONG width, ULONG height, ULONG type)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdCopyPix: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdCopyPix: mcd32.dll not initialized\n");
|
|
|
|
//
|
|
// Before calling MCD to draw, flush state.
|
|
//
|
|
|
|
vFlushDirtyState(gengc);
|
|
|
|
return (gpMcdTable->pMCDCopyPixels)(&gengc->pMcdState->McdContext,
|
|
x, y, width, height, type);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdPixelMap
|
|
*
|
|
* Stub to call MCDPixelMap.
|
|
*
|
|
* History:
|
|
* 27-May-1996 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
ULONG FASTCALL GenMcdPixelMap(__GLGENcontext *gengc, ULONG mapType,
|
|
ULONG mapSize, VOID *pMap)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdPixelMap: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdPixelMap: mcd32.dll not initialized\n");
|
|
|
|
return (gpMcdTable->pMCDPixelMap)(&gengc->pMcdState->McdContext,
|
|
mapType, mapSize, pMap);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* GenMcdDestroyWindow
|
|
*
|
|
* Passes on GLGENwindow cleanup notifications
|
|
*
|
|
* History:
|
|
* Thu Sep 19 12:01:40 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL GenMcdDestroyWindow(GLGENwindow *pwnd)
|
|
{
|
|
HDC hdc;
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdDestroyWindow: "
|
|
"mcd32.dll not initialized\n");
|
|
|
|
// The HDC stored in the pwnd may no longer be valid, so if there's
|
|
// a window associated with the pwnd get a fresh DC.
|
|
if (pwnd->gwid.iType == GLWID_DDRAW ||
|
|
pwnd->gwid.hwnd == NULL)
|
|
{
|
|
hdc = pwnd->gwid.hdc;
|
|
}
|
|
else
|
|
{
|
|
hdc = GetDC(pwnd->gwid.hwnd);
|
|
if (hdc == NULL)
|
|
{
|
|
WARNING("GenMcdDestroyWindow unable to GetDC\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
(gpMcdTable->pMCDDestroyWindow)(hdc, pwnd->dwMcdWindow);
|
|
|
|
if (pwnd->gwid.iType != GLWID_DDRAW &&
|
|
pwnd->gwid.hwnd != NULL)
|
|
{
|
|
ReleaseDC(pwnd->gwid.hwnd, hdc);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* GenMcdGetTextureFormats
|
|
*
|
|
* History:
|
|
* Thu Sep 26 18:34:49 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
int FASTCALL GenMcdGetTextureFormats(__GLGENcontext *gengc, int nFmts,
|
|
struct _DDSURFACEDESC *pddsd)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
|
|
ASSERTOPENGL(gengc->pMcdState,
|
|
"GenMcdGetMcdTextureFormats: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable,
|
|
"GenMcdGetMcdTextureFormats: mcd32.dll not initialized\n");
|
|
|
|
return (gpMcdTable->pMCDGetTextureFormats)(&gengc->pMcdState->McdContext,
|
|
nFmts, pddsd);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* GenMcdSwapMultiple
|
|
*
|
|
* History:
|
|
* Tue Oct 15 12:51:09 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DWORD FASTCALL GenMcdSwapMultiple(UINT cBuffers, GENMCDSWAP *pgms)
|
|
{
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable, "GenMcdSwapMultiple: "
|
|
"mcd32.dll not initialized\n");
|
|
|
|
return (gpMcdTable->pMCDSwapMultiple)(pgms[0].pwswap->hdc, cBuffers, pgms);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GenMcdProcessPrim
|
|
*
|
|
* Process the primitives in the POLYARRAY/POLYDATA array pointed to by pa.
|
|
* The primitives are chained together as a linked list terminated by a
|
|
* NULL. The return value is a pointer to the first unhandled primitive
|
|
* (NULL if the entire chain is successfully processed).
|
|
*
|
|
* This routine differs from GenMcdProcessPrim in that it is the MCD 2.0
|
|
* entry point for front-end processors and so calls MCDrvProcess rather
|
|
* than MCDrvDraw.
|
|
*
|
|
* Returns:
|
|
* NULL if entire batch is processed; otherwise, return value is a pointer
|
|
* to the unhandled portion of the chain.
|
|
*
|
|
* History:
|
|
* 13-Mar-1997 -by- Drew Bliss [drewb]
|
|
* Created from GenMcdDrawPrim.
|
|
\**************************************************************************/
|
|
|
|
POLYARRAY * FASTCALL GenMcdProcessPrim(__GLGENcontext *gengc, POLYARRAY *pa,
|
|
ULONG cmdFlagsAll, ULONG primFlags,
|
|
MCDTRANSFORM *pMCDTransform,
|
|
MCDMATERIALCHANGES *pMCDMatChanges)
|
|
{
|
|
GENMCDSTATE *pMcdState = gengc->pMcdState;
|
|
int levels;
|
|
LPDIRECTDRAWSURFACE *pdds;
|
|
|
|
if (!SUPPORTS_20())
|
|
{
|
|
return pa;
|
|
}
|
|
|
|
ASSERTOPENGL(gengc->pMcdState, "GenMcdProcessPrim: null pMcdState\n");
|
|
|
|
//
|
|
// This function can assume that MCD entry point table is already
|
|
// initialized as we cannot get here without MCD already having been
|
|
// called.
|
|
//
|
|
|
|
ASSERTOPENGL(gpMcdTable,
|
|
"GenMcdProcessPrim: mcd32.dll not initialized\n");
|
|
|
|
#if DBG
|
|
{
|
|
LONG lOffset;
|
|
|
|
lOffset = (LONG) ((BYTE *) pa - (BYTE *) pMcdState->pMcdPrimBatch->pv);
|
|
|
|
ASSERTOPENGL(
|
|
(lOffset >= 0) &&
|
|
(lOffset < (LONG) pMcdState->pMcdPrimBatch->size),
|
|
"GenMcdProcessPrim: pa not in shared mem window\n");
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Before calling MCD to draw, flush state.
|
|
//
|
|
|
|
vFlushDirtyState(gengc);
|
|
|
|
#ifdef AUTOMATIC_SURF_LOCK
|
|
levels = gengc->gc.texture.ddtex.levels;
|
|
if (levels > 0 &&
|
|
gengc->gc.texture.ddtex.texobj.loadKey != 0)
|
|
{
|
|
pdds = gengc->gc.texture.ddtex.pdds;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
levels = 0;
|
|
pdds = NULL;
|
|
}
|
|
|
|
return (POLYARRAY *)
|
|
(gpMcdTable->pMCDProcessBatch2)(&pMcdState->McdContext,
|
|
pMcdState->McdCmdBatch.pv,
|
|
pMcdState->pMcdPrimBatch->pv,
|
|
(PVOID) pa, levels, pdds,
|
|
cmdFlagsAll, primFlags,
|
|
pMCDTransform, pMCDMatChanges);
|
|
}
|
|
|
|
#endif
|