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

1821 lines
62 KiB
C
Raw Normal View History

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