/* ** Copyright 1991-1993, Silicon Graphics, Inc. ** All Rights Reserved. ** ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; ** the contents of this file may not be disclosed to third parties, copied or ** duplicated in any form, in whole or in part, without the prior written ** permission of Silicon Graphics, Inc. ** ** RESTRICTED RIGHTS LEGEND: ** Use, duplication or disclosure by the Government is subject to restrictions ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - ** rights reserved under the Copyright Laws of the United States. */ #include "precomp.h" #pragma hdrstop #include "texture.h" /* ** Determine if the alpha color component is needed. If it's not needed ** then the renderers can avoid computing it. */ GLboolean FASTCALL __glNeedAlpha(__GLcontext *gc) { if (gc->modes.colorIndexMode) { return GL_FALSE; } if (gc->state.enables.general & __GL_ALPHA_TEST_ENABLE) { return GL_TRUE; } if (gc->modes.alphaBits > 0) { return GL_TRUE; } if (gc->state.enables.general & __GL_BLEND_ENABLE) { GLint src = gc->state.raster.blendSrc; GLint dst = gc->state.raster.blendDst; /* ** See if one of the source alpha combinations are used. */ if ((src == GL_SRC_ALPHA) || (src == GL_ONE_MINUS_SRC_ALPHA) || (src == GL_SRC_ALPHA_SATURATE) || (dst == GL_SRC_ALPHA) || (dst == GL_ONE_MINUS_SRC_ALPHA)) { return GL_TRUE; } } return GL_FALSE; } /************************************************************************/ /* these are depth test routines for C.. */ GLboolean (FASTCALL *__glCDTPixel[32])(__GLzValue, __GLzValue *) = { /* unsigned ops, no mask */ __glDT_NEVER, __glDT_LESS, __glDT_EQUAL, __glDT_LEQUAL, __glDT_GREATER, __glDT_NOTEQUAL, __glDT_GEQUAL, __glDT_ALWAYS, /* unsigned ops, mask */ __glDT_NEVER, __glDT_LESS_M, __glDT_EQUAL_M, __glDT_LEQUAL_M, __glDT_GREATER_M, __glDT_NOTEQUAL_M, __glDT_GEQUAL_M, __glDT_ALWAYS_M, /* unsigned ops, no mask */ __glDT_NEVER, __glDT16_LESS, __glDT16_EQUAL, __glDT16_LEQUAL, __glDT16_GREATER, __glDT16_NOTEQUAL, __glDT16_GEQUAL, __glDT16_ALWAYS, /* unsigned ops, mask */ __glDT_NEVER, __glDT16_LESS_M, __glDT16_EQUAL_M, __glDT16_LEQUAL_M, __glDT16_GREATER_M, __glDT16_NOTEQUAL_M, __glDT16_GEQUAL_M, __glDT16_ALWAYS_M, }; #ifdef __GL_USEASMCODE void (*__glSDepthTestPixel[16])(void) = { NULL, __glDTS_LESS, __glDTS_EQUAL, __glDTS_LEQUAL, __glDTS_GREATER, __glDTS_NOTEQUAL, __glDTS_GEQUAL, __glDTS_ALWAYS, NULL, __glDTS_LESS_M, __glDTS_EQUAL_M, __glDTS_LEQUAL_M, __glDTS_GREATER_M, __glDTS_NOTEQUAL_M, __glDTS_GEQUAL_M, __glDTS_ALWAYS_M, }; #endif /************************************************************************/ void FASTCALL __glGenericPickPointProcs(__GLcontext *gc) { GLuint modeFlags = gc->polygon.shader.modeFlags; if (gc->renderMode == GL_FEEDBACK) { gc->procs.renderPoint = __glFeedbackPoint; return; } if (gc->renderMode == GL_SELECT) { gc->procs.renderPoint = __glSelectPoint; return; } if (gc->state.enables.general & __GL_POINT_SMOOTH_ENABLE) { if (gc->modes.colorIndexMode) { gc->procs.renderPoint = __glRenderAntiAliasedCIPoint; } else { gc->procs.renderPoint = __glRenderAntiAliasedRGBPoint; } return; } else if (gc->state.point.aliasedSize != 1) { gc->procs.renderPoint = __glRenderAliasedPointN; } else if (gc->texture.textureEnabled) { gc->procs.renderPoint = __glRenderAliasedPoint1; } else { gc->procs.renderPoint = __glRenderAliasedPoint1_NoTex; } #ifdef __BUGGY_RENDER_POINT #ifdef NT if ((modeFlags & __GL_SHADE_CHEAP_FOG) && !(modeFlags & __GL_SHADE_SMOOTH_LIGHT)) { gc->procs.renderPoint2 = gc->procs.renderPoint; gc->procs.renderPoint = __glRenderFlatFogPoint; } else if (modeFlags & __GL_SHADE_SLOW_FOG) { gc->procs.renderPoint2 = gc->procs.renderPoint; gc->procs.renderPoint = __glRenderFlatFogPointSlow; } #else // SGIBUG the slow fog path does not compute vertex->fog value! if (((modeFlags & __GL_SHADE_CHEAP_FOG) && !(modeFlags & __GL_SHADE_SMOOTH_LIGHT)) || (modeFlags & __GL_SHADE_SLOW_FOG)) { gc->procs.renderPoint2 = gc->procs.renderPoint; gc->procs.renderPoint = __glRenderFlatFogPoint; } #endif #endif //__BUGGY_RENDER_POINT } #ifdef __GL_USEASMCODE static void (*LDepthTestPixel[16])(void) = { NULL, __glDTP_LESS, __glDTP_EQUAL, __glDTP_LEQUAL, __glDTP_GREATER, __glDTP_NOTEQUAL, __glDTP_GEQUAL, __glDTP_ALWAYS, NULL, __glDTP_LESS_M, __glDTP_EQUAL_M, __glDTP_LEQUAL_M, __glDTP_GREATER_M, __glDTP_NOTEQUAL_M, __glDTP_GEQUAL_M, __glDTP_ALWAYS_M, }; #endif void FASTCALL __glGenericPickRenderBitmapProcs(__GLcontext *gc) { gc->procs.renderBitmap = __glRenderBitmap; } void FASTCALL __glGenericPickClipProcs(__GLcontext *gc) { gc->procs.clipTriangle = __glClipTriangle; } void FASTCALL __glGenericPickTextureProcs(__GLcontext *gc) { __GLtexture *current; __GLtextureParamState *params; #ifdef NT /* Pick coordinate generation function */ if ((gc->state.enables.general & __GL_TEXTURE_GEN_S_ENABLE) && (gc->state.enables.general & __GL_TEXTURE_GEN_T_ENABLE) && !(gc->state.enables.general & __GL_TEXTURE_GEN_R_ENABLE) && !(gc->state.enables.general & __GL_TEXTURE_GEN_Q_ENABLE) && (gc->state.texture.s.mode == gc->state.texture.t.mode)) { /* Use a special function when both modes are enabled and identical */ if (gc->state.texture.s.mode == GL_SPHERE_MAP) { gc->procs.paCalcTexture = PolyArrayCalcSphereMap; } else { __GLcoord *cs, *ct; cs = &gc->state.texture.s.eyePlaneEquation; ct = &gc->state.texture.t.eyePlaneEquation; if (cs->x == ct->x && cs->y == ct->y && cs->z == ct->z && cs->w == ct->w) { if (gc->state.texture.s.mode == GL_EYE_LINEAR) gc->procs.paCalcTexture = PolyArrayCalcEyeLinearSameST; else gc->procs.paCalcTexture = PolyArrayCalcObjectLinearSameST; } else { if (gc->state.texture.s.mode == GL_EYE_LINEAR) gc->procs.paCalcTexture = PolyArrayCalcEyeLinear; else gc->procs.paCalcTexture = PolyArrayCalcObjectLinear; } } } else { if (gc->state.enables.general & (__GL_TEXTURE_GEN_S_ENABLE | __GL_TEXTURE_GEN_T_ENABLE | __GL_TEXTURE_GEN_R_ENABLE | __GL_TEXTURE_GEN_Q_ENABLE)) /* Use fast function when both are disabled */ gc->procs.paCalcTexture = PolyArrayCalcMixedTexture; else gc->procs.paCalcTexture = PolyArrayCalcTexture; } #else /* Pick coordinate generation function */ if ((gc->state.enables.general & __GL_TEXTURE_GEN_S_ENABLE) && (gc->state.enables.general & __GL_TEXTURE_GEN_T_ENABLE) && !(gc->state.enables.general & __GL_TEXTURE_GEN_R_ENABLE) && !(gc->state.enables.general & __GL_TEXTURE_GEN_Q_ENABLE) && (gc->state.texture.s.mode == gc->state.texture.t.mode)) { /* Use a special function when both modes are enabled and identical */ switch (gc->state.texture.s.mode) { case GL_EYE_LINEAR: gc->procs.calcTexture = __glCalcEyeLinear; break; case GL_OBJECT_LINEAR: gc->procs.calcTexture = __glCalcObjectLinear; break; case GL_SPHERE_MAP: gc->procs.calcTexture = __glCalcSphereMap; break; } } else { if (!(gc->state.enables.general & __GL_TEXTURE_GEN_S_ENABLE) && !(gc->state.enables.general & __GL_TEXTURE_GEN_T_ENABLE) && !(gc->state.enables.general & __GL_TEXTURE_GEN_R_ENABLE) && !(gc->state.enables.general & __GL_TEXTURE_GEN_Q_ENABLE)) { /* Use fast function when both are disabled */ gc->procs.calcTexture = __glCalcTexture; } else { gc->procs.calcTexture = __glCalcMixedTexture; } } #endif // NT gc->texture.currentTexture = current = 0; if (gc->state.enables.general & __GL_TEXTURE_2D_ENABLE) { if (__glIsTextureConsistent(gc, GL_TEXTURE_2D)) { params = __glLookUpTextureParams(gc, GL_TEXTURE_2D); gc->texture.currentTexture = current = __glLookUpTexture(gc, GL_TEXTURE_2D); } } else if (gc->state.enables.general & __GL_TEXTURE_1D_ENABLE) { if (__glIsTextureConsistent(gc, GL_TEXTURE_1D)) { params = __glLookUpTextureParams(gc, GL_TEXTURE_1D); gc->texture.currentTexture = current = __glLookUpTexture(gc, GL_TEXTURE_1D); } } else { current = NULL; } #ifdef _MCD_ MCD_STATE_DIRTY(gc, TEXTURE); #endif /* Pick texturing function for the current texture */ if (current) { GLenum baseFormat; /* XXX most of this should be bound into the texture param code, right? */ current->params = *params; /* ** Figure out if mipmapping is being used. If not, then the ** rho computations can be avoided as there is only one texture ** to choose from. */ gc->procs.calcLineRho = __glComputeLineRho; gc->procs.calcPolygonRho = __glComputePolygonRho; if ((current->params.minFilter == GL_LINEAR) || (current->params.minFilter == GL_NEAREST)) { /* No mipmapping needed */ if (current->params.minFilter == current->params.magFilter) { /* No rho needed as min/mag application is identical */ current->textureFunc = __glFastTextureFragment; gc->procs.calcLineRho = __glNopLineRho; gc->procs.calcPolygonRho = __glNopPolygonRho; } else { current->textureFunc = __glTextureFragment; /* ** Pre-calculate min/mag switchover point. The rho calculation ** doesn't perform a square root (ever). Consequently, these ** constants are squared. */ if ((current->params.magFilter == GL_LINEAR) && ((current->params.minFilter == GL_NEAREST_MIPMAP_NEAREST) || (current->params.minFilter == GL_LINEAR_MIPMAP_NEAREST))) { current->c = ((__GLfloat) 2.0); } else { current->c = __glOne; } } } else { current->textureFunc = __glMipMapFragment; /* ** Pre-calculate min/mag switchover point. The rho ** calculation doesn't perform a square root (ever). ** Consequently, these constants are squared. */ if ((current->params.magFilter == GL_LINEAR) && ((current->params.minFilter == GL_NEAREST_MIPMAP_NEAREST) || (current->params.minFilter == GL_LINEAR_MIPMAP_NEAREST))) { current->c = ((__GLfloat) 2.0); } else { current->c = __glOne; } } /* Pick environment function */ baseFormat = current->level[0].baseFormat; switch (gc->state.texture.env[0].mode) { case GL_MODULATE: switch (baseFormat) { case GL_LUMINANCE: current->env = __glTextureModulateL; break; case GL_LUMINANCE_ALPHA: current->env = __glTextureModulateLA; break; case GL_RGB: current->env = __glTextureModulateRGB; break; case GL_RGBA: current->env = __glTextureModulateRGBA; break; case GL_ALPHA: current->env = __glTextureModulateA; break; case GL_INTENSITY: current->env = __glTextureModulateI; break; #ifdef NT default: ASSERTOPENGL(FALSE, "Unexpected baseFormat\n"); break; #endif } break; case GL_DECAL: switch (baseFormat) { case GL_LUMINANCE: current->env = __glNopGCCOLOR; break; case GL_LUMINANCE_ALPHA: current->env = __glNopGCCOLOR; break; case GL_RGB: current->env = __glTextureDecalRGB; break; case GL_RGBA: current->env = __glTextureDecalRGBA; break; case GL_ALPHA: current->env = __glNopGCCOLOR; break; case GL_INTENSITY: current->env = __glNopGCCOLOR; break; #ifdef NT default: ASSERTOPENGL(FALSE, "Unexpected baseFormat\n"); break; #endif } break; case GL_BLEND: switch (baseFormat) { case GL_LUMINANCE: current->env = __glTextureBlendL; break; case GL_LUMINANCE_ALPHA: current->env = __glTextureBlendLA; break; case GL_RGB: current->env = __glTextureBlendRGB; break; case GL_RGBA: current->env = __glTextureBlendRGBA; break; case GL_ALPHA: current->env = __glTextureBlendA; break; case GL_INTENSITY: current->env = __glTextureBlendI; break; #ifdef NT default: ASSERTOPENGL(FALSE, "Unexpected baseFormat\n"); break; #endif } break; case GL_REPLACE: switch (baseFormat) { case GL_LUMINANCE: current->env = __glTextureReplaceL; break; case GL_LUMINANCE_ALPHA: current->env = __glTextureReplaceLA; break; case GL_RGB: current->env = __glTextureReplaceRGB; break; case GL_RGBA: current->env = __glTextureReplaceRGBA; break; case GL_ALPHA: current->env = __glTextureReplaceA; break; case GL_INTENSITY: current->env = __glTextureReplaceI; break; #ifdef NT default: ASSERTOPENGL(FALSE, "Unexpected baseFormat\n"); break; #endif } break; #ifdef NT default: ASSERTOPENGL(FALSE, "Unexpected texture mode\n"); break; #endif } /* Pick mag/min functions */ switch (current->dim) { case 1: current->nearest = __glNearestFilter1; current->linear = __glLinearFilter1; break; case 2: current->nearest = __glNearestFilter2; current->linear = __glLinearFilter2; // Accelerate BGR{A}8 case when wrap modes are both REPEAT if( (current->params.sWrapMode == GL_REPEAT) && (current->params.tWrapMode == GL_REPEAT) ) { __GLmipMapLevel *lp = ¤t->level[0]; if( lp->extract == __glExtractTexelBGR8 ) current->linear = __glLinearFilter2_BGR8Repeat; else if( lp->extract == __glExtractTexelBGRA8 ) current->linear = __glLinearFilter2_BGRA8Repeat; } break; } /* set mag filter function */ switch (current->params.magFilter) { case GL_LINEAR: current->magnify = __glLinearFilter; break; case GL_NEAREST: current->magnify = __glNearestFilter; break; } /* set min filter function */ switch (current->params.minFilter) { case GL_LINEAR: current->minnify = __glLinearFilter; break; case GL_NEAREST: current->minnify = __glNearestFilter; break; case GL_NEAREST_MIPMAP_NEAREST: current->minnify = __glNMNFilter; break; case GL_LINEAR_MIPMAP_NEAREST: current->minnify = __glLMNFilter; break; case GL_NEAREST_MIPMAP_LINEAR: current->minnify = __glNMLFilter; break; case GL_LINEAR_MIPMAP_LINEAR: current->minnify = __glLMLFilter; break; } gc->procs.texture = current->textureFunc; } else { gc->procs.texture = 0; } } void FASTCALL __glGenericPickFogProcs(__GLcontext *gc) { #ifdef GL_WIN_specular_fog /* ** If specular shading is on, coerce the fog sub-system to go through ** DONT_CARE path. Disregard the GL_NICEST hint!!! */ #endif //GL_WIN_specular_fog if ((gc->state.enables.general & __GL_FOG_ENABLE) #ifdef GL_WIN_specular_fog || (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG) #endif //GL_WIN_specular_fog ) { if ((gc->state.hints.fog == GL_NICEST) #ifdef GL_WIN_specular_fog && !(gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG) #endif //GL_WIN_specular_fog ) { gc->procs.fogVertex = 0; /* Better not be called */ } else { if (gc->state.fog.mode == GL_LINEAR) gc->procs.fogVertex = __glFogVertexLinear; else gc->procs.fogVertex = __glFogVertex; } gc->procs.fogPoint = __glFogFragmentSlow; gc->procs.fogColor = __glFogColorSlow; } else { gc->procs.fogVertex = 0; gc->procs.fogPoint = 0; gc->procs.fogColor = 0; } } void FASTCALL __glGenericPickBufferProcs(__GLcontext *gc) { GLint i; __GLbufferMachine *buffers; buffers = &gc->buffers; buffers->doubleStore = GL_FALSE; /* Set draw buffer pointer */ switch (gc->state.raster.drawBuffer) { case GL_FRONT: gc->drawBuffer = gc->front; break; case GL_FRONT_AND_BACK: if (gc->modes.doubleBufferMode) { gc->drawBuffer = gc->back; buffers->doubleStore = GL_TRUE; } else { gc->drawBuffer = gc->front; } break; case GL_BACK: gc->drawBuffer = gc->back; break; case GL_AUX0: case GL_AUX1: case GL_AUX2: case GL_AUX3: i = gc->state.raster.drawBuffer - GL_AUX0; #if __GL_NUMBER_OF_AUX_BUFFERS > 0 gc->drawBuffer = &gc->auxBuffer[i]; #endif break; } } void FASTCALL __glGenericPickPixelProcs(__GLcontext *gc) { __GLpixelTransferMode *tm; __GLpixelMachine *pm; GLboolean mapColor; GLfloat red, green, blue, alpha; GLint entry; GLuint enables = gc->state.enables.general; __GLpixelMapHead *pmap; GLint i; /* Set read buffer pointer */ switch (gc->state.pixel.readBuffer) { case GL_FRONT: gc->readBuffer = gc->front; break; case GL_BACK: gc->readBuffer = gc->back; break; case GL_AUX0: case GL_AUX1: case GL_AUX2: case GL_AUX3: i = gc->state.pixel.readBuffer - GL_AUX0; #if __GL_NUMBER_OF_AUX_BUFFERS > 0 gc->readBuffer = &gc->auxBuffer[i]; #endif break; } if (gc->texture.textureEnabled || (gc->polygon.shader.modeFlags & __GL_SHADE_SLOW_FOG)) { gc->procs.pxStore = __glSlowDrawPixelsStore; } else { gc->procs.pxStore = gc->procs.store; } tm = &gc->state.pixel.transferMode; pm = &(gc->pixel); mapColor = tm->mapColor; if (mapColor || gc->modes.rgbMode || tm->indexShift || tm->indexOffset) { pm->iToICurrent = GL_FALSE; pm->iToRGBACurrent = GL_FALSE; pm->modifyCI = GL_TRUE; } else { pm->modifyCI = GL_FALSE; } if (tm->mapStencil || tm->indexShift || tm->indexOffset) { pm->modifyStencil = GL_TRUE; } else { pm->modifyStencil = GL_FALSE; } if (tm->d_scale != __glOne || tm->d_bias) { pm->modifyDepth = GL_TRUE; } else { pm->modifyDepth = GL_FALSE; } if (mapColor || tm->r_bias || tm->g_bias || tm->b_bias || tm->a_bias || tm->r_scale != __glOne || tm->g_scale != __glOne || tm->b_scale != __glOne || tm->a_scale != __glOne) { pm->modifyRGBA = GL_TRUE; pm->rgbaCurrent = GL_FALSE; } else { pm->modifyRGBA = GL_FALSE; } if (pm->modifyRGBA) { /* Compute default values for red, green, blue, alpha */ red = gc->state.pixel.transferMode.r_bias; green = gc->state.pixel.transferMode.g_bias; blue = gc->state.pixel.transferMode.b_bias; alpha = gc->state.pixel.transferMode.a_scale + gc->state.pixel.transferMode.a_bias; if (mapColor) { pmap = &gc->state.pixel.pixelMap[__GL_PIXEL_MAP_R_TO_R]; entry = (GLint)(red * pmap->size); if (entry < 0) entry = 0; else if (entry > pmap->size-1) entry = pmap->size-1; red = pmap->base.mapF[entry]; pmap = &gc->state.pixel.pixelMap[__GL_PIXEL_MAP_G_TO_G]; entry = (GLint)(green * pmap->size); if (entry < 0) entry = 0; else if (entry > pmap->size-1) entry = pmap->size-1; green = pmap->base.mapF[entry]; pmap = &gc->state.pixel.pixelMap[__GL_PIXEL_MAP_B_TO_B]; entry = (GLint)(blue * pmap->size); if (entry < 0) entry = 0; else if (entry > pmap->size-1) entry = pmap->size-1; blue = pmap->base.mapF[entry]; pmap = &gc->state.pixel.pixelMap[__GL_PIXEL_MAP_A_TO_A]; entry = (GLint)(alpha * pmap->size); if (entry < 0) entry = 0; else if (entry > pmap->size-1) entry = pmap->size-1; alpha = pmap->base.mapF[entry]; } else { if (red > __glOne) red = __glOne; else if (red < 0) red = 0; if (green > __glOne) green = __glOne; else if (green < 0) green = 0; if (blue > __glOne) blue = __glOne; else if (blue < 0) blue = 0; if (alpha > __glOne) alpha = __glOne; else if (alpha < 0) alpha = 0; } pm->red0Mod = red * gc->frontBuffer.redScale; pm->green0Mod = green * gc->frontBuffer.greenScale; pm->blue0Mod = blue * gc->frontBuffer.blueScale; pm->alpha1Mod = alpha * gc->frontBuffer.alphaScale; } else { pm->red0Mod = __glZero; pm->green0Mod = __glZero; pm->blue0Mod = __glZero; pm->alpha1Mod = gc->frontBuffer.alphaScale; } gc->procs.drawPixels = __glSlowPickDrawPixels; gc->procs.readPixels = __glSlowPickReadPixels; gc->procs.copyPixels = __glSlowPickCopyPixels; } /* ** pick the depth function pointers */ int FASTCALL __glGenericPickDepthProcs(__GLcontext *gc) { GLint depthIndex; depthIndex = gc->state.depth.testFunc - GL_NEVER; if (gc->modes.depthBits && gc->modes.haveDepthBuffer) { if (gc->state.depth.writeEnable == GL_FALSE) depthIndex += 8; if (gc->depthBuffer.buf.elementSize == 2) depthIndex += 16; } else { /* ** No depthBits so force StoreALWAYS_W, _glDT_ALWAYS_M, etc. */ depthIndex = (GL_ALWAYS - GL_NEVER) + 8; } (*gc->depthBuffer.pick)(gc, &gc->depthBuffer, depthIndex); gc->procs.DTPixel = __glCDTPixel[depthIndex]; #ifdef __GL_USEASMCODE gc->procs.span.depthTestPixel = __glSDepthTestPixel[depthIndex]; gc->procs.line.depthTestPixel = __glPDepthTestPixel[depthIndex]; if( gc->procs.line.depthTestLine ) { if( __glDTLine[depthIndex] ) { *(gc->procs.line.depthTestLine) = __glDTLine[depthIndex]; } else { /* ** If this happens, it may mean one of two things: ** (a) __glDTLine is malformed ** (b) A device-dependent line picker was a bit careless. ** This will probably happen if that implementation is ** not using the slow path. ** Eg: For NEWPORT, AA depth lines go through slow path, ** but non-AA depth lines have a fast path. When switching ** to a non-AA path, we may end up here, but that's ok, since ** we are not using the slow path. If that is about to happen, ** the line picker will be reinvoked. */ /* ** use some generic function here that will work */ *(gc->procs.line.depthTestLine) = __glDepthTestLine_asm; } } #endif return depthIndex; } void FASTCALL __glGenericValidate(__GLcontext *gc) { (*gc->procs.pickAllProcs)(gc); } void FASTCALL __glGenericPickAllProcs(__GLcontext *gc) { GLuint enables = gc->state.enables.general; GLuint modeFlags = 0; if (gc->dirtyMask & (__GL_DIRTY_TEXTURE | __GL_DIRTY_GENERIC)) { /* ** Set textureEnabled flag early on, so we can set modeFlags ** based upon it. */ (*gc->procs.pickTextureProcs)(gc); gc->texture.textureEnabled = gc->modes.rgbMode && gc->texture.currentTexture; } if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_LIGHTING)) { #ifdef _MCD_ MCD_STATE_DIRTY(gc, ENABLES); #endif // Check and see whether the current texturing settings will // completely replace the polygon color if (gc->texture.textureEnabled && #ifdef GL_EXT_flat_paletted_lighting (enables & __GL_PALETTED_LIGHTING_ENABLE) == 0 && #endif gc->state.texture.env[0].mode == GL_REPLACE && (gc->texture.currentTexture->level[0].baseFormat == GL_RGBA || gc->texture.currentTexture->level[0].baseFormat == GL_INTENSITY || gc->texture.currentTexture->level[0].baseFormat == GL_LUMINANCE_ALPHA || ((enables & __GL_BLEND_ENABLE) == 0 && (gc->texture.currentTexture->level[0].baseFormat == GL_LUMINANCE || gc->texture.currentTexture->level[0].baseFormat == GL_RGB)))) { modeFlags |= __GL_SHADE_FULL_REPLACE_TEXTURE; } } /* Compute shading mode flags before triangle, span, and line picker */ if (gc->modes.rgbMode) { modeFlags |= __GL_SHADE_RGB; if (gc->texture.textureEnabled) { modeFlags |= __GL_SHADE_TEXTURE; } if (enables & __GL_BLEND_ENABLE) { modeFlags |= __GL_SHADE_BLEND; } if (enables & __GL_ALPHA_TEST_ENABLE) { modeFlags |= __GL_SHADE_ALPHA_TEST; } if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { modeFlags |= __GL_SHADE_LOGICOP; } if (!gc->state.raster.rMask || !gc->state.raster.gMask || !gc->state.raster.bMask #ifndef NT // NT doesn't support destination alpha so there's no point // in worrying about the alpha mask since we'll never write // alpha values anyway || !gc->state.raster.aMask #endif ) { modeFlags |= __GL_SHADE_MASK; } } else { if (enables & __GL_INDEX_LOGIC_OP_ENABLE) { modeFlags |= __GL_SHADE_LOGICOP; } if (gc->state.raster.writeMask != __GL_MASK_INDEXI(gc, ~0)) { modeFlags |= __GL_SHADE_MASK; } } if (gc->state.light.shadingModel == GL_SMOOTH) { modeFlags |= __GL_SHADE_SMOOTH | __GL_SHADE_SMOOTH_LIGHT; #ifdef GL_WIN_phong_shading } else if (gc->state.light.shadingModel == GL_PHONG_WIN) { if (enables & __GL_LIGHTING_ENABLE) modeFlags |= __GL_SHADE_PHONG; else modeFlags |= __GL_SHADE_SMOOTH | __GL_SHADE_SMOOTH_LIGHT; #endif //GL_WIN_phong_shading } if ((enables & __GL_DEPTH_TEST_ENABLE) && gc->modes.haveDepthBuffer) { modeFlags |= ( __GL_SHADE_DEPTH_TEST | __GL_SHADE_DEPTH_ITER ); } if (enables & __GL_CULL_FACE_ENABLE) { modeFlags |= __GL_SHADE_CULL_FACE; } if (enables & __GL_DITHER_ENABLE) { modeFlags |= __GL_SHADE_DITHER; } if (enables & __GL_POLYGON_STIPPLE_ENABLE) { modeFlags |= __GL_SHADE_STIPPLE; } if (enables & __GL_LINE_STIPPLE_ENABLE) { modeFlags |= __GL_SHADE_LINE_STIPPLE; } if ((enables & __GL_STENCIL_TEST_ENABLE) && gc->modes.haveStencilBuffer) { modeFlags |= __GL_SHADE_STENCIL_TEST; } if ((enables & __GL_LIGHTING_ENABLE) && gc->state.light.model.twoSided) { modeFlags |= __GL_SHADE_TWOSIDED; } #ifdef GL_WIN_specular_fog /* ** Specularly lit textures using fog only if: ** -- Lighting is enabled ** -- Texturing is enabled ** -- Texturing mode is GL_MODULATE ** -- Lighting calculation is not skipped ** -- No two sided lighting */ if ( (gc->state.texture.env[0].mode == GL_MODULATE) && (enables & __GL_FOG_SPEC_TEX_ENABLE) && (enables & __GL_LIGHTING_ENABLE) && !(modeFlags & __GL_SHADE_TWOSIDED) && (modeFlags & __GL_SHADE_TEXTURE) && !( (modeFlags & __GL_SHADE_FULL_REPLACE_TEXTURE) && (gc->renderMode == GL_RENDER) ) ) { modeFlags |= __GL_SHADE_SPEC_FOG; modeFlags |= __GL_SHADE_INTERP_FOG; } #endif //GL_WIN_specular_fog if (enables & __GL_FOG_ENABLE) { /* Figure out type of fogging to do. Try to do cheap fog */ if (!(modeFlags & __GL_SHADE_TEXTURE) && #ifdef GL_WIN_phong_shading !(modeFlags & __GL_SHADE_PHONG) && #endif //GL_WIN_phong_shading (gc->state.hints.fog != GL_NICEST)) { /* #ifdef NT ** Cheap fog can be done. Now figure out which kind we ** will do. If smooth shading, its easy - just update ** the color in DrawPolyArray. Otherwise, set has flag ** later on to use smooth shading to do flat shaded fogging. #else ** Cheap fog can be done. Now figure out which kind we ** will do. If smooth shading, its easy - just change ** the calcColor proc (let the color proc picker do it). ** Otherwise, set has flag later on to use smooth shading ** to do flat shaded fogging. #endif */ modeFlags |= __GL_SHADE_CHEAP_FOG | __GL_SHADE_SMOOTH; } else { /* Use slowest fog mode */ modeFlags |= __GL_SHADE_SLOW_FOG; if ((gc->state.hints.fog == GL_NICEST) #ifdef GL_WIN_specular_fog && (!(modeFlags & __GL_SHADE_SPEC_FOG)) #endif //GL_WIN_specular_fog ) { modeFlags |= __GL_SHADE_COMPUTE_FOG; } else { modeFlags |= __GL_SHADE_INTERP_FOG; } } } gc->polygon.shader.modeFlags = modeFlags; if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_LIGHTING)) { (*gc->front->pick)(gc, gc->front); if (gc->modes.doubleBufferMode) { (*gc->back->pick)(gc, gc->back); } #if __GL_NUMBER_OF_AUX_BUFFERS > 0 { GLint i; for (i = 0; i < gc->modes.maxAuxBuffers; i++) { (*gc->auxBuffer[i].pick)(gc, &gc->auxBuffer[i]); } } #endif if (gc->modes.haveStencilBuffer) { (*gc->stencilBuffer.pick)(gc, &gc->stencilBuffer); } (*gc->procs.pickBufferProcs)(gc); /* ** Note: Must call gc->front->pick and gc->back->pick before calling ** pickStoreProcs. This also must be called prior to line, point, ** polygon, clipping, or bitmap pickers. The LIGHT implementation ** depends upon it. */ (*gc->procs.pickStoreProcs)(gc); #ifdef NT /* ** Compute the color material change bits before lighting since ** __glValidateLighting calls ComputeMaterialState. */ ComputeColorMaterialChange(gc); #endif __glValidateLighting(gc); /* ** Note: pickColorMaterialProcs is called frequently outside of this ** generic picking routine. */ (*gc->procs.pickColorMaterialProcs)(gc); (*gc->procs.pickBlendProcs)(gc); (*gc->procs.pickFogProcs)(gc); (*gc->procs.pickParameterClipProcs)(gc); (*gc->procs.pickClipProcs)(gc); /* ** Needs to be done after pickStoreProcs. */ (*gc->procs.pickRenderBitmapProcs)(gc); if (gc->validateMask & __GL_VALIDATE_ALPHA_FUNC) { __glValidateAlphaTest(gc); } } #ifdef NT // Compute paNeeds flags PANEEDS_TEXCOORD, PANEEDS_NORMAL, // PANEEDS_RASTERPOS_NORMAL, PANEEDS_CLIP_ONLY, and PANEEDS_SKIP_LIGHTING. if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_LIGHTING)) { GLuint paNeeds; paNeeds = gc->vertex.paNeeds; paNeeds &= ~(PANEEDS_TEXCOORD | PANEEDS_NORMAL | PANEEDS_RASTERPOS_NORMAL | PANEEDS_CLIP_ONLY | PANEEDS_SKIP_LIGHTING); // Compute PANEEDS_SKIP_LIGHTING flag. // If we're rendering with a replace mode texture which fills all // the color components then lighting is unnecessary in most cases. if ((modeFlags & __GL_SHADE_FULL_REPLACE_TEXTURE) && (gc->renderMode == GL_RENDER)) paNeeds |= PANEEDS_SKIP_LIGHTING; // Compute PANEEDS_TEXCOORD. // Feedback needs texture coordinates when the feedback type is // GL_3D_COLOR_TEXTURE or GL_4D_COLOR_TEXTURE whether or not it is // enabled. if (gc->texture.textureEnabled || gc->renderMode == GL_FEEDBACK) paNeeds |= PANEEDS_TEXCOORD; // Compute PANEEDS_NORMAL. #ifdef NEW_NORMAL_PROCESSING if(enables & __GL_LIGHTING_ENABLE && !(paNeeds & PANEEDS_SKIP_LIGHTING)) // uses PANEEDS_SKIP_LIGHTING computed above paNeeds |= PANEEDS_NORMAL; if ( ((paNeeds & PANEEDS_TEXCOORD) // uses PANEEDS_TEXCOORD computed above! && (enables & __GL_TEXTURE_GEN_S_ENABLE) && (gc->state.texture.s.mode == GL_SPHERE_MAP)) || ((paNeeds & PANEEDS_TEXCOORD) // uses PANEEDS_TEXCOORD computed above! && (enables & __GL_TEXTURE_GEN_T_ENABLE) && (gc->state.texture.t.mode == GL_SPHERE_MAP)) ) paNeeds |= PANEEDS_NORMAL_FOR_TEXTURE; #else if ( ((enables & __GL_LIGHTING_ENABLE) && !(paNeeds & PANEEDS_SKIP_LIGHTING)) // uses PANEEDS_SKIP_LIGHTING computed above || ((paNeeds & PANEEDS_TEXCOORD) // uses PANEEDS_TEXCOORD computed above! && (enables & __GL_TEXTURE_GEN_S_ENABLE) && (gc->state.texture.s.mode == GL_SPHERE_MAP)) || ((paNeeds & PANEEDS_TEXCOORD) // uses PANEEDS_TEXCOORD computed above! && (enables & __GL_TEXTURE_GEN_T_ENABLE) && (gc->state.texture.t.mode == GL_SPHERE_MAP)) ) paNeeds |= PANEEDS_NORMAL | PANEEDS_NORMAL_FOR_TEXTURE; #endif // Compute PANEEDS_RASTERPOS_NORMAL. #ifdef NEW_NORMAL_PROCESSING if (enables & __GL_LIGHTING_ENABLE) paNeeds |= PANEEDS_RASTERPOS_NORMAL; if ((enables & __GL_TEXTURE_GEN_S_ENABLE && gc->state.texture.s.mode == GL_SPHERE_MAP) || (enables & __GL_TEXTURE_GEN_T_ENABLE && gc->state.texture.t.mode == GL_SPHERE_MAP)) paNeeds |= PANEEDS_RASTERPOS_NORMAL_FOR_TEXTURE; #else if ( (enables & __GL_LIGHTING_ENABLE) || ((enables & __GL_TEXTURE_GEN_S_ENABLE) && (gc->state.texture.s.mode == GL_SPHERE_MAP)) || ((enables & __GL_TEXTURE_GEN_T_ENABLE) && (gc->state.texture.t.mode == GL_SPHERE_MAP)) ) paNeeds |= PANEEDS_RASTERPOS_NORMAL; #endif // Compute PANEEDS_CLIP_ONLY. // It is set in selection mode to take a fast path in DrawPolyArray. // It must be cleared by RasterPos before calling DrawPolyArray! if (gc->renderMode == GL_SELECT) { paNeeds |= PANEEDS_CLIP_ONLY; paNeeds &= ~PANEEDS_NORMAL; } gc->vertex.paNeeds = paNeeds; } // Compute PANEEDS_EDGEFLAG flag // __GL_DIRTY_POLYGON test is probably sufficient. if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_POLYGON)) { if (gc->state.polygon.frontMode != GL_FILL || gc->state.polygon.backMode != GL_FILL) gc->vertex.paNeeds |= PANEEDS_EDGEFLAG; else gc->vertex.paNeeds &= ~PANEEDS_EDGEFLAG; } #endif // NT if (gc->dirtyMask & __GL_DIRTY_POLYGON_STIPPLE) { /* ** Usually, the polygon stipple is converted immediately after ** it is changed. However, if the polygon stipple was changed ** when this context was the destination of a CopyContext, then ** the polygon stipple will be converted here. */ (*gc->procs.convertPolygonStipple)(gc); } // Compute paNeeds flags PANEEDS_FRONT_COLOR and PANEEDS_BACK_COLOR if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_POLYGON | __GL_DIRTY_LIGHTING | __GL_DIRTY_DEPTH)) { GLuint paNeeds; /* ** May be used for picking Rect() procs, need to check polygon ** bit. Must also be called after gc->vertex.needs is set.!!! ** Needs to be called prior to point, line, and triangle pickers. ** Also needs to be called after the store procs picker is called. */ (*gc->procs.pickVertexProcs)(gc); (*gc->procs.pickSpanProcs)(gc); (*gc->procs.pickTriangleProcs)(gc); #ifdef NT // Compute front and back color needs for polygons. // Points and lines always use the front color. // Unlit primitives always use the front color. // // Cull enable? Two sided? Cull face Color needs // N N BACK FRONT // N N FRONT FRONT // N N FRONT_AND_BACK FRONT // N Y BACK FRONT/BACK // N Y FRONT FRONT/BACK // N Y FRONT_AND_BACK FRONT/BACK // Y N BACK FRONT // Y N FRONT FRONT // Y N FRONT_AND_BACK None // Y Y BACK FRONT // Y Y FRONT BACK // Y Y FRONT_AND_BACK None paNeeds = gc->vertex.paNeeds; paNeeds &= ~(PANEEDS_FRONT_COLOR | PANEEDS_BACK_COLOR); if (enables & __GL_LIGHTING_ENABLE) { if (!(enables & __GL_CULL_FACE_ENABLE)) { if (gc->state.light.model.twoSided) paNeeds |= PANEEDS_FRONT_COLOR | PANEEDS_BACK_COLOR; else paNeeds |= PANEEDS_FRONT_COLOR; } else { if (!(gc->state.polygon.cull == GL_FRONT_AND_BACK)) { if (gc->state.polygon.cull == GL_FRONT && gc->state.light.model.twoSided) paNeeds |= PANEEDS_BACK_COLOR; else paNeeds |= PANEEDS_FRONT_COLOR; } } } else paNeeds |= PANEEDS_FRONT_COLOR; gc->vertex.paNeeds = paNeeds; #endif } if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_POINT | __GL_DIRTY_LIGHTING | __GL_DIRTY_DEPTH)) { (*gc->procs.pickPointProcs)(gc); } if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_LINE | __GL_DIRTY_LIGHTING | __GL_DIRTY_DEPTH)) { (*gc->procs.pickLineProcs)(gc); } if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_PIXEL | __GL_DIRTY_LIGHTING | __GL_DIRTY_DEPTH)) { (*gc->procs.pickPixelProcs)(gc); } /* ** deal with the depth function pointers last. This has to be done last. */ if (gc->dirtyMask & (__GL_DIRTY_GENERIC | __GL_DIRTY_DEPTH)) { (*gc->procs.pickDepthProcs)(gc); } gc->validateMask = 0; gc->dirtyMask = 0; }