/******************************Module*Header*******************************\ * Module Name: genaccel.c * * * * This module provides support routines for acceleration functions. * * * * Created: 18-Feb-1994 * * Author: Otto Berkes [ottob] * * * * Copyright (c) 1994 Microsoft Corporation * \**************************************************************************/ #include "precomp.h" #pragma hdrstop #include "genline.h" #ifdef GL_WIN_specular_fog #define DO_NICEST_FOG(gc)\ ((gc->state.hints.fog == GL_NICEST) && !(gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)) #else //GL_WIN_specular_fog #define DO_NICEST_FOG(gc)\ (gc->state.hints.fog == GL_NICEST) #endif //GL_WIN_specular_fog static ULONG internalSolidTexture[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}; GENTEXCACHE *GetGenTexCache(__GLcontext *gc, __GLtexture *tex) { ULONG size; GENTEXCACHE *pGenTex; ULONG internalFormat; GLuint modeFlags = gc->polygon.shader.modeFlags; // Replace maps are only used for a subset of possible modes // 8 or 16bpp // 16-bit Z // // No dithering. Since dithering can turn on and off there // are two cases: // Dither off at TexImage time but on at texturing time - // We create a map that's unused // Dither on and then off - We won't create a map at // TexImage time but it'll be created on the fly when // dithering is turned on and everything is repicked // // Replace maps aren't created for DirectDraw textures because // the data isn't constant if (GENACCEL(gc).bpp < 8 || GENACCEL(gc).bpp > 16 || ((modeFlags & (__GL_SHADE_DEPTH_TEST | __GL_SHADE_DEPTH_ITER)) && gc->modes.depthBits > 16) || (modeFlags & __GL_SHADE_DITHER) || gc->texture.ddtex.levels > 0) { return NULL; } internalFormat = tex->level[0].internalFormat; // We only support 8-bit palettes that are fully populated if (internalFormat == GL_COLOR_INDEX16_EXT || (internalFormat == GL_COLOR_INDEX8_EXT && tex->paletteSize != 256)) { return NULL; } pGenTex = tex->pvUser; // Check and see whether the cached information can be reused // for the texture passed in if (pGenTex != NULL) { // gc's don't match so this must be a shared texture // Don't attempt to create a replace map for this gc if (gc != pGenTex->gc) { return NULL; } // Size and format must match to reuse the existing data area // If they don't, release the existing buffer. A new one // will then be allocated if (internalFormat == GL_COLOR_INDEX8_EXT) { if (pGenTex->internalFormat != internalFormat || pGenTex->width != tex->paletteTotalSize) { GCFREE(gc, pGenTex); tex->pvUser = NULL; } } else { if (pGenTex->internalFormat != internalFormat || pGenTex->width != tex->level[0].width || pGenTex->height != tex->level[0].height) { GCFREE(gc, pGenTex); tex->pvUser = NULL; } } } if (tex->pvUser == NULL) { if (internalFormat == GL_COLOR_INDEX8_EXT) { size = tex->paletteTotalSize * sizeof(DWORD); } else { size = tex->level[0].width * tex->level[0].height * GENACCEL(gc).xMultiplier; } pGenTex = (GENTEXCACHE *)GCALLOC(gc, size + sizeof(GENTEXCACHE)); if (pGenTex != NULL) { tex->pvUser = pGenTex; pGenTex->gc = gc; pGenTex->paletteTimeStamp = ((__GLGENcontext *)gc)->PaletteTimestamp; if (internalFormat == GL_COLOR_INDEX8_EXT) { pGenTex->height = 0; pGenTex->width = tex->paletteTotalSize; } else { pGenTex->height = tex->level[0].height; pGenTex->width = tex->level[0].width; } pGenTex->internalFormat = internalFormat; pGenTex->texImageReplace = (UCHAR *)(pGenTex+1); } } return pGenTex; } BOOL FASTCALL __fastGenLoadTexImage(__GLcontext *gc, __GLtexture *tex) { UCHAR *texBuffer; GLint internalFormat = tex->level[0].internalFormat; GENTEXCACHE *pGenTex; if (tex->level[0].buffer == NULL || ((internalFormat != GL_BGR_EXT) && (internalFormat != GL_BGRA_EXT) && (internalFormat != GL_COLOR_INDEX8_EXT))) { return FALSE; } // OK, the texture doesn't have a compressed replace-mode format, so // make one... if ((internalFormat == GL_BGR_EXT) || (internalFormat == GL_BGRA_EXT)) { ULONG size; UCHAR *replaceBuffer; ULONG bytesPerPixel = GENACCEL(gc).xMultiplier; pGenTex = GetGenTexCache(gc, tex); if (pGenTex == NULL) { return FALSE; } texBuffer = (UCHAR *)tex->level[0].buffer; replaceBuffer = pGenTex->texImageReplace; { __GLcolorBuffer *cfb = gc->drawBuffer; ULONG rShift = cfb->redShift; ULONG gShift = cfb->greenShift; ULONG bShift = cfb->blueShift; ULONG rBits = ((__GLGENcontext *)gc)->gsurf.pfd.cRedBits; ULONG gBits = ((__GLGENcontext *)gc)->gsurf.pfd.cGreenBits; ULONG bBits = ((__GLGENcontext *)gc)->gsurf.pfd.cBlueBits; BYTE *pXlat = ((__GLGENcontext *)gc)->pajTranslateVector; ULONG i; size = tex->level[0].width * tex->level[0].height; for (i = 0; i < size; i++, texBuffer += 4) { ULONG color; color = ((((ULONG)texBuffer[2] << rBits) >> 8) << rShift) | ((((ULONG)texBuffer[1] << gBits) >> 8) << gShift) | ((((ULONG)texBuffer[0] << bBits) >> 8) << bShift); if (GENACCEL(gc).bpp == 8) *replaceBuffer = pXlat[color & 0xff]; else *((USHORT *)replaceBuffer) = (USHORT)color; replaceBuffer += bytesPerPixel; } } } else { ULONG size; ULONG *replaceBuffer; // If we don't have palette data yet we can't create the // fast version. It will be created when the ColorTable // call happens if (tex->paletteTotalData == NULL) { return FALSE; } pGenTex = GetGenTexCache(gc, tex); if (pGenTex == NULL) { return FALSE; } texBuffer = (UCHAR *)tex->paletteTotalData; replaceBuffer = (ULONG *)pGenTex->texImageReplace; size = tex->paletteTotalSize; { __GLcolorBuffer *cfb = gc->drawBuffer; ULONG rShift = cfb->redShift; ULONG gShift = cfb->greenShift; ULONG bShift = cfb->blueShift; ULONG rBits = ((__GLGENcontext *)gc)->gsurf.pfd.cRedBits; ULONG gBits = ((__GLGENcontext *)gc)->gsurf.pfd.cGreenBits; ULONG bBits = ((__GLGENcontext *)gc)->gsurf.pfd.cBlueBits; BYTE *pXlat = ((__GLGENcontext *)gc)->pajTranslateVector; ULONG i; for (i = 0; i < size; i++, texBuffer += 4) { ULONG color; color = ((((ULONG)texBuffer[2] << rBits) >> 8) << rShift) | ((((ULONG)texBuffer[1] << gBits) >> 8) << gShift) | ((((ULONG)texBuffer[0] << bBits) >> 8) << bShift); if (GENACCEL(gc).bpp == 8) color = pXlat[color & 0xff]; *replaceBuffer++ = (color | ((ULONG)texBuffer[3] << 24)); } } } GENACCEL(gc).texImageReplace = ((GENTEXCACHE *)tex->pvUser)->texImageReplace; return TRUE; } /* ** Pick the fastest triangle rendering implementation available based on ** the current mode set. Use any available accelerated resources if ** available, or use the generic routines for unsupported modes. */ void FASTCALL __fastGenCalcDeltas(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c); void FASTCALL __fastGenCalcDeltasTexRGBA(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c); void FASTCALL __fastGenDrvCalcDeltas(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c); void __fastGenSetInitialParameters(__GLcontext *gc, const __GLvertex *a, __GLfloat dx, __GLfloat dy); void __fastGenSetInitialParametersTexRGBA(__GLcontext *gc, const __GLvertex *a, __GLfloat dx, __GLfloat dy); void __ZippyFT( __GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c, GLboolean ccw); VOID FASTCALL InitAccelTextureValues(__GLcontext *gc, __GLtexture *tex) { ULONG wLog2; ULONG hLog2; GENACCEL(gc).tex = tex; GENACCEL(gc).texImage = (ULONG *)tex->level[0].buffer; if (tex->level[0].internalFormat == GL_COLOR_INDEX8_EXT || tex->level[0].internalFormat == GL_COLOR_INDEX16_EXT) { GENACCEL(gc).texPalette = (ULONG *)tex->paletteTotalData; } else { GENACCEL(gc).texPalette = NULL; } wLog2 = tex->level[0].widthLog2; hLog2 = tex->level[0].heightLog2; GENACCEL(gc).sMask = (~(~0 << wLog2)) << TEX_SCALESHIFT; GENACCEL(gc).tMask = (~(~0 << hLog2)) << TEX_SCALESHIFT; GENACCEL(gc).tShift = TEX_SCALESHIFT - (wLog2 + TEX_SHIFTPER4BPPTEXEL); GENACCEL(gc).tMaskSubDiv = (~(~0 << hLog2)) << (wLog2 + TEX_T_FRAC_BITS + TEX_SHIFTPER1BPPTEXEL); GENACCEL(gc).tShiftSubDiv = TEX_SCALESHIFT - (wLog2 + TEX_T_FRAC_BITS + TEX_SHIFTPER1BPPTEXEL); GENACCEL(gc).texXScale = (__GLfloat)tex->level[0].width * TEX_SCALEFACT; GENACCEL(gc).texYScale = (__GLfloat)tex->level[0].height * TEX_SCALEFACT; } BOOL FASTCALL bUseGenTriangles(__GLcontext *gc) { GLuint modeFlags = gc->polygon.shader.modeFlags; GLuint enables = gc->state.enables.general; __GLGENcontext *gengc = (__GLGENcontext *)gc; ULONG bpp = GENACCEL(gc).bpp; int iType; BOOL fZippy; BOOL bTryFastTexRGBA; PFNZIPPYSUB pfnZippySub; BOOL fUseFastGenSpan; GLboolean bMcdZ; ULONG internalFormat; ULONG textureMode; BOOL bRealTexture; BOOL bAccelDecal; if ((enables & (__GL_ALPHA_TEST_ENABLE | __GL_STENCIL_TEST_ENABLE)) || (modeFlags & (__GL_SHADE_STENCIL_TEST | __GL_SHADE_LOGICOP | __GL_SHADE_ALPHA_TEST | __GL_SHADE_SLOW_FOG #ifdef GL_WIN_specular_fog | __GL_SHADE_SPEC_FOG #endif //GL_WIN_specular_fog )) || !gc->state.raster.rMask || !gc->state.raster.gMask || !gc->state.raster.bMask || (gc->drawBuffer->buf.flags & COLORMASK_ON) || ALPHA_WRITE_ENABLED( gc->drawBuffer ) || (gengc->gsurf.pfd.cColorBits < 8) || ((modeFlags & __GL_SHADE_DEPTH_TEST) && (!gc->state.depth.writeEnable)) ) return FALSE; if (modeFlags & __GL_SHADE_TEXTURE) { internalFormat = gc->texture.currentTexture->level[0].internalFormat; textureMode = gc->state.texture.env[0].mode; bAccelDecal = (gc->texture.currentTexture->level[0].baseFormat != GL_RGBA); if (!((((textureMode == GL_DECAL) && bAccelDecal) || (textureMode == GL_REPLACE) || (textureMode == GL_MODULATE)) && (gc->texture.currentTexture && (gc->texture.currentTexture->params.minFilter == GL_NEAREST) && (gc->texture.currentTexture->params.magFilter == GL_NEAREST) && (gc->texture.currentTexture->params.sWrapMode == GL_REPEAT) && (gc->texture.currentTexture->params.tWrapMode == GL_REPEAT) && (gc->texture.currentTexture->level[0].border == 0) && (internalFormat == GL_BGR_EXT || internalFormat == GL_BGRA_EXT || internalFormat == GL_COLOR_INDEX8_EXT)))) return FALSE; InitAccelTextureValues(gc, gc->texture.currentTexture); } bMcdZ = ((((__GLGENcontext *)gc)->pMcdState != NULL) && (((__GLGENcontext *)gc)->pMcdState->pDepthSpan != NULL) && (((__GLGENcontext *)gc)->pMcdState->pMcdSurf != NULL) && !(((__GLGENcontext *)gc)->pMcdState->McdBuffers.mcdDepthBuf.bufFlags & MCDBUF_ENABLED)); bTryFastTexRGBA = ((gc->state.raster.drawBuffer != GL_FRONT_AND_BACK) && ((modeFlags & __GL_SHADE_DEPTH_TEST && modeFlags & __GL_SHADE_DEPTH_ITER) || (!(modeFlags & __GL_SHADE_DEPTH_TEST) && !(modeFlags & __GL_SHADE_DEPTH_ITER))) && (modeFlags & __GL_SHADE_STIPPLE) == 0); fZippy = (bTryFastTexRGBA && ((gc->drawBuffer->buf.flags & DIB_FORMAT) != 0) && ((gc->drawBuffer->buf.flags & MEMORY_DC) != 0) && gc->transform.reasonableViewport); GENACCEL(gc).flags &= ~( GEN_DITHER | GEN_RGBMODE | GEN_TEXTURE | GEN_SHADE | GEN_FASTZBUFFER | GEN_LESS | SURFACE_TYPE_DIB | GEN_TEXTURE_ORTHO ); if ((enables & __GL_BLEND_ENABLE) || (modeFlags & __GL_SHADE_TEXTURE)) { GENACCEL(gc).__fastCalcDeltaPtr = __fastGenCalcDeltasTexRGBA; GENACCEL(gc).__fastSetInitParamPtr = __fastGenSetInitialParametersTexRGBA; } else { GENACCEL(gc).__fastCalcDeltaPtr = __fastGenCalcDeltas; GENACCEL(gc).__fastSetInitParamPtr = __fastGenSetInitialParameters; } #ifdef GL_WIN_phong_shading if (modeFlags & __GL_SHADE_PHONG) { gc->procs.fillTriangle = __glFillPhongTriangle; } else #endif //GL_WIN_phong_shading { #ifdef _MCD_ // If MCD driver is being used, then we need to call the "floating // point state safe" version of fillTriangle. This version will // not attempt to span floating point operations over a call that // may invoke the MCD driver (which will corrupt the FP state). if (gengc->pMcdState) { gc->procs.fillTriangle = __fastGenMcdFillTriangle; } else { gc->procs.fillTriangle = __fastGenFillTriangle; } #else //_MCD_ gc->procs.fillTriangle = __fastGenFillTriangle; #endif //_MCD_ } // If we're doing perspective-corrected texturing, we will support // the following combinations: // z....... <, <= // alpha... src, 1-src // dither.. on/off // bpp..... 332, 555, 565, 888 // NOTE: We will always try this path first for general texturing. if ((modeFlags & __GL_SHADE_TEXTURE) || (enables & __GL_BLEND_ENABLE)) { LONG pixType = -1; if (gc->state.hints.perspectiveCorrection != GL_NICEST) GENACCEL(gc).flags |= GEN_TEXTURE_ORTHO; if (!bTryFastTexRGBA) goto perspTexPathFail; if ((enables & __GL_BLEND_ENABLE) && ((gc->state.raster.blendSrc != GL_SRC_ALPHA) || (gc->state.raster.blendDst != GL_ONE_MINUS_SRC_ALPHA))) return FALSE; if (!(modeFlags & __GL_SHADE_TEXTURE)) { if (!(modeFlags & __GL_SHADE_RGB)) goto perspTexPathFail; bRealTexture = FALSE; GENACCEL(gc).flags |= GEN_TEXTURE_ORTHO; GENACCEL(gc).texPalette = NULL; textureMode = GL_MODULATE; internalFormat = GL_BGRA_EXT; GENACCEL(gc).texImage = (ULONG *)internalSolidTexture; GENACCEL(gc).sMask = 0; GENACCEL(gc).tMask = 0; GENACCEL(gc).tShift = 0; GENACCEL(gc).tMaskSubDiv = 0; GENACCEL(gc).tShiftSubDiv = 0; } else { bRealTexture = TRUE; } if (bpp == 8) { if ((gengc->gc.drawBuffer->redShift == 0) && (gengc->gc.drawBuffer->greenShift == 3) && (gengc->gc.drawBuffer->blueShift == 6)) pixType = 0; } else if (bpp == 16) { if ((gengc->gc.drawBuffer->greenShift == 5) && (gengc->gc.drawBuffer->blueShift == 0)) { if (gengc->gc.drawBuffer->redShift == 10) pixType = 1; else if (gengc->gc.drawBuffer->redShift == 11) pixType = 2; } } else if ((bpp == 32) || (bpp == 24)) { if ((gengc->gc.drawBuffer->redShift == 16) && (gengc->gc.drawBuffer->greenShift == 8) && (gengc->gc.drawBuffer->blueShift == 0)) pixType = 3; } if (pixType < 0) goto perspTexPathFail; pixType *= 6; if (modeFlags & __GL_SHADE_DEPTH_ITER) { if (bMcdZ) goto perspTexPathFail; if (!((gc->state.depth.testFunc == GL_LESS) || (gc->state.depth.testFunc == GL_LEQUAL))) goto perspTexPathFail; if (gc->modes.depthBits > 16) goto perspTexPathFail; if (gc->state.depth.testFunc == GL_LEQUAL) pixType += 1; else pixType += 2; GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTZ; } if (enables & __GL_BLEND_ENABLE) pixType += 3; // Note: For selecting the sub-triangle filling routine, assume // that we will use one of the "zippy" routines. Then, check at the // end whether or not we can actually do this, or if we have to fall // back to a more generic (and slower) routine. if (internalFormat != GL_COLOR_INDEX8_EXT && internalFormat != GL_COLOR_INDEX16_EXT) { // // Handle full RGB(A) textures // // Check if we can support the size... if (bRealTexture && GENACCEL(gc).tex && ((GENACCEL(gc).tex->level[0].widthLog2 > TEX_MAX_SIZE_LOG2) || (GENACCEL(gc).tex->level[0].heightLog2 > TEX_MAX_SIZE_LOG2))) goto perspTexPathFail; if ((textureMode == GL_DECAL) || (textureMode == GL_REPLACE)) { // we don't handle the goofy alpha case for decal... if ((textureMode == GL_DECAL) && (enables & __GL_BLEND_ENABLE)) return FALSE; // If we're not dithering, we can go with the compressed // texture format. Otherwise, we're forced to use flat-shading // procs to get the texture colors to dither properly. Ouch... // We'd like to also go through this path if a DirectDraw // texture is used because replace maps can't be created, // but they only work with dithering if (modeFlags & __GL_SHADE_DITHER) { GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexFlatFuncs[pixType]; } else { if ((bpp >= 8 && bpp <= 16) && !(enables & __GL_BLEND_ENABLE)) { // handle the case where we can use compressed textures // for optimal performance. We do this for bit depths // <= 16 bits, no dithering, and no blending. if (!GENACCEL(gc).tex->pvUser) { if (!__fastGenLoadTexImage(gc, GENACCEL(gc).tex)) return FALSE; } else { // If the compressed texture image was created for // another gc, revert to using the RGBA image. // We do this by using the alpha paths. // // NOTE: This logic depends on A being forced to // 1 for all RGB textures. if (gc != ((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->gc) { pixType += 3; } else { // Check that the cached data is the right size ASSERTOPENGL(((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->width == GENACCEL(gc).tex->level[0].width && ((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->height == GENACCEL(gc).tex->level[0].height, "Cached texture size mismatch\n"); } } } GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexReplaceFuncs[pixType]; } if (!(modeFlags & __GL_SHADE_DEPTH_ITER)) GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTTex; } else if (textureMode == GL_MODULATE) { if (modeFlags & __GL_SHADE_SMOOTH) { GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexSmoothFuncs[pixType]; if (!(modeFlags & __GL_SHADE_DEPTH_ITER)) GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTRGBTex; } else { GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexFlatFuncs[pixType]; if (!(modeFlags & __GL_SHADE_DEPTH_ITER)) GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTTex; } } } else { // // Handle palettized textures // // Check if we can support the size... if (bRealTexture && GENACCEL(gc).tex && ((GENACCEL(gc).tex->level[0].widthLog2 > TEX_MAX_SIZE_LOG2) || (GENACCEL(gc).tex->level[0].heightLog2 > TEX_MAX_SIZE_LOG2))) return FALSE; if ((textureMode == GL_DECAL) || (textureMode == GL_REPLACE)) { // we don't handle the goofy alpha case for decal... if ((textureMode == GL_DECAL) && (enables & __GL_BLEND_ENABLE)) return FALSE; // If we're not dithering, we can go with the compressed // texture format. Otherwise, we're forced to use flat-shading // procs to get the texture colors to dither properly. Ouch... // We'd like to also go through this path if a DirectDraw // texture is used because replace maps can't be created, // but they only work with dithering if (modeFlags & __GL_SHADE_DITHER) { GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexFlatFuncs[pixType]; } else { GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexPalReplaceFuncs[pixType]; if (bpp >= 8 && bpp <= 16) { // handle the case where we can use compressed paletted // textures for optimal performance. We do this for // bit depths <= 16 bits with no dithering. if (!GENACCEL(gc).tex->pvUser) { if (!__fastGenLoadTexImage(gc, GENACCEL(gc).tex)) return FALSE; } else { // If the compressed texture image was created for // another gc, we have no choice but to fall back to flat shading. // We should find a better solution for this... if (gc != ((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->gc) { GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexFlatFuncs[pixType]; } else { ASSERTOPENGL(((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->width == GENACCEL(gc).tex->paletteTotalSize, "Cached texture size mismatch\n"); } } } } if (!(modeFlags & __GL_SHADE_DEPTH_ITER)) GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTTex; } else if (textureMode == GL_MODULATE) { if (modeFlags & __GL_SHADE_SMOOTH) { GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexSmoothFuncs[pixType]; if (!(modeFlags & __GL_SHADE_DEPTH_ITER)) GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTRGBTex; } else { GENACCEL(gc).__fastTexSpanFuncPtr = __fastPerspTexFlatFuncs[pixType]; if (!(modeFlags & __GL_SHADE_DEPTH_ITER)) GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTTex; } } } if (!fZippy) GENACCEL(gc).__fastFillSubTrianglePtr = __fastGenFillSubTriangleTexRGBA; else GENACCEL(gc).flags |= SURFACE_TYPE_DIB; return TRUE; } perspTexPathFail: // We don't support any alpha modes yet... if (enables & __GL_BLEND_ENABLE) return FALSE; fUseFastGenSpan = FALSE; if (bpp == 8) { iType = 2; if ( (gengc->gc.drawBuffer->redShift != 0) || (gengc->gc.drawBuffer->greenShift != 3) || (gengc->gc.drawBuffer->blueShift != 6) ) { fUseFastGenSpan = TRUE; } } else if (bpp == 16) { if ( (gengc->gc.drawBuffer->greenShift == 5) && (gengc->gc.drawBuffer->blueShift == 0) ) { if (gengc->gc.drawBuffer->redShift == 10) { iType = 3; } else if (gengc->gc.drawBuffer->redShift == 11) { iType = 4; } else { iType = 3; fUseFastGenSpan = TRUE; } } else { iType = 3; fUseFastGenSpan = TRUE; } } else { if (bpp == 24) { iType = 0; } else { iType = 1; } if ( (gengc->gc.drawBuffer->redShift != 16) || (gengc->gc.drawBuffer->greenShift != 8) || (gengc->gc.drawBuffer->blueShift != 0) ) { fUseFastGenSpan = TRUE; } } if (modeFlags & __GL_SHADE_DITHER) { if ( (bpp == 8) || (bpp == 16) || ((modeFlags & __GL_SHADE_DEPTH_ITER) == 0) ) { GENACCEL(gc).flags |= GEN_DITHER; } iType += 5; } // Use the accelerated span functions (with no inline z-buffering) if // we support the z-buffer function AND we're not using hardware // z-buffering: if (modeFlags & __GL_SHADE_DEPTH_ITER) { if (bMcdZ) { fUseFastGenSpan = TRUE; } else if (!fZippy) { fUseFastGenSpan = TRUE; } else if (gc->state.depth.testFunc == GL_LESS) { GENACCEL(gc).flags |= GEN_LESS; } else if (gc->state.depth.testFunc != GL_LEQUAL) { fUseFastGenSpan = TRUE; } iType += 10; } if (modeFlags & __GL_SHADE_RGB) { GENACCEL(gc).flags |= GEN_RGBMODE; pfnZippySub = __ZippyFSTRGB; if (modeFlags & __GL_SHADE_TEXTURE) { GENACCEL(gc).flags |= (GEN_TEXTURE | GEN_TEXTURE_ORTHO); if (gc->state.hints.perspectiveCorrection == GL_NICEST) return FALSE; if (internalFormat == GL_COLOR_INDEX8_EXT || internalFormat == GL_COLOR_INDEX16_EXT) return FALSE; if (textureMode == GL_DECAL) { if (modeFlags & __GL_SHADE_DITHER) GENACCEL(gc).__fastTexSpanFuncPtr = __fastGenTexFuncs[iType]; else GENACCEL(gc).__fastTexSpanFuncPtr = __fastGenTexDecalFuncs[iType]; pfnZippySub = __ZippyFSTTex; } else { GENACCEL(gc).flags |= GEN_SHADE; pfnZippySub = __ZippyFSTRGBTex; GENACCEL(gc).__fastTexSpanFuncPtr = __fastGenTexFuncs[iType]; } if (GENACCEL(gc).__fastTexSpanFuncPtr == __fastGenSpan) { fUseFastGenSpan = TRUE; } } else { GENACCEL(gc).__fastSmoothSpanFuncPtr = __fastGenRGBFuncs[iType]; GENACCEL(gc).__fastFlatSpanFuncPtr = __fastGenRGBFlatFuncs[iType]; if (GENACCEL(gc).__fastSmoothSpanFuncPtr == __fastGenSpan) { fUseFastGenSpan = TRUE; } } } else { pfnZippySub = __ZippyFSTCI; GENACCEL(gc).__fastSmoothSpanFuncPtr = __fastGenCIFuncs[iType]; GENACCEL(gc).__fastFlatSpanFuncPtr = __fastGenCIFlatFuncs[iType]; } if (modeFlags & __GL_SHADE_STIPPLE) { fUseFastGenSpan = TRUE; } if (fUseFastGenSpan) { GENACCEL(gc).__fastTexSpanFuncPtr = __fastGenSpan; GENACCEL(gc).__fastSmoothSpanFuncPtr = __fastGenSpan; GENACCEL(gc).__fastFlatSpanFuncPtr = __fastGenSpan; GENACCEL(gc).__fastFillSubTrianglePtr = __fastGenFillSubTriangle; } else { if (fZippy) { GENACCEL(gc).flags |= SURFACE_TYPE_DIB; if ( (iType == 2) && ( (modeFlags & (__GL_SHADE_RGB | __GL_SHADE_SMOOTH) ) == 0 ) ) { GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTCI8Flat; } else if (iType >= 10) { GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTZ; GENACCEL(gc).flags |= GEN_FASTZBUFFER; } else { GENACCEL(gc).flags &= ~(HAVE_STIPPLE); GENACCEL(gc).__fastFillSubTrianglePtr = pfnZippySub; } } else { GENACCEL(gc).__fastFillSubTrianglePtr = __fastGenFillSubTriangle; } } return TRUE; } void FASTCALL __fastGenPickTriangleProcs(__GLcontext *gc) { GLuint modeFlags = gc->polygon.shader.modeFlags; __GLGENcontext *genGc = (__GLGENcontext *)gc; CASTINT(gc->polygon.shader.rLittle) = 0; CASTINT(gc->polygon.shader.rBig) = 0; CASTINT(gc->polygon.shader.gLittle) = 0; CASTINT(gc->polygon.shader.gBig) = 0; CASTINT(gc->polygon.shader.bLittle) = 0; CASTINT(gc->polygon.shader.bBig) = 0; CASTINT(gc->polygon.shader.sLittle) = 0; CASTINT(gc->polygon.shader.sBig) = 0; CASTINT(gc->polygon.shader.tLittle) = 0; CASTINT(gc->polygon.shader.tBig) = 0; GENACCEL(gc).spanDelta.r = 0; GENACCEL(gc).spanDelta.g = 0; GENACCEL(gc).spanDelta.b = 0; GENACCEL(gc).spanDelta.a = 0; /* ** Setup cullFace so that a single test will do the cull check. */ if (modeFlags & __GL_SHADE_CULL_FACE) { switch (gc->state.polygon.cull) { case GL_FRONT: gc->polygon.cullFace = __GL_CULL_FLAG_FRONT; break; case GL_BACK: gc->polygon.cullFace = __GL_CULL_FLAG_BACK; break; case GL_FRONT_AND_BACK: gc->procs.renderTriangle = __glDontRenderTriangle; gc->procs.fillTriangle = 0; /* Done to find bugs */ return; } } else { gc->polygon.cullFace = __GL_CULL_FLAG_DONT; } /* Build lookup table for face direction */ switch (gc->state.polygon.frontFaceDirection) { case GL_CW: if (gc->constants.yInverted) { gc->polygon.face[__GL_CW] = __GL_BACKFACE; gc->polygon.face[__GL_CCW] = __GL_FRONTFACE; } else { gc->polygon.face[__GL_CW] = __GL_FRONTFACE; gc->polygon.face[__GL_CCW] = __GL_BACKFACE; } break; case GL_CCW: if (gc->constants.yInverted) { gc->polygon.face[__GL_CW] = __GL_FRONTFACE; gc->polygon.face[__GL_CCW] = __GL_BACKFACE; } else { gc->polygon.face[__GL_CW] = __GL_BACKFACE; gc->polygon.face[__GL_CCW] = __GL_FRONTFACE; } break; } /* Make polygon mode indexable and zero based */ gc->polygon.mode[__GL_FRONTFACE] = (GLubyte) (gc->state.polygon.frontMode & 0xf); gc->polygon.mode[__GL_BACKFACE] = (GLubyte) (gc->state.polygon.backMode & 0xf); if (gc->renderMode == GL_FEEDBACK) { gc->procs.renderTriangle = __glFeedbackTriangle; gc->procs.fillTriangle = 0; /* Done to find bugs */ return; } if (gc->renderMode == GL_SELECT) { gc->procs.renderTriangle = __glSelectTriangle; gc->procs.fillTriangle = 0; /* Done to find bugs */ return; } if ((gc->state.polygon.frontMode == gc->state.polygon.backMode) && (gc->state.polygon.frontMode == GL_FILL)) { if (modeFlags & __GL_SHADE_SMOOTH_LIGHT) { gc->procs.renderTriangle = __glRenderSmoothTriangle; #ifdef GL_WIN_phong_shading } else if (modeFlags & __GL_SHADE_PHONG) { gc->procs.renderTriangle = __glRenderPhongTriangle; #endif //GL_WIN_phong_shading } else { gc->procs.renderTriangle = __glRenderFlatTriangle; } } else { gc->procs.renderTriangle = __glRenderTriangle; } if (gc->state.enables.general & __GL_POLYGON_SMOOTH_ENABLE) { #ifdef GL_WIN_phong_shading if (modeFlags & __GL_SHADE_PHONG) gc->procs.fillTriangle = __glFillAntiAliasedPhongTriangle; else #endif //GL_WIN_phong_shading gc->procs.fillTriangle = __glFillAntiAliasedTriangle; } else { if ((gc->state.raster.drawBuffer == GL_NONE) || !bUseGenTriangles(gc)) #ifdef GL_WIN_phong_shading if (modeFlags & __GL_SHADE_PHONG) gc->procs.fillTriangle = __glFillPhongTriangle; else #endif //GL_WIN_phong_shading gc->procs.fillTriangle = __glFillTriangle; } if ((modeFlags & __GL_SHADE_CHEAP_FOG) && !(modeFlags & __GL_SHADE_SMOOTH_LIGHT)) { gc->procs.fillTriangle2 = gc->procs.fillTriangle; gc->procs.fillTriangle = __glFillFlatFogTriangle; } #ifdef GL_WIN_specular_fog /* ** The case where 1) Specular fog is enabled AND 2) flat-shaded */ if ((modeFlags & (__GL_SHADE_SPEC_FOG | __GL_SHADE_SMOOTH_LIGHT | __GL_SHADE_PHONG)) == __GL_SHADE_SPEC_FOG) { gc->procs.fillTriangle2 = gc->procs.fillTriangle; gc->procs.fillTriangle = __glFillFlatSpecFogTriangle; } #endif //GL_WIN_specular_fog } void FASTCALL __fastGenPickSpanProcs(__GLcontext *gc) { __GLGENcontext *genGc = (__GLGENcontext *)gc; GLuint enables = gc->state.enables.general; GLuint modeFlags = gc->polygon.shader.modeFlags; __GLcolorBuffer *cfb = gc->drawBuffer; __GLspanFunc *sp; __GLstippledSpanFunc *ssp; int spanCount; GLboolean replicateSpan; GLboolean bMcdZ = ((((__GLGENcontext *)gc)->pMcdState != NULL) && (((__GLGENcontext *)gc)->pMcdState->pDepthSpan != NULL) && (((__GLGENcontext *)gc)->pMcdState->pMcdSurf != NULL) && !(((__GLGENcontext *)gc)->pMcdState->McdBuffers.mcdDepthBuf.bufFlags & MCDBUF_ENABLED)); // Always reset the color scale values at the beginning of the pick // procs. Lines, triangles, and spans may all use these values... GENACCEL(gc).rAccelScale = (GLfloat)ACCEL_FIX_SCALE; GENACCEL(gc).gAccelScale = (GLfloat)ACCEL_FIX_SCALE; GENACCEL(gc).bAccelScale = (GLfloat)ACCEL_FIX_SCALE; // Note: we need to scale between 0 and 255 to get proper alpha // blending. The software-accelerated blending code assumes this // scaling for simplicity... GENACCEL(gc).aAccelScale = (GLfloat)(ACCEL_FIX_SCALE) * (GLfloat)255.0 / gc->drawBuffer->alphaScale; replicateSpan = GL_FALSE; sp = gc->procs.span.spanFuncs; ssp = gc->procs.span.stippledSpanFuncs; /* Load phase one procs */ if (!gc->transform.reasonableViewport) { *sp++ = __glClipSpan; *ssp++ = NULL; } if (modeFlags & __GL_SHADE_STIPPLE) { *sp++ = __glStippleSpan; *ssp++ = __glStippleStippledSpan; if (modeFlags & __GL_SHADE_DEPTH_TEST) { if (bMcdZ) { GENACCEL(gc).__fastStippleDepthTestSpan = GenMcdStippleAnyDepthTestSpan; } else { if (gc->state.depth.testFunc == GL_LESS) { if (gc->modes.depthBits == 32) { GENACCEL(gc).__fastStippleDepthTestSpan = __fastGenStippleLt32Span; } else { GENACCEL(gc).__fastStippleDepthTestSpan = __fastGenStippleLt16Span; } } else { GENACCEL(gc).__fastStippleDepthTestSpan = __fastGenStippleAnyDepthTestSpan; } } } else { GENACCEL(gc).__fastStippleDepthTestSpan = __glStippleSpan; } } /* Load phase three procs */ if (modeFlags & __GL_SHADE_RGB) { if (modeFlags & __GL_SHADE_SMOOTH) { *sp = __glShadeRGBASpan; *ssp = __glShadeRGBASpan; #ifdef GL_WIN_phong_shading } else if (modeFlags & __GL_SHADE_PHONG) { *sp = __glPhongRGBASpan; *ssp = __glPhongRGBASpan; #endif //GL_WIN_phong_shading } else { *sp = __glFlatRGBASpan; *ssp = __glFlatRGBASpan; } } else { if (modeFlags & __GL_SHADE_SMOOTH) { *sp = __glShadeCISpan; *ssp = __glShadeCISpan; #ifdef GL_WIN_phong_shading } else if (modeFlags & __GL_SHADE_PHONG) { *sp = __glPhongCISpan; *ssp = __glPhongCISpan; #endif //GL_WIN_phong_shading } else { *sp = __glFlatCISpan; *ssp = __glFlatCISpan; } } sp++; ssp++; if (modeFlags & __GL_SHADE_TEXTURE) { *sp++ = __glTextureSpan; *ssp++ = __glTextureStippledSpan; } #ifdef GL_WIN_specular_fog if (modeFlags & (__GL_SHADE_SLOW_FOG | __GL_SHADE_SPEC_FOG)) #else //GL_WIN_specular_fog if (modeFlags & __GL_SHADE_SLOW_FOG) #endif //GL_WIN_specular_fog { if (DO_NICEST_FOG (gc)) { *sp = __glFogSpanSlow; *ssp = __glFogStippledSpanSlow; } else { *sp = __glFogSpan; *ssp = __glFogStippledSpan; } sp++; ssp++; } if (modeFlags & __GL_SHADE_ALPHA_TEST) { *sp++ = __glAlphaTestSpan; *ssp++ = __glAlphaTestStippledSpan; } /* Load phase two procs */ if (modeFlags & __GL_SHADE_STENCIL_TEST) { *sp++ = __glStencilTestSpan; *ssp++ = __glStencilTestStippledSpan; if (modeFlags & __GL_SHADE_DEPTH_TEST) { if (bMcdZ) { *sp = GenMcdDepthTestStencilSpan; *ssp = GenMcdDepthTestStencilStippledSpan; } else { *sp = __glDepthTestStencilSpan; *ssp = __glDepthTestStencilStippledSpan; } } else { *sp = __glDepthPassSpan; *ssp = __glDepthPassStippledSpan; } sp++; ssp++; } else { if (modeFlags & __GL_SHADE_DEPTH_TEST) { if (bMcdZ) { *sp++ = GenMcdDepthTestSpan; *ssp++ = GenMcdDepthTestStippledSpan; if (gc->state.depth.writeEnable) ((__GLGENcontext *)gc)->pMcdState->softZSpanFuncPtr = __fastDepthFuncs[gc->state.depth.testFunc & 0x7]; else ((__GLGENcontext *)gc)->pMcdState->softZSpanFuncPtr = (__GLspanFunc)NULL; GENACCEL(gc).__fastZSpanFuncPtr = GenMcdDepthTestSpan; } else { if (gc->state.depth.writeEnable) { if( gc->modes.depthBits == 32 ) { *sp++ = GENACCEL(gc).__fastZSpanFuncPtr = __fastDepthFuncs[gc->state.depth.testFunc & 0x7]; } else { *sp++ = GENACCEL(gc).__fastZSpanFuncPtr = __fastDepth16Funcs[gc->state.depth.testFunc & 0x7]; } } else { *sp++ = GENACCEL(gc).__fastZSpanFuncPtr = __glDepthTestSpan; } *ssp++ = __glDepthTestStippledSpan; } } } if (gc->state.raster.drawBuffer == GL_FRONT_AND_BACK) { spanCount = (int)((ULONG_PTR)(sp - gc->procs.span.spanFuncs)); gc->procs.span.n = spanCount; replicateSpan = GL_TRUE; } /* Span routines deal with masking, dithering, logicop, blending */ *sp++ = cfb->storeSpan; *ssp++ = cfb->storeStippledSpan; spanCount = (int)((ULONG_PTR)(sp - gc->procs.span.spanFuncs)); gc->procs.span.m = spanCount; if (replicateSpan) { gc->procs.span.processSpan = __glProcessReplicateSpan; } else { gc->procs.span.processSpan = __glProcessSpan; gc->procs.span.n = spanCount; } } // These are the bits in modeFlags that affect lines #ifdef GL_WIN_specular_fog #define __FAST_LINE_SPEC_FOG __GL_SHADE_SPEC_FOG #else #define __FAST_LINE_SPEC_FOG 0 #endif //GL_WIN_specular_fog #ifdef GL_WIN_phong_shading #define __FAST_LINE_PHONG __GL_SHADE_PHONG #else #define __FAST_LINE_PHONG 0 #endif //GL_WIN_phong_shading #define __FAST_LINE_MODE_FLAGS \ (__GL_SHADE_DEPTH_TEST | __GL_SHADE_SMOOTH | __GL_SHADE_TEXTURE | \ __GL_SHADE_LINE_STIPPLE | __GL_SHADE_STENCIL_TEST | __GL_SHADE_LOGICOP | \ __GL_SHADE_BLEND | __GL_SHADE_ALPHA_TEST | __GL_SHADE_MASK | \ __GL_SHADE_SLOW_FOG | __GL_SHADE_CHEAP_FOG | __FAST_LINE_SPEC_FOG | \ __FAST_LINE_PHONG) /******************************Public*Routine******************************\ * __fastGenPickLineProcs * * Picks the line-rendering procedures. Most of this function was copied from * the soft code. Some differences include: * 1. The beginPrim function pointers are hooked by the accelerated code * 2. If the attribute state is such that acceleration can be used, * __fastGenLineSetup is called to initialize the state machine. * * History: * 22-Mar-1994 -by- Eddie Robinson [v-eddier] * Wrote it. \**************************************************************************/ void FASTCALL __fastGenPickLineProcs(__GLcontext *gc) { __GLGENcontext *genGc = (__GLGENcontext *) gc; GENACCEL *genAccel; GLuint enables = gc->state.enables.general; GLuint modeFlags = gc->polygon.shader.modeFlags; __GLspanFunc *sp; __GLstippledSpanFunc *ssp; int spanCount; GLboolean wideLine; GLboolean replicateLine; GLuint aaline; GLboolean bMcdZ = ((genGc->pMcdState != NULL) && (genGc->pMcdState->pDepthSpan != NULL) && (genGc->pMcdState->pMcdSurf != NULL) && !(genGc->pMcdState->McdBuffers.mcdDepthBuf.bufFlags & MCDBUF_ENABLED)); /* ** The fast line code replaces the line function pointers, so reset them ** to a good state */ gc->procs.lineBegin = __glNopLineBegin; gc->procs.lineEnd = __glNopLineEnd; if (gc->renderMode == GL_FEEDBACK) { gc->procs.renderLine = __glFeedbackLine; } else if (gc->renderMode == GL_SELECT) { gc->procs.renderLine = __glSelectLine; } else { if (genAccel = (GENACCEL *) genGc->pPrivateArea) { if (!(modeFlags & __FAST_LINE_MODE_FLAGS & ~genAccel->flLineAccelModes) && !(gc->state.enables.general & __GL_LINE_SMOOTH_ENABLE) && !(gc->state.enables.general & __GL_SCISSOR_TEST_ENABLE) && !(gc->state.raster.drawBuffer == GL_NONE) && !gc->buffers.doubleStore && !genGc->pMcdState && (genGc->dwCurrentFlags & (GLSURF_HDC | GLSURF_METAFILE)) == GLSURF_HDC) { __fastLineComputeOffsets(genGc); #if NT_NO_BUFFER_INVARIANCE if (!(gc->drawBuffer->buf.flags & DIB_FORMAT)) { if (genAccel->bFastLineDispAccel) { if (__fastGenLineSetupDisplay(gc)) return; } } else { if (genAccel->bFastLineDIBAccel) { if (__fastGenLineSetupDIB(gc)) return; } } #else if (genAccel->bFastLineDispAccel) { if (__fastGenLineSetupDisplay(gc)) return; } #endif } } if (__glGenSetupEitherLines(gc)) { return; } replicateLine = wideLine = GL_FALSE; aaline = gc->state.enables.general & __GL_LINE_SMOOTH_ENABLE; if (aaline) { gc->procs.renderLine = __glRenderAntiAliasLine; } else { gc->procs.renderLine = __glRenderAliasLine; } sp = gc->procs.line.lineFuncs; ssp = gc->procs.line.stippledLineFuncs; if (!aaline && (modeFlags & __GL_SHADE_LINE_STIPPLE)) { *sp++ = __glStippleLine; *ssp++ = NULL; } if (!aaline && gc->state.line.aliasedWidth > 1) { wideLine = GL_TRUE; } spanCount = (int)((ULONG_PTR)(sp - gc->procs.line.lineFuncs)); gc->procs.line.n = spanCount; *sp++ = __glScissorLine; *ssp++ = __glScissorStippledLine; if (!aaline) { if (modeFlags & __GL_SHADE_STENCIL_TEST) { *sp++ = __glStencilTestLine; *ssp++ = __glStencilTestStippledLine; if (modeFlags & __GL_SHADE_DEPTH_TEST) { if (bMcdZ) { *sp = GenMcdDepthTestStencilLine; *ssp = GenMcdDepthTestStencilStippledLine; } else if( gc->modes.depthBits == 32 ) { *sp = __glDepthTestStencilLine; *ssp = __glDepthTestStencilStippledLine; } else { *sp = __glDepth16TestStencilLine; *ssp = __glDepth16TestStencilStippledLine; } } else { *sp = __glDepthPassLine; *ssp = __glDepthPassStippledLine; } sp++; ssp++; } else { if (modeFlags & __GL_SHADE_DEPTH_TEST) { if (gc->state.depth.testFunc == GL_NEVER) { /* Unexpected end of line routine picking! */ spanCount = (int)((ULONG_PTR)(sp - gc->procs.line.lineFuncs)); gc->procs.line.m = spanCount; gc->procs.line.l = spanCount; goto pickLineProcessor; #ifdef __GL_USEASMCODE } else { unsigned long ix; if (gc->state.depth.writeEnable) { ix = 0; } else { ix = 8; } ix += gc->state.depth.testFunc & 0x7; if (ix == (GL_LEQUAL & 0x7)) { *sp++ = __glDepthTestLine_LEQ_asm; } else { *sp++ = __glDepthTestLine_asm; gc->procs.line.depthTestPixel = LDepthTestPixel[ix]; } #else } else { if (bMcdZ) { *sp++ = GenMcdDepthTestLine; } else { if( gc->modes.depthBits == 32 ) *sp++ = __glDepthTestLine; else *sp++ = __glDepth16TestLine; } #endif } if (bMcdZ) { *ssp++ = GenMcdDepthTestStippledLine; } else { if( gc->modes.depthBits == 32 ) *ssp++ = __glDepthTestStippledLine; else *ssp++ = __glDepth16TestStippledLine; } } } } /* Load phase three procs */ if (modeFlags & __GL_SHADE_RGB) { if (modeFlags & __GL_SHADE_SMOOTH) { *sp = __glShadeRGBASpan; *ssp = __glShadeRGBASpan; #ifdef GL_WIN_phong_shading } else if (modeFlags & __GL_SHADE_PHONG) { *sp = __glPhongRGBASpan; *ssp = __glPhongRGBASpan; #endif //GL_WIN_phong_shading } else { *sp = __glFlatRGBASpan; *ssp = __glFlatRGBASpan; } } else { if (modeFlags & __GL_SHADE_SMOOTH) { *sp = __glShadeCISpan; *ssp = __glShadeCISpan; #ifdef GL_WIN_phong_shading } else if (modeFlags & __GL_SHADE_PHONG) { *sp = __glPhongCISpan; *ssp = __glPhongCISpan; #endif //GL_WIN_phong_shading } else { *sp = __glFlatCISpan; *ssp = __glFlatCISpan; } } sp++; ssp++; if (modeFlags & __GL_SHADE_TEXTURE) { *sp++ = __glTextureSpan; *ssp++ = __glTextureStippledSpan; } #ifdef GL_WIN_specular_fog if (modeFlags & (__GL_SHADE_SLOW_FOG | __GL_SHADE_SPEC_FOG)) #else //GL_WIN_specular_fog if (modeFlags & __GL_SHADE_SLOW_FOG) #endif //GL_WIN_specular_fog { if (DO_NICEST_FOG (gc)) { *sp = __glFogSpanSlow; *ssp = __glFogStippledSpanSlow; } else { *sp = __glFogSpan; *ssp = __glFogStippledSpan; } sp++; ssp++; } if (aaline) { *sp++ = __glAntiAliasLine; *ssp++ = __glAntiAliasStippledLine; } if (aaline) { if (modeFlags & __GL_SHADE_STENCIL_TEST) { *sp++ = __glStencilTestLine; *ssp++ = __glStencilTestStippledLine; if (modeFlags & __GL_SHADE_DEPTH_TEST) { if (bMcdZ) { *sp = GenMcdDepthTestStencilLine; *ssp = GenMcdDepthTestStencilStippledLine; } else if( gc->modes.depthBits == 32 ) { *sp = __glDepthTestStencilLine; *ssp = __glDepthTestStencilStippledLine; } else { *sp = __glDepth16TestStencilLine; *ssp = __glDepth16TestStencilStippledLine; } } else { *sp = __glDepthPassLine; *ssp = __glDepthPassStippledLine; } sp++; ssp++; } else { if (modeFlags & __GL_SHADE_DEPTH_TEST) { if (gc->state.depth.testFunc == GL_NEVER) { /* Unexpected end of line routine picking! */ spanCount = (int)((ULONG_PTR)(sp - gc->procs.line.lineFuncs)); gc->procs.line.m = spanCount; gc->procs.line.l = spanCount; goto pickLineProcessor; #ifdef __GL_USEASMCODE } else { unsigned long ix; if (gc->state.depth.writeEnable) { ix = 0; } else { ix = 8; } ix += gc->state.depth.testFunc & 0x7; *sp++ = __glDepthTestLine_asm; gc->procs.line.depthTestPixel = LDepthTestPixel[ix]; #else } else { if (bMcdZ) *sp++ = GenMcdDepthTestLine; else if( gc->modes.depthBits == 32 ) *sp++ = __glDepthTestLine; else *sp++ = __glDepth16TestLine; #endif } if (bMcdZ) *ssp++ = GenMcdDepthTestStippledLine; else if (gc->modes.depthBits == 32) *ssp++ = __glDepthTestStippledLine; else *ssp++ = __glDepth16TestStippledLine; } } } if (modeFlags & __GL_SHADE_ALPHA_TEST) { *sp++ = __glAlphaTestSpan; *ssp++ = __glAlphaTestStippledSpan; } if (gc->buffers.doubleStore) { replicateLine = GL_TRUE; } spanCount = (int)((ULONG_PTR)(sp - gc->procs.line.lineFuncs)); gc->procs.line.m = spanCount; *sp++ = __glStoreLine; *ssp++ = __glStoreStippledLine; spanCount = (int)((ULONG_PTR)(sp - gc->procs.line.lineFuncs)); gc->procs.line.l = spanCount; sp = &gc->procs.line.wideLineRep; ssp = &gc->procs.line.wideStippledLineRep; if (wideLine) { *sp = __glWideLineRep; *ssp = __glWideStippleLineRep; sp = &gc->procs.line.drawLine; ssp = &gc->procs.line.drawStippledLine; } if (replicateLine) { *sp = __glDrawBothLine; *ssp = __glDrawBothStippledLine; } else { *sp = __glNopGCBOOL; *ssp = __glNopGCBOOL; gc->procs.line.m = gc->procs.line.l; } if (!wideLine) { gc->procs.line.n = gc->procs.line.m; } pickLineProcessor: if (!wideLine && !replicateLine && spanCount == 3) { gc->procs.line.processLine = __glProcessLine3NW; } else { gc->procs.line.processLine = __glProcessLine; } if ((modeFlags & __GL_SHADE_CHEAP_FOG) && !(modeFlags & __GL_SHADE_SMOOTH_LIGHT)) { gc->procs.renderLine2 = gc->procs.renderLine; gc->procs.renderLine = __glRenderFlatFogLine; } } } BOOL FASTCALL __glGenCreateAccelContext(__GLcontext *gc) { __GLGENcontext *genGc = (__GLGENcontext *)gc; PIXELFORMATDESCRIPTOR *pfmt; ULONG bpp; pfmt = &genGc->gsurf.pfd; bpp = pfmt->cColorBits; genGc->pPrivateArea = (VOID *)(&genGc->genAccel); __glQueryLineAcceleration(gc); gc->procs.pickTriangleProcs = __fastGenPickTriangleProcs; gc->procs.pickSpanProcs = __fastGenPickSpanProcs; // Set up constant-color values: GENACCEL(gc).constantR = ((1 << pfmt->cRedBits) - 1) << 16; GENACCEL(gc).constantG = ((1 << pfmt->cGreenBits) - 1) << 16; GENACCEL(gc).constantB = ((1 << pfmt->cBlueBits) - 1) << 16; if( pfmt->cAlphaBits ) GENACCEL(gc).constantA = ((1 << pfmt->cAlphaBits) - 1) << 16; else GENACCEL(gc).constantA = 0xff << 16; GENACCEL(gc).bpp = bpp; GENACCEL(gc).xMultiplier = ((bpp + 7) / 8); if (gc->modes.depthBits == 16 ) GENACCEL(gc).zScale = (__GLfloat)65536.0; else GENACCEL(gc).zScale = (__GLfloat)1.0; return TRUE; } MCDHANDLE FASTCALL __glGenLoadTexture(__GLcontext *gc, __GLtexture *tex, ULONG flags) { __GLGENcontext *gengc = (__GLGENcontext *)gc; MCDHANDLE texHandle; DWORD texKey; #ifdef _MCD_ if (gengc->pMcdState) { texHandle = GenMcdCreateTexture(gengc, tex, flags); if (texHandle) { tex->textureKey = GenMcdTextureKey(gengc, texHandle); gc->textureKey = tex->textureKey; } return texHandle; } else #endif return 0; } BOOL FASTCALL __glGenMakeTextureCurrent(__GLcontext *gc, __GLtexture *tex, MCDHANDLE loadKey) { GLint internalFormat; if (!tex) return FALSE; InitAccelTextureValues(gc, tex); // Update the driver texture key in the context: if (((__GLGENcontext *)gc)->pMcdState && (gc->textureKey = tex->textureKey)) { GenMcdUpdateTextureState((__GLGENcontext *)gc, tex, loadKey); } // Previously we called bUseGenTriangles here to determine whether we were // doing 'fast' texturing, and if so, setup the texture cache pointers // below. But this slowed down texture bind time, so for now we always // execute this next section of code (safe, since we check for valid ptrs). if (tex->level[0].internalFormat == GL_COLOR_INDEX8_EXT) { if (tex->pvUser) GENACCEL(gc).texImageReplace = ((GENTEXCACHE *)tex->pvUser)->texImageReplace; } else if (tex->level[0].internalFormat != GL_COLOR_INDEX16_EXT) { if (tex->pvUser) GENACCEL(gc).texImageReplace = ((GENTEXCACHE *)tex->pvUser)->texImageReplace; GENACCEL(gc).texPalette = NULL; } return TRUE; } BOOL FASTCALL __glGenUpdateTexture(__GLcontext *gc, __GLtexture *tex, MCDHANDLE loadKey) { //!! NOTE !! //!! This should really be broken into separate load and update calls since //!! loading and updating are different operations. The texture texture //!! data cache will never shrink with the current implementation. // Do not quit if the load fails because we want the repick to occur // in MakeTextureCurrent in both the success and failure cases __fastGenLoadTexImage(gc, tex); __glGenMakeTextureCurrent(gc, tex, loadKey); return TRUE; } void FASTCALL __glGenFreeTexture(__GLcontext *gc, __GLtexture *tex, MCDHANDLE loadKey) { __GLGENcontext *gengc = (__GLGENcontext *)gc; if (GENACCEL(gc).texImage) GENACCEL(gc).texImage = NULL; if (tex->pvUser) { GCFREE(gc, tex->pvUser); tex->pvUser = NULL; } #ifdef _MCD_ if (gengc->pMcdState && loadKey) { GenMcdDeleteTexture(gengc, loadKey); } #endif } void FASTCALL __glGenUpdateTexturePalette(__GLcontext *gc, __GLtexture *tex, MCDHANDLE loadKey, ULONG start, ULONG count) { UCHAR *texBuffer; GENTEXCACHE *pGenTex; __GLcolorBuffer *cfb = gc->drawBuffer; BYTE *pXlat = ((__GLGENcontext *)gc)->pajTranslateVector; ULONG rBits, gBits, bBits; ULONG rShift, gShift, bShift; ULONG i, end; ULONG *replaceBuffer; ASSERTOPENGL(tex->paletteTotalData != NULL, "__GenUpdateTexturePalette: null texture data\n"); #ifdef _MCD_ if (((__GLGENcontext *)gc)->pMcdState && loadKey) { GenMcdUpdateTexturePalette((__GLGENcontext *)gc, tex, loadKey, start, count); } #endif pGenTex = GetGenTexCache(gc, tex); if (!pGenTex) return; GENACCEL(gc).texImageReplace = pGenTex->texImageReplace; replaceBuffer = (ULONG *)(pGenTex->texImageReplace) + start; texBuffer = (UCHAR *)(tex->paletteTotalData + start); rShift = cfb->redShift; gShift = cfb->greenShift; bShift = cfb->blueShift; rBits = ((__GLGENcontext *)gc)->gsurf.pfd.cRedBits; gBits = ((__GLGENcontext *)gc)->gsurf.pfd.cGreenBits; bBits = ((__GLGENcontext *)gc)->gsurf.pfd.cBlueBits; end = start + count; for (i = start; i < end; i++, texBuffer += 4) { ULONG color; color = ((((ULONG)texBuffer[2] << rBits) >> 8) << rShift) | ((((ULONG)texBuffer[1] << gBits) >> 8) << gShift) | ((((ULONG)texBuffer[0] << bBits) >> 8) << bShift); if (GENACCEL(gc).bpp == 8) color = pXlat[color & 0xff]; *replaceBuffer++ = (color | ((ULONG)texBuffer[3] << 24)); } } #ifdef GL_EXT_flat_paletted_lighting void FASTCALL __glGenSetPaletteOffset(__GLcontext *gc, __GLtexture *tex, GLint offset) { GENTEXCACHE *pGenTex; if (GENACCEL(gc).texPalette == NULL) { return; } GENACCEL(gc).texPalette = (ULONG *)tex->paletteTotalData+offset; pGenTex = GetGenTexCache(gc, tex); if (pGenTex == NULL) { return; } // Replace map for paletted textures is a replace map of the // entire palette, so offset it if (GENACCEL(gc).texImageReplace != NULL) { GENACCEL(gc).texImageReplace = (UCHAR *) ((ULONG *)pGenTex->texImageReplace+offset); } // Consider - Call MCD } #endif void FASTCALL __glGenDestroyAccelContext(__GLcontext *gc) { __GLGENcontext *genGc = (__GLGENcontext *)gc; /* Free any platform-specific private data area */ if (genGc->pPrivateArea) { if (GENACCEL(gc).pFastLineBuffer) { GCFREE(gc, GENACCEL(gc).pFastLineBuffer); #ifndef _CLIENTSIDE_ wglDeletePath(GENACCEL(gc).pFastLinePathobj); #endif } genGc->pPrivateArea = NULL; } }