1821 lines
62 KiB
C
1821 lines
62 KiB
C
/******************************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;
|
|
}
|
|
}
|