/* ** 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 #include #include /* ** 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