#include "glheader.h"
#include "colormac.h"
+#include "colortab.h"
#include "context.h"
#include "enums.h"
#include "extensions.h"
#include "macros.h"
+#include "nvfragprog.h"
#include "texobj.h"
#include "teximage.h"
#include "texstate.h"
/**********************************************************************/
-void
+void GLAPIENTRY
_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
{
GET_CURRENT_CONTEXT(ctx);
if (texUnit->LodBias == param[0])
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->LodBias = CLAMP(param[0], -ctx->Const.MaxTextureLodBias,
- ctx->Const.MaxTextureLodBias);
+ texUnit->LodBias = param[0];
}
else {
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
}
}
else if (target == GL_POINT_SPRITE_NV) {
- /* GL_NV_point_sprite */
- if (!ctx->Extensions.NV_point_sprite) {
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ if (!ctx->Extensions.NV_point_sprite
+ && !ctx->Extensions.ARB_point_sprite) {
_mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
return;
}
}
-void
+void GLAPIENTRY
_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
{
_mesa_TexEnvfv( target, pname, ¶m );
-void
+void GLAPIENTRY
_mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
{
GLfloat p[4];
}
-void
+void GLAPIENTRY
_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
{
GLfloat p[4];
}
-void
+void GLAPIENTRY
_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
{
GET_CURRENT_CONTEXT(ctx);
}
}
else if (target == GL_POINT_SPRITE_NV) {
- /* GL_NV_point_sprite */
- if (!ctx->Extensions.NV_point_sprite) {
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ if (!ctx->Extensions.NV_point_sprite
+ && !ctx->Extensions.ARB_point_sprite) {
_mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
return;
}
}
-void
+void GLAPIENTRY
_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
{
GET_CURRENT_CONTEXT(ctx);
}
}
else if (target == GL_POINT_SPRITE_NV) {
- /* GL_NV_point_sprite */
- if (!ctx->Extensions.NV_point_sprite) {
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ if (!ctx->Extensions.NV_point_sprite
+ && !ctx->Extensions.ARB_point_sprite) {
_mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
return;
}
/* Texture Parameters */
/**********************************************************************/
+static GLboolean
+_mesa_validate_texture_wrap_mode(GLcontext * ctx,
+ GLenum target, GLenum eparam)
+{
+ const struct gl_extensions * const e = & ctx->Extensions;
-void
+ if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
+ (eparam == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) {
+ /* any texture target */
+ return GL_TRUE;
+ }
+ else if (target != GL_TEXTURE_RECTANGLE_NV &&
+ (eparam == GL_REPEAT ||
+ (eparam == GL_MIRRORED_REPEAT &&
+ e->ARB_texture_mirrored_repeat) ||
+ (eparam == GL_MIRROR_CLAMP_EXT &&
+ (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
+ (eparam == GL_MIRROR_CLAMP_TO_EDGE_EXT &&
+ (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
+ (eparam == GL_MIRROR_CLAMP_TO_BORDER_EXT &&
+ (e->EXT_texture_mirror_clamp)))) {
+ /* non-rectangle texture */
+ return GL_TRUE;
+ }
+
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return GL_FALSE;
+}
+
+
+void GLAPIENTRY
_mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param )
{
_mesa_TexParameterfv(target, pname, ¶m);
}
-void
+void GLAPIENTRY
_mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
{
GET_CURRENT_CONTEXT(ctx);
case GL_TEXTURE_WRAP_S:
if (texObj->WrapS == eparam)
return;
- if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
- (eparam == GL_CLAMP_TO_BORDER &&
- ctx->Extensions.ARB_texture_border_clamp)) {
- /* any texture target */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->WrapS = eparam;
- }
- else if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
- (eparam == GL_REPEAT ||
- (eparam == GL_MIRRORED_REPEAT &&
- ctx->Extensions.ARB_texture_mirrored_repeat) ||
- (eparam == GL_MIRROR_CLAMP_ATI &&
- ctx->Extensions.ATI_texture_mirror_once) ||
- (eparam == GL_MIRROR_CLAMP_TO_EDGE_ATI &&
- ctx->Extensions.ATI_texture_mirror_once))) {
- /* non-rectangle texture */
+ if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
texObj->WrapS = eparam;
}
else {
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
return;
}
break;
case GL_TEXTURE_WRAP_T:
if (texObj->WrapT == eparam)
return;
- if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
- (eparam == GL_CLAMP_TO_BORDER &&
- ctx->Extensions.ARB_texture_border_clamp)) {
- /* any texture target */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->WrapT = eparam;
- }
- else if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
- (eparam == GL_REPEAT ||
- (eparam == GL_MIRRORED_REPEAT &&
- ctx->Extensions.ARB_texture_mirrored_repeat) ||
- (eparam == GL_MIRROR_CLAMP_ATI &&
- ctx->Extensions.ATI_texture_mirror_once) ||
- (eparam == GL_MIRROR_CLAMP_TO_EDGE_ATI &&
- ctx->Extensions.ATI_texture_mirror_once))) {
- /* non-rectangle texture */
+ if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
texObj->WrapT = eparam;
}
else {
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
return;
}
break;
case GL_TEXTURE_WRAP_R:
if (texObj->WrapR == eparam)
return;
- if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
- (eparam == GL_CLAMP_TO_BORDER &&
- ctx->Extensions.ARB_texture_border_clamp)) {
- /* any texture target */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->WrapR = eparam;
- }
- else if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
- (eparam == GL_REPEAT ||
- (eparam == GL_MIRRORED_REPEAT &&
- ctx->Extensions.ARB_texture_mirrored_repeat) ||
- (eparam == GL_MIRROR_CLAMP_ATI &&
- ctx->Extensions.ATI_texture_mirror_once) ||
- (eparam == GL_MIRROR_CLAMP_TO_EDGE_ATI &&
- ctx->Extensions.ATI_texture_mirror_once))) {
- /* non-rectangle texture */
+ if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
texObj->WrapR = eparam;
}
else {
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return;
}
break;
case GL_TEXTURE_BORDER_COLOR:
return;
}
break;
+ case GL_TEXTURE_LOD_BIAS:
+ /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias*/
+ if (ctx->Extensions.EXT_texture_lod_bias) {
+ if (texObj->LodBias != params[0]) {
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texObj->LodBias = params[0];
+ }
+ }
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
}
-void
+void GLAPIENTRY
_mesa_TexParameteri( GLenum target, GLenum pname, GLint param )
{
GLfloat fparam[4];
}
-void
+void GLAPIENTRY
_mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
{
GLfloat fparam[4];
}
-void
+void GLAPIENTRY
_mesa_GetTexLevelParameterfv( GLenum target, GLint level,
GLenum pname, GLfloat *params )
{
}
-void
+void GLAPIENTRY
_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
GLenum pname, GLint *params )
{
-void
+void GLAPIENTRY
_mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
{
GET_CURRENT_CONTEXT(ctx);
return;
}
break;
+ case GL_TEXTURE_LOD_BIAS:
+ if (ctx->Extensions.EXT_texture_lod_bias) {
+ *params = obj->LodBias;
+ break;
+ }
+ break;
default:
; /* silence warnings */
}
}
-void
+void GLAPIENTRY
_mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
{
GET_CURRENT_CONTEXT(ctx);
switch (pname) {
case GL_TEXTURE_MAG_FILTER:
*params = (GLint) obj->MagFilter;
+ case GL_TEXTURE_LOD_BIAS:
+ if (ctx->Extensions.EXT_texture_lod_bias) {
+ *params = (GLint) obj->LodBias;
+ break;
+ }
+ break;
return;
case GL_TEXTURE_MIN_FILTER:
*params = (GLint) obj->MinFilter;
/* Texture Coord Generation */
/**********************************************************************/
-
-void
+#if FEATURE_texgen
+void GLAPIENTRY
_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
{
GET_CURRENT_CONTEXT(ctx);
}
-void
+void GLAPIENTRY
_mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params )
{
GLfloat p[4];
}
-void
+void GLAPIENTRY
_mesa_TexGend(GLenum coord, GLenum pname, GLdouble param )
{
GLfloat p = (GLfloat) param;
}
-void
+void GLAPIENTRY
_mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params )
{
GLfloat p[4];
}
-void
+void GLAPIENTRY
_mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param )
{
_mesa_TexGenfv(coord, pname, ¶m);
}
-void
+void GLAPIENTRY
_mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
{
_mesa_TexGeniv( coord, pname, ¶m );
-void
+void GLAPIENTRY
_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
{
GET_CURRENT_CONTEXT(ctx);
-void
+void GLAPIENTRY
_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
{
GET_CURRENT_CONTEXT(ctx);
-void
+void GLAPIENTRY
_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
{
GET_CURRENT_CONTEXT(ctx);
return;
}
}
-
+#endif
/* GL_ARB_multitexture */
-void
+void GLAPIENTRY
_mesa_ActiveTextureARB( GLenum target )
{
GET_CURRENT_CONTEXT(ctx);
/* GL_ARB_multitexture */
-void
+void GLAPIENTRY
_mesa_ClientActiveTextureARB( GLenum target )
{
GET_CURRENT_CONTEXT(ctx);
/* Pixel Texgen Extensions */
/**********************************************************************/
-void
+void GLAPIENTRY
_mesa_PixelTexGenSGIX(GLenum mode)
{
GLenum newRgbSource, newAlphaSource;
}
-void
+void GLAPIENTRY
_mesa_PixelTexGenParameterfSGIS(GLenum target, GLfloat value)
{
_mesa_PixelTexGenParameteriSGIS(target, (GLint) value);
}
-void
+void GLAPIENTRY
_mesa_PixelTexGenParameterfvSGIS(GLenum target, const GLfloat *value)
{
_mesa_PixelTexGenParameteriSGIS(target, (GLint) *value);
}
-void
+void GLAPIENTRY
_mesa_PixelTexGenParameteriSGIS(GLenum target, GLint value)
{
GET_CURRENT_CONTEXT(ctx);
}
-void
+void GLAPIENTRY
_mesa_PixelTexGenParameterivSGIS(GLenum target, const GLint *value)
{
_mesa_PixelTexGenParameteriSGIS(target, *value);
}
-void
+void GLAPIENTRY
_mesa_GetPixelTexGenParameterfvSGIS(GLenum target, GLfloat *value)
{
GET_CURRENT_CONTEXT(ctx);
}
-void
+void GLAPIENTRY
_mesa_GetPixelTexGenParameterivSGIS(GLenum target, GLint *value)
{
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelTexGenParameterivSGIS(target)");
}
}
+
+
+
+/**********************************************************************/
+/***** State management *****/
+/**********************************************************************/
+
+
+/**
+ * \note This routine refers to derived texture attribute values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_textures(), below.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_matrices( GLcontext *ctx )
+{
+ GLuint i;
+
+ ctx->Texture._TexMatEnabled = 0;
+
+ for (i=0; i < ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->TextureMatrixStack[i].Top->flags & MAT_DIRTY) {
+ _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
+
+ if (ctx->Texture.Unit[i]._ReallyEnabled &&
+ ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
+
+ if (ctx->Driver.TextureMatrix)
+ ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
+ }
+ }
+}
+
+
+
+
+/**
+ * \note This routine refers to derived texture matrix values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_texture_matrices, above.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_state( GLcontext *ctx )
+{
+ GLuint unit;
+
+ ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are
+ * actual changes.
+ */
+
+ ctx->Texture._EnabledUnits = 0;
+ ctx->Texture._GenFlags = 0;
+ ctx->Texture._TexMatEnabled = 0;
+ ctx->Texture._TexGenEnabled = 0;
+
+ /* Update texture unit state.
+ * XXX this loop should probably be broken into separate loops for
+ * texture coord units and texture image units.
+ */
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLuint enableBits;
+
+ texUnit->_Current = NULL;
+ texUnit->_ReallyEnabled = 0;
+ texUnit->_GenFlags = 0;
+
+ /* Get the bitmask of texture enables */
+ if (ctx->FragmentProgram.Enabled && ctx->FragmentProgram.Current) {
+ enableBits = ctx->FragmentProgram.Current->TexturesUsed[unit];
+ }
+ else {
+ if (!texUnit->Enabled)
+ continue;
+ enableBits = texUnit->Enabled;
+ }
+
+ /* Look for the highest-priority texture target that's enabled and
+ * complete. That's the one we'll use for texturing. If we're using
+ * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
+ */
+ if (enableBits & TEXTURE_CUBE_BIT) {
+ struct gl_texture_object *texObj = texUnit->CurrentCubeMap;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_CUBE_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_3D_BIT)) {
+ struct gl_texture_object *texObj = texUnit->Current3D;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_3D_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_RECT_BIT)) {
+ struct gl_texture_object *texObj = texUnit->CurrentRect;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_RECT_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_2D_BIT)) {
+ struct gl_texture_object *texObj = texUnit->Current2D;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_2D_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_1D_BIT)) {
+ struct gl_texture_object *texObj = texUnit->Current1D;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_1D_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled) {
+ continue;
+ }
+
+ if (texUnit->_ReallyEnabled)
+ ctx->Texture._EnabledUnits |= (1 << unit);
+
+ if (texUnit->TexGenEnabled) {
+ if (texUnit->TexGenEnabled & S_BIT) {
+ texUnit->_GenFlags |= texUnit->_GenBitS;
+ }
+ if (texUnit->TexGenEnabled & T_BIT) {
+ texUnit->_GenFlags |= texUnit->_GenBitT;
+ }
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ texUnit->_GenFlags |= texUnit->_GenBitQ;
+ }
+ if (texUnit->TexGenEnabled & R_BIT) {
+ texUnit->_GenFlags |= texUnit->_GenBitR;
+ }
+
+ ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
+ ctx->Texture._GenFlags |= texUnit->_GenFlags;
+ }
+
+ if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
+ }
+
+ ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
+ /* Fragment programs may need texture coordinates but not the
+ * corresponding texture images.
+ */
+ if (ctx->FragmentProgram.Enabled && ctx->FragmentProgram.Current) {
+ ctx->Texture._EnabledCoordUnits |=
+ (ctx->FragmentProgram.Current->InputsRead >> FRAG_ATTRIB_TEX0);
+ }
+}
+
+
+void _mesa_update_texture( GLcontext *ctx, GLuint new_state )
+{
+ if (new_state & _NEW_TEXTURE_MATRIX)
+ update_texture_matrices( ctx );
+
+ if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
+ update_texture_state( ctx );
+}
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+/**
+ * Allocate the proxy textures for the given context.
+ *
+ * \param ctx the context to allocate proxies for.
+ *
+ * \return GL_TRUE on success, or GL_FALSE on failure
+ *
+ * If run out of memory part way through the allocations, clean up and return
+ * GL_FALSE.
+ */
+static GLboolean
+alloc_proxy_textures( GLcontext *ctx )
+{
+ ctx->Texture.Proxy1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
+ if (!ctx->Texture.Proxy1D)
+ goto cleanup;
+
+ ctx->Texture.Proxy2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D);
+ if (!ctx->Texture.Proxy2D)
+ goto cleanup;
+
+ ctx->Texture.Proxy3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D);
+ if (!ctx->Texture.Proxy3D)
+ goto cleanup;
+
+ ctx->Texture.ProxyCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB);
+ if (!ctx->Texture.ProxyCubeMap)
+ goto cleanup;
+
+ ctx->Texture.ProxyRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV);
+ if (!ctx->Texture.ProxyRect)
+ goto cleanup;
+
+ return GL_TRUE;
+
+ cleanup:
+ if (ctx->Texture.Proxy1D)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D);
+ if (ctx->Texture.Proxy2D)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D);
+ if (ctx->Texture.Proxy3D)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D);
+ if (ctx->Texture.ProxyCubeMap)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap);
+ if (ctx->Texture.ProxyRect)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect);
+ return GL_FALSE;
+}
+
+
+/**
+ * Initialize a texture unit.
+ *
+ * \param ctx GL context.
+ * \param unit texture unit number to be initialized.
+ */
+static void
+init_texture_unit( GLcontext *ctx, GLuint unit )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ texUnit->EnvMode = GL_MODULATE;
+ ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
+
+ texUnit->CombineModeRGB = GL_MODULATE;
+ texUnit->CombineModeA = GL_MODULATE;
+ texUnit->CombineSourceRGB[0] = GL_TEXTURE;
+ texUnit->CombineSourceRGB[1] = GL_PREVIOUS_EXT;
+ texUnit->CombineSourceRGB[2] = GL_CONSTANT_EXT;
+ texUnit->CombineSourceA[0] = GL_TEXTURE;
+ texUnit->CombineSourceA[1] = GL_PREVIOUS_EXT;
+ texUnit->CombineSourceA[2] = GL_CONSTANT_EXT;
+ texUnit->CombineOperandRGB[0] = GL_SRC_COLOR;
+ texUnit->CombineOperandRGB[1] = GL_SRC_COLOR;
+ texUnit->CombineOperandRGB[2] = GL_SRC_ALPHA;
+ texUnit->CombineOperandA[0] = GL_SRC_ALPHA;
+ texUnit->CombineOperandA[1] = GL_SRC_ALPHA;
+ texUnit->CombineOperandA[2] = GL_SRC_ALPHA;
+ texUnit->CombineScaleShiftRGB = 0;
+ texUnit->CombineScaleShiftA = 0;
+
+ texUnit->TexGenEnabled = 0;
+ texUnit->GenModeS = GL_EYE_LINEAR;
+ texUnit->GenModeT = GL_EYE_LINEAR;
+ texUnit->GenModeR = GL_EYE_LINEAR;
+ texUnit->GenModeQ = GL_EYE_LINEAR;
+ texUnit->_GenBitS = TEXGEN_EYE_LINEAR;
+ texUnit->_GenBitT = TEXGEN_EYE_LINEAR;
+ texUnit->_GenBitR = TEXGEN_EYE_LINEAR;
+ texUnit->_GenBitQ = TEXGEN_EYE_LINEAR;
+
+ /* Yes, these plane coefficients are correct! */
+ ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
+
+ texUnit->Current1D = ctx->Shared->Default1D;
+ texUnit->Current2D = ctx->Shared->Default2D;
+ texUnit->Current3D = ctx->Shared->Default3D;
+ texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
+ texUnit->CurrentRect = ctx->Shared->DefaultRect;
+}
+
+
+GLboolean _mesa_init_texture( GLcontext * ctx )
+{
+ int i;
+
+ assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
+ assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
+
+ /* Effectively bind the default textures to all texture units */
+ ctx->Shared->Default1D->RefCount += MAX_TEXTURE_UNITS;
+ ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS;
+ ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS;
+ ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS;
+ ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS;
+
+ /* Texture group */
+ ctx->Texture.CurrentUnit = 0; /* multitexture */
+ ctx->Texture._EnabledUnits = 0;
+ for (i=0; i<MAX_TEXTURE_UNITS; i++)
+ init_texture_unit( ctx, i );
+ ctx->Texture.SharedPalette = GL_FALSE;
+ _mesa_init_colortable(&ctx->Texture.Palette);
+
+ /* Allocate proxy textures */
+ if (!alloc_proxy_textures( ctx ))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+void _mesa_free_texture_data( GLcontext *ctx )
+{
+ int i;
+
+ /* Free proxy texture objects */
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D );
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D );
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D );
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap );
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect );
+
+ for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
+ _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
+}