|
|
/******************************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
|