windows-nt/Source/XPSP1/NT/multimedia/opengl/server/generic/mcdcx.c

4266 lines
131 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/******************************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