windows-nt/Source/XPSP1/NT/multimedia/opengl/server/soft/so_textu.c
2020-09-26 16:20:57 +08:00

967 lines
25 KiB
C

/*
** Copyright 1991,1992, 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 <namesint.h>
#include <math.h>
#include <glmath.h>
/*
** Some math routines that are optimized in assembly
*/
#define __GL_M_LN2_INV ((__GLfloat) (1.0 / 0.69314718055994530942))
#define __GL_M_SQRT2 ((__GLfloat) 1.41421356237309504880)
/************************************************************************/
__GLtextureParamState * FASTCALL __glLookUpTextureParams(__GLcontext *gc, GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
return &gc->state.texture.texture[2].params;
case GL_TEXTURE_2D:
return &gc->state.texture.texture[3].params;
default:
return 0;
}
}
__GLtextureObjectState * FASTCALL __glLookUpTextureTexobjs(__GLcontext *gc,
GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
return &gc->state.texture.texture[2].texobjs;
case GL_TEXTURE_2D:
return &gc->state.texture.texture[3].texobjs;
default:
return 0;
}
}
__GLtexture * FASTCALL __glLookUpTexture(__GLcontext *gc, GLenum target)
{
switch (target) {
case GL_PROXY_TEXTURE_1D:
return &gc->texture.texture[0]->map;
case GL_PROXY_TEXTURE_2D:
return &gc->texture.texture[1]->map;
case GL_TEXTURE_1D:
return &gc->texture.texture[2]->map;
case GL_TEXTURE_2D:
return &gc->texture.texture[3]->map;
default:
return 0;
}
}
__GLtextureObject * FASTCALL __glLookUpTextureObject(__GLcontext *gc, GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
return gc->texture.boundTextures[2];
case GL_TEXTURE_2D:
return gc->texture.boundTextures[3];
default:
return 0;
}
}
/************************************************************************/
/*
* Set palette subdivision parameters
*/
void FASTCALL __glSetPaletteSubdivision(__GLtexture *tex, GLsizei subdiv)
{
tex->paletteSize = subdiv;
tex->paletteDivShift = __glIntLog2(subdiv);
tex->paletteDivision = (tex->paletteTotalSize >> tex->paletteDivShift)-1;
}
/*
* Initialize palette portion of a texture
*/
GLboolean FASTCALL __glInitTexturePalette(__GLcontext *gc, __GLtexture *tex)
{
#ifdef GL_EXT_paletted_texture
tex->paletteBaseFormat = GL_RGBA;
tex->paletteRequestedFormat = GL_RGBA;
tex->paletteTotalSize = 1;
__glSetPaletteSubdivision(tex, tex->paletteTotalSize);
tex->paletteTotalData = GCALLOC(gc, sizeof(RGBQUAD));
tex->paletteData = tex->paletteTotalData;
if (tex->paletteTotalData != NULL)
{
*(DWORD *)&tex->paletteTotalData[0] = 0xffffffff;
return GL_TRUE;
}
else
{
return GL_FALSE;
}
#else
return GL_TRUE;
#endif
}
/*
** Initialize everything in a texture object except the textureMachine.
*/
GLboolean FASTCALL __glInitTextureObject(__GLcontext *gc,
__GLtextureObject *texobj,
GLuint name, GLuint targetIndex)
{
ASSERTOPENGL(NULL != texobj, "No texobj\n");
texobj->targetIndex = targetIndex;
texobj->resident = GL_FALSE;
texobj->texture.map.texobjs.name = name;
texobj->texture.map.texobjs.priority = 1.0;
texobj->lowerPriority = NULL;
texobj->higherPriority = NULL;
texobj->loadKey = 0;
return __glInitTexturePalette(gc, &texobj->texture.map);
}
void __glCleanupTexture(__GLcontext *gc, __GLtexture *tex,
GLboolean freeBuffers)
{
GLint level, maxLevel;
if (tex->level != NULL)
{
if (freeBuffers)
{
maxLevel = gc->constants.maxMipMapLevel;
for (level = 0; level < maxLevel; level++)
{
if (tex->level[level].buffer != NULL)
{
GCFREE(gc, tex->level[level].buffer);
}
}
}
GCFREE(gc, tex->level);
}
#ifdef GL_EXT_paletted_texture
if (tex->paletteTotalData != NULL)
{
GCFREE(gc, tex->paletteTotalData);
}
#endif
}
GLvoid FASTCALL __glCleanupTexObj(__GLcontext *gc, void *pData)
{
__GLtextureObject *texobj = (__GLtextureObject *)pData;
// The last context to clean up shared state sets shared to NULL
// so don't depend on it being non-NULL
if (gc->texture.shared != NULL)
{
__glTexPriListRemove(gc, texobj, GL_TRUE);
}
__glCleanupTexture(gc, &texobj->texture.map, GL_TRUE);
GCFREE(gc, texobj);
}
GLvoid WINAPIV __glDisposeTexObj(__GLcontext *gc, void *pData)
{
__GLtextureObject *texobj = (__GLtextureObject *)pData;
#if DBG
if (gc->texture.shared != NULL)
{
__GL_NAMES_ASSERT_LOCKED(gc->texture.shared->namesArray);
}
#endif
texobj->refcount--;
ASSERTOPENGL(texobj->refcount >= 0, "Invalid refcount\n");
if (texobj->refcount == 0) {
__glCleanupTexObj(gc, pData);
}
}
static __GLnamesArrayTypeInfo texTypeInfo =
{
NULL, /* ptr to empty data struct */
sizeof(__GLtextureObject), /* dataSize */
__glDisposeTexObj, /* free callback */
NULL /* alloc callback */
};
void FASTCALL __glEarlyInitTextureState(__GLcontext *gc)
{
GLint numTextures, numEnvs;
GLint i,maxMipMapLevel;
__GLtextureObject *texobj;
/* XXX Override device dependent values */
gc->constants.numberOfTextures = 4;
gc->constants.maxTextureSize = 1 << (gc->constants.maxMipMapLevel - 1);
/* Allocate memory based on number of textures supported */
numTextures = gc->constants.numberOfTextures;
numEnvs = gc->constants.numberOfTextureEnvs;
gc->state.texture.texture = (__GLperTextureState*)
GCALLOCZ(gc, numTextures*sizeof(__GLperTextureState));
gc->texture.texture = (__GLperTextureMachine**)
GCALLOCZ(gc, numTextures*sizeof(__GLperTextureMachine*));
#ifdef NT
if (gc->texture.texture == NULL)
{
return;
}
#endif
gc->state.texture.env = (__GLtextureEnvState*)
GCALLOCZ(gc, numEnvs*sizeof(__GLtextureEnvState));
/*
** Init texture object structures.
** The default textures need to be turned into texture objects
** and stored away in the namesArray so they can be retrieved.
** Normally a texture object has only one textureMachine allocated
** with it because it supports only one object. The default texture
** texture object is special in that its textureMachine is an array
** of textureMachines, one for each target.
*/
gc->texture.shared = GCALLOCZ(gc, sizeof(__GLsharedTextureState));
if (gc->texture.shared == NULL)
{
return;
}
if (NULL == gc->texture.shared->namesArray) {
gc->texture.shared->namesArray = __glNamesNewArray(gc, &texTypeInfo);
}
maxMipMapLevel = gc->constants.maxMipMapLevel;
/*
** Set up the dummy texture objects for the default textures.
** Because the default textures are not shared, they should
** not be hung off of the namesArray structure.
*/
gc->texture.defaultTextures = (__GLtextureObject *)GCALLOCZ
(gc, numTextures*sizeof(__GLtextureObject));
if (gc->texture.defaultTextures == NULL)
{
return;
}
/* allocate the boundTextures array */
gc->texture.boundTextures = (__GLtextureObject **)GCALLOCZ
(gc, numTextures*sizeof(__GLtextureObject *));
if (gc->texture.boundTextures == NULL)
{
return;
}
// Allocate DirectDraw texture surface pointers
gc->texture.ddtex.pdds = (LPDIRECTDRAWSURFACE *)GCALLOCZ
(gc, maxMipMapLevel*sizeof(LPDIRECTDRAWSURFACE));
if (gc->texture.ddtex.pdds == NULL)
{
return;
}
if (!__glInitTextureObject(gc, &gc->texture.ddtex.texobj, __GL_TEX_DDRAW,
__GL_TEX_TARGET_INDEX_2D))
{
return;
}
gc->texture.ddtex.texobj.refcount = 1;
gc->texture.ddtex.texobj.texture.map.level = (__GLmipMapLevel*)
GCALLOCZ(gc, maxMipMapLevel*sizeof(__GLmipMapLevel));
texobj = gc->texture.defaultTextures;
for (i=0; i < numTextures; i++, texobj++) {
__glInitTextureObject(gc, texobj, 0/*name*/, i/*targetIndex*/);
ASSERTOPENGL(texobj->texture.map.texobjs.name == 0,
"Non-default texture at init time\n");
/*
** The refcount is unused because default textures aren't
** shared.
*/
texobj->refcount = 1;
/*
** Install the default textures into the gc.
*/
gc->texture.texture[i] = &(texobj->texture);
gc->texture.boundTextures[i] = texobj;
/* Allocate memory based on max mipmap level supported */
texobj->texture.map.level = (__GLmipMapLevel*)
GCALLOCZ(gc, maxMipMapLevel*sizeof(__GLmipMapLevel));
if (texobj->texture.map.level == NULL)
{
return;
}
__glTexPriListAdd(gc, texobj, GL_TRUE);
}
}
/*
** This routine is used to initialize a texture object.
** Texture objects must be initialized exactly the way the default
** textures are initialized at startup of the library.
*/
void FASTCALL __glInitTextureMachine(__GLcontext *gc, GLuint targetIndex,
__GLperTextureMachine *ptm,
GLboolean allocLevels)
{
GLint level, maxMipMapLevel;
ptm->map.gc = gc;
/*
** Can't copy the params currently in the gc state.texture params,
** because they might not be at init conditions.
*/
ptm->map.params.sWrapMode = GL_REPEAT;
ptm->map.params.tWrapMode = GL_REPEAT;
ptm->map.params.minFilter = GL_NEAREST_MIPMAP_LINEAR;
ptm->map.params.magFilter = GL_LINEAR;
switch (targetIndex) {
case 0:
ptm->map.dim = 1;
ptm->map.createLevel = __glCreateProxyLevel;
break;
case 1:
ptm->map.dim = 2;
ptm->map.createLevel = __glCreateProxyLevel;
break;
case 2:
ptm->map.dim = 1;
ptm->map.createLevel = __glCreateLevel;
break;
case 3:
ptm->map.dim = 2;
ptm->map.createLevel = __glCreateLevel;
break;
default:
break;
}
maxMipMapLevel = gc->constants.maxMipMapLevel;
if (allocLevels)
{
ptm->map.level = (__GLmipMapLevel*)
GCALLOCZ(gc, maxMipMapLevel*sizeof(__GLmipMapLevel));
if (ptm->map.level == NULL)
{
return;
}
}
/* Init each texture level */
for (level = 0; level < maxMipMapLevel; level++) {
ptm->map.level[level].requestedFormat = 1;
}
}
void FASTCALL __glInitTextureState(__GLcontext *gc)
{
__GLperTextureState *pts;
__GLtextureEnvState *tes;
__GLperTextureMachine **ptm;
GLint i, numTextures, numEnvs;
numTextures = gc->constants.numberOfTextures;
numEnvs = gc->constants.numberOfTextureEnvs;
gc->state.current.texture.w = __glOne;
/* Init each texture environment state */
tes = &gc->state.texture.env[0];
for (i = 0; i < numEnvs; i++, tes++) {
tes->mode = GL_MODULATE;
}
/* Init each textures state */
pts = &gc->state.texture.texture[0];
ptm = gc->texture.texture;
for (i = 0; i < numTextures; i++, pts++, ptm++) {
/* Init client state */
pts->texobjs.name = 0;
pts->texobjs.priority = 1.0;
/* Init machine state */
__glInitTextureMachine(gc, i, *ptm, GL_FALSE);
pts->params = (*ptm)->map.params;
}
/* Init rest of texture state */
gc->state.texture.s.mode = GL_EYE_LINEAR;
gc->state.texture.s.eyePlaneEquation.x = __glOne;
gc->state.texture.s.objectPlaneEquation.x = __glOne;
gc->state.texture.t.mode = GL_EYE_LINEAR;
gc->state.texture.t.eyePlaneEquation.y = __glOne;
gc->state.texture.t.objectPlaneEquation.y = __glOne;
gc->state.texture.r.mode = GL_EYE_LINEAR;
gc->state.texture.q.mode = GL_EYE_LINEAR;
// Initialize DirectDraw texture
__glInitTextureMachine(gc, __GL_TEX_TARGET_INDEX_2D,
&gc->texture.ddtex.texobj.texture, GL_FALSE);
}
void __glFreeSharedTextureState(__GLcontext *gc)
{
#ifdef NT
__glNamesLockArray(gc, gc->texture.shared->namesArray);
gc->texture.shared->namesArray->refcount--;
if (gc->texture.shared->namesArray->refcount == 0)
{
__GLsharedTextureState *shared;
__glTexPriListUnloadAll(gc);
// NULL the shared pointer first, preventing its reuse
// after we unlock it. We need to unlock before we free it
// because the critical section will be cleaned up in the
// free
shared = gc->texture.shared;
gc->texture.shared = NULL;
__glNamesFreeArray(gc, shared->namesArray);
GCFREE(gc, shared);
}
else
{
__glNamesUnlockArray(gc, gc->texture.shared->namesArray);
gc->texture.shared = NULL;
}
#else
gc->texture.namesArray->refcount--;
if (gc->texture.namesArray->refcount == 0)
{
__glNamesFreeArray(gc, gc->texture.namesArray);
}
gc->texture.namesArray = NULL;
#endif
}
void FASTCALL __glFreeTextureState(__GLcontext *gc)
{
__GLperTextureMachine **ptm;
GLint i, level, numTextures;
/*
** Clean up all allocs associated with texture objects.
*/
numTextures = gc->constants.numberOfTextures;
ptm = gc->texture.texture;
for (i = 0; i < numTextures; i++, ptm++)
{
// If the texture selected is a texture object, unbind it
// This protects any shared texture objects plus it selects
// the default texture so it gets cleaned up
if ( (*ptm) != NULL)
{
if ((*ptm)->map.texobjs.name != 0)
{
__glBindTexture(gc, i, 0, GL_FALSE);
}
ASSERTOPENGL((*ptm)->map.texobjs.name == 0,
"Texture object still bound during cleanup");
}
// Pull the default texture out of the priority list.
// If we failed partway through initialization we may not
// have added the texture to the list so we need to check
// whether it is appropriate to call remove.
if (gc->texture.defaultTextures != NULL)
{
if (gc->texture.defaultTextures[i].texture.map.level != NULL)
{
__glTexPriListRemove(gc, gc->texture.defaultTextures+i,
GL_FALSE);
}
}
if ( (*ptm) != NULL)
{
__glCleanupTexture(gc, &(*ptm)->map, GL_TRUE);
}
}
__glFreeSharedTextureState(gc);
GCFREE(gc, gc->texture.texture);
GCFREE(gc, gc->texture.boundTextures);
GCFREE(gc, gc->texture.defaultTextures);
GCFREE(gc, gc->state.texture.texture);
GCFREE(gc, gc->state.texture.env);
gc->texture.texture = NULL;
gc->texture.boundTextures = NULL;
gc->texture.defaultTextures = NULL;
gc->state.texture.texture = NULL;
gc->state.texture.env = NULL;
// Free DirectDraw texture state
GCFREE(gc, gc->texture.ddtex.pdds);
gc->texture.ddtex.pdds = NULL;
__glCleanupTexture(gc, &gc->texture.ddtex.texobj.texture.map, GL_FALSE);
}
/************************************************************************/
void APIPRIVATE __glim_TexGenfv(GLenum coord, GLenum pname, const GLfloat pv[])
{
__GLtextureCoordState *tcs;
__GLtransform *tr;
__GL_SETUP_NOT_IN_BEGIN();
switch (coord) {
case GL_S: tcs = &gc->state.texture.s; break;
case GL_T: tcs = &gc->state.texture.t; break;
case GL_R: tcs = &gc->state.texture.r; break;
case GL_Q: tcs = &gc->state.texture.q; break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
switch (pname) {
case GL_TEXTURE_GEN_MODE:
switch (((GLenum) FTOL(pv[0]))) {
case GL_EYE_LINEAR:
case GL_OBJECT_LINEAR:
tcs->mode = (GLenum) FTOL(pv[0]);
break;
case GL_SPHERE_MAP:
if ((coord == GL_R) || (coord == GL_Q)) {
__glSetError(GL_INVALID_ENUM);
return;
}
tcs->mode = (GLenum) FTOL(pv[0]);
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
break;
case GL_OBJECT_PLANE:
tcs->objectPlaneEquation.x = pv[0];
tcs->objectPlaneEquation.y = pv[1];
tcs->objectPlaneEquation.z = pv[2];
tcs->objectPlaneEquation.w = pv[3];
break;
case GL_EYE_PLANE:
#ifdef NT
tr = gc->transform.modelView;
if (tr->flags & XFORM_UPDATE_INVERSE)
__glComputeInverseTranspose(gc, tr);
(*tr->inverseTranspose.xf4)(&tcs->eyePlaneEquation, pv,
&tr->inverseTranspose);
#else
/*XXX transform should not be in generic code */
tcs->eyePlaneSet.x = pv[0];
tcs->eyePlaneSet.y = pv[1];
tcs->eyePlaneSet.z = pv[2];
tcs->eyePlaneSet.w = pv[3];
tr = gc->transform.modelView;
if (tr->flags & XFORM_UPDATE_INVERSE) {
(*gc->procs.computeInverseTranspose)(gc, tr);
}
(*tr->inverseTranspose.xf4)(&tcs->eyePlaneEquation,
&tcs->eyePlaneSet.x,
&tr->inverseTranspose);
#endif
break;
default:
__glSetError(GL_INVALID_ENUM);
return;
}
__GL_DELAY_VALIDATE(gc);
MCD_STATE_DIRTY(gc, TEXGEN);
}
/************************************************************************/
void APIPRIVATE __glim_TexParameterfv(GLenum target, GLenum pname, const GLfloat pv[])
{
__GLtextureParamState *pts;
GLenum e;
GLboolean bTexState = GL_TRUE;
__GL_SETUP_NOT_IN_BEGIN();
pts = __glLookUpTextureParams(gc, target);
if (!pts) {
bad_enum:
bTexState = GL_FALSE;
__glSetError(GL_INVALID_ENUM);
return;
}
switch (pname) {
case GL_TEXTURE_WRAP_S:
switch (e = (GLenum) FTOL(pv[0])) {
case GL_REPEAT:
case GL_CLAMP:
pts->sWrapMode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_WRAP_T:
switch (e = (GLenum) FTOL(pv[0])) {
case GL_REPEAT:
case GL_CLAMP:
pts->tWrapMode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_MIN_FILTER:
switch (e = (GLenum)FTOL(pv[0])) {
case GL_NEAREST:
case GL_LINEAR:
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
pts->minFilter = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_MAG_FILTER:
switch (e = (GLenum)FTOL(pv[0])) {
case GL_NEAREST:
case GL_LINEAR:
pts->magFilter = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_BORDER_COLOR:
__glClampColorf(gc, &pts->borderColor, pv);
break;
case GL_TEXTURE_PRIORITY:
{
__GLtextureObject *texobj;
__GLtextureObjectState *ptos;
ptos = __glLookUpTextureTexobjs(gc, target);
ptos->priority = __glClampf(pv[0], __glZero, __glOne);
texobj = __glLookUpTextureObject(gc, target);
texobj->texture.map.texobjs.priority = ptos->priority;
__glTexPriListChangePriority(gc, texobj, GL_TRUE);
}
bTexState = GL_FALSE;
break;
default:
goto bad_enum;
}
__GL_DELAY_VALIDATE(gc);
#ifdef _MCD_
if (bTexState &&
gc->texture.currentTexture &&
(pts == &gc->texture.currentTexture->params))
{
MCD_STATE_DIRTY(gc, TEXTURE);
}
#endif
}
void APIPRIVATE __glim_TexParameteriv(GLenum target, GLenum pname, const GLint pv[])
{
__GLtextureParamState *pts;
GLenum e;
GLboolean bTexState = GL_TRUE;
__GL_SETUP_NOT_IN_BEGIN();
pts = __glLookUpTextureParams(gc, target);
if (!pts) {
bad_enum:
bTexState = GL_FALSE;
__glSetError(GL_INVALID_ENUM);
return;
}
switch (pname) {
case GL_TEXTURE_WRAP_S:
switch (e = (GLenum) pv[0]) {
case GL_REPEAT:
case GL_CLAMP:
pts->sWrapMode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_WRAP_T:
switch (e = (GLenum) pv[0]) {
case GL_REPEAT:
case GL_CLAMP:
pts->tWrapMode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_MIN_FILTER:
switch (e = (GLenum) pv[0]) {
case GL_NEAREST:
case GL_LINEAR:
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
pts->minFilter = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_MAG_FILTER:
switch (e = (GLenum) pv[0]) {
case GL_NEAREST:
case GL_LINEAR:
pts->magFilter = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_BORDER_COLOR:
__glClampColori(gc, &pts->borderColor, pv);
break;
case GL_TEXTURE_PRIORITY:
{
__GLfloat priority;
__GLtextureObjectState *ptos;
__GLtextureObject *texobj;
ptos = __glLookUpTextureTexobjs(gc, target);
priority = __glClampf(__GL_I_TO_FLOAT(pv[0]), __glZero, __glOne);
ptos->priority = priority;
texobj = __glLookUpTextureObject(gc, target);
texobj->texture.map.texobjs.priority = priority;
__glTexPriListChangePriority(gc, texobj, GL_TRUE);
}
bTexState = GL_FALSE;
break;
default:
goto bad_enum;
}
__GL_DELAY_VALIDATE(gc);
#ifdef _MCD_
if (bTexState &&
gc->texture.currentTexture &&
(pts == &gc->texture.currentTexture->params))
{
MCD_STATE_DIRTY(gc, TEXTURE);
}
#endif
}
/************************************************************************/
void APIPRIVATE __glim_TexEnvfv(GLenum target, GLenum pname, const GLfloat pv[])
{
__GLtextureEnvState *tes;
GLenum e;
__GL_SETUP_NOT_IN_BEGIN();
if(target < GL_TEXTURE_ENV) {
__glSetError(GL_INVALID_ENUM);
return;
}
target -= GL_TEXTURE_ENV;
#ifdef NT
// target is unsigned!
if (target >= (GLenum) gc->constants.numberOfTextureEnvs) {
#else
if (target >= gc->constants.numberOfTextureEnvs) {
#endif // NT
bad_enum:
__glSetError(GL_INVALID_ENUM);
return;
}
tes = &gc->state.texture.env[target];
switch (pname) {
case GL_TEXTURE_ENV_MODE:
switch(e = (GLenum) FTOL(pv[0])) {
case GL_MODULATE:
case GL_DECAL:
case GL_BLEND:
case GL_REPLACE:
tes->mode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_ENV_COLOR:
__glClampAndScaleColorf(gc, &tes->color, pv);
break;
default:
goto bad_enum;
}
__GL_DELAY_VALIDATE(gc);
MCD_STATE_DIRTY(gc, TEXENV);
}
void APIPRIVATE __glim_TexEnviv(GLenum target, GLenum pname, const GLint pv[])
{
__GLtextureEnvState *tes;
GLenum e;
__GL_SETUP_NOT_IN_BEGIN();
if(target < GL_TEXTURE_ENV) {
__glSetError(GL_INVALID_ENUM);
return;
}
target -= GL_TEXTURE_ENV;
#ifdef NT
// target is unsigned!
if (target >= (GLenum) gc->constants.numberOfTextureEnvs) {
#else
if (target >= gc->constants.numberOfTextureEnvs) {
#endif // NT
bad_enum:
__glSetError(GL_INVALID_ENUM);
return;
}
tes = &gc->state.texture.env[target];
switch (pname) {
case GL_TEXTURE_ENV_MODE:
switch(e = (GLenum) pv[0]) {
case GL_MODULATE:
case GL_DECAL:
case GL_BLEND:
case GL_REPLACE:
tes->mode = e;
break;
default:
goto bad_enum;
}
break;
case GL_TEXTURE_ENV_COLOR:
__glClampAndScaleColori(gc, &tes->color, pv);
break;
default:
goto bad_enum;
}
__GL_DELAY_VALIDATE(gc);
MCD_STATE_DIRTY(gc, TEXENV);
}
/************************************************************************/
GLboolean FASTCALL __glIsTextureConsistent(__GLcontext *gc, GLenum name)
{
__GLtexture *tex = __glLookUpTexture(gc, name);
__GLtextureParamState *params = __glLookUpTextureParams(gc, name);
GLint i, width, height;
GLint maxLevel;
GLint border;
GLenum baseFormat;
GLenum requestedFormat;
if ((tex->level[0].width == 0) || (tex->level[0].height == 0)) {
return GL_FALSE;
}
border = tex->level[0].border;
width = tex->level[0].width - border*2;
height = tex->level[0].height - border*2;
maxLevel = gc->constants.maxMipMapLevel;
baseFormat = tex->level[0].baseFormat;
requestedFormat = tex->level[0].requestedFormat;
switch(gc->state.texture.env[0].mode) {
case GL_DECAL:
if (baseFormat != GL_RGB && baseFormat != GL_RGBA) {
return GL_FALSE;
}
break;
default:
break;
}
/* If not-mipmapping, we are ok */
switch (params->minFilter) {
case GL_NEAREST:
case GL_LINEAR:
return GL_TRUE;
default:
break;
}
i = 0;
while (++i < maxLevel) {
if (width == 1 && height == 1) break;
width >>= 1;
if (width == 0) width = 1;
height >>= 1;
if (height == 0) height = 1;
if (tex->level[i].border != border ||
(GLenum)tex->level[i].requestedFormat != requestedFormat ||
tex->level[i].width != width + border*2 ||
tex->level[i].height != height + border*2)
{
return GL_FALSE;
}
}
return GL_TRUE;
}
/***********************************************************************/
#ifdef GL_WIN_multiple_textures
void APIPRIVATE __glim_CurrentTextureIndexWIN(GLuint index)
{
}
void APIPRIVATE __glim_NthTexCombineFuncWIN(GLuint index,
GLenum leftColorFactor, GLenum colorOp, GLenum rightColorFactor,
GLenum leftAlphaFactor, GLenum alphaOp, GLenum rightAlphaFactor)
{
}
#endif // GL_WIN_multiple_textures