* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+/**
+ * \file texstate.c
+ *
+ * Texture state handling.
+ */
#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"
#define ENUM_TO_DOUBLE(X) ((GLdouble)(X))
#endif
+/**
+ * Default texture combine environment state. This is used to initialize
+ * a context's texture units and as the basis for converting "classic"
+ * texture environmnets to ARB_texture_env_combine style values.
+ */
+static const struct gl_tex_env_combine_state default_combine_state = {
+ GL_MODULATE, GL_MODULATE,
+ { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
+ { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
+ { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA },
+ { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
+ 0, 0,
+ 2, 2
+};
void
dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias;
/* GL_EXT_texture_env_combine */
- dst->Texture.Unit[i].CombineModeRGB = src->Texture.Unit[i].CombineModeRGB;
- dst->Texture.Unit[i].CombineModeA = src->Texture.Unit[i].CombineModeA;
- COPY_3V(dst->Texture.Unit[i].CombineSourceRGB, src->Texture.Unit[i].CombineSourceRGB);
- COPY_3V(dst->Texture.Unit[i].CombineSourceA, src->Texture.Unit[i].CombineSourceA);
- COPY_3V(dst->Texture.Unit[i].CombineOperandRGB, src->Texture.Unit[i].CombineOperandRGB);
- COPY_3V(dst->Texture.Unit[i].CombineOperandA, src->Texture.Unit[i].CombineOperandA);
- dst->Texture.Unit[i].CombineScaleShiftRGB = src->Texture.Unit[i].CombineScaleShiftRGB;
- dst->Texture.Unit[i].CombineScaleShiftA = src->Texture.Unit[i].CombineScaleShiftA;
+ dst->Texture.Unit[i].Combine.ModeRGB = src->Texture.Unit[i].Combine.ModeRGB;
+ dst->Texture.Unit[i].Combine.ModeA = src->Texture.Unit[i].Combine.ModeA;
+ COPY_3V(dst->Texture.Unit[i].Combine.SourceRGB, src->Texture.Unit[i].Combine.SourceRGB);
+ COPY_3V(dst->Texture.Unit[i].Combine.SourceA, src->Texture.Unit[i].Combine.SourceA);
+ COPY_3V(dst->Texture.Unit[i].Combine.OperandRGB, src->Texture.Unit[i].Combine.OperandRGB);
+ COPY_3V(dst->Texture.Unit[i].Combine.OperandA, src->Texture.Unit[i].Combine.OperandA);
+ dst->Texture.Unit[i].Combine.ScaleShiftRGB = src->Texture.Unit[i].Combine.ScaleShiftRGB;
+ dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA;
/* texture object state */
_mesa_copy_texture_object(dst->Texture.Unit[i].Current1D,
const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
_mesa_printf("Texture Unit %d\n", unit);
_mesa_printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
- _mesa_printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineModeRGB));
- _mesa_printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineModeA));
- _mesa_printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceRGB[0]));
- _mesa_printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceRGB[1]));
- _mesa_printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceRGB[2]));
- _mesa_printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceA[0]));
- _mesa_printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceA[1]));
- _mesa_printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineSourceA[2]));
- _mesa_printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandRGB[0]));
- _mesa_printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandRGB[1]));
- _mesa_printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandRGB[2]));
- _mesa_printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandA[0]));
- _mesa_printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandA[1]));
- _mesa_printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->CombineOperandA[2]));
- _mesa_printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->CombineScaleShiftRGB);
- _mesa_printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->CombineScaleShiftA);
+ _mesa_printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
+ _mesa_printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
+ _mesa_printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
+ _mesa_printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
+ _mesa_printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
+ _mesa_printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
+ _mesa_printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
+ _mesa_printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
+ _mesa_printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
+ _mesa_printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
+ _mesa_printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
+ _mesa_printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
+ _mesa_printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
+ _mesa_printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
+ _mesa_printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
+ _mesa_printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
_mesa_printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
}
/* Texture Environment */
/**********************************************************************/
+/**
+ * Convert "classic" texture environment to ARB_texture_env_combine style
+ * environments.
+ *
+ * \param state texture_env_combine state vector to be filled-in.
+ * \param mode Classic texture environment mode (i.e., \c GL_REPLACE,
+ * \c GL_BLEND, \c GL_DECAL, etc.).
+ * \param tex_base_format Base format of the texture associated with the
+ * texture unit.
+ */
+static void
+calculate_derived_texenv( struct gl_tex_env_combine_state * state,
+ GLenum mode, GLenum tex_base_format )
+{
+ GLenum mode_rgb;
+ GLenum mode_a;
-void
+ *state = default_combine_state;
+
+ switch( tex_base_format ) {
+ case GL_ALPHA:
+ state->SourceRGB[0] = GL_PREVIOUS;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_RGBA:
+ break;
+
+ case GL_LUMINANCE:
+ case GL_RGB:
+ case GL_YCBCR_MESA:
+ state->SourceA[0] = GL_PREVIOUS;
+ break;
+
+ default:
+ state->SourceRGB[0] = GL_PREVIOUS;
+ state->SourceA[0] = GL_PREVIOUS;
+ state->ModeRGB = GL_REPLACE;
+ state->ModeA = GL_REPLACE;
+ ASSERT(0);
+ return;
+ }
+
+ switch( mode ) {
+ case GL_REPLACE:
+ case GL_MODULATE:
+ mode_rgb = (tex_base_format == GL_ALPHA) ? GL_REPLACE : mode;
+ mode_a = mode;
+ break;
+
+ case GL_DECAL:
+ mode_rgb = GL_INTERPOLATE;
+ mode_a = GL_REPLACE;
+
+ state->SourceA[0] = GL_PREVIOUS;
+
+ /* Having alpha / luminance / intensity textures replace using the
+ * incoming fragment color matches the definition in NV_texture_shader.
+ * The 1.5 spec simply marks these as "undefined".
+ */
+ switch( tex_base_format ) {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ state->SourceRGB[0] = GL_PREVIOUS;
+ break;
+ case GL_RGB:
+ case GL_YCBCR_MESA:
+ mode_rgb = GL_REPLACE;
+ break;
+ case GL_RGBA:
+ state->SourceRGB[2] = GL_TEXTURE;
+ break;
+ }
+ break;
+
+ case GL_BLEND:
+ mode_rgb = GL_INTERPOLATE;
+ mode_a = GL_MODULATE;
+
+ switch( tex_base_format ) {
+ case GL_ALPHA:
+ mode_rgb = GL_REPLACE;
+ break;
+ case GL_INTENSITY:
+ mode_a = GL_INTERPOLATE;
+ /* FALLTHROUGH */
+ case GL_LUMINANCE:
+ case GL_RGB:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ case GL_YCBCR_MESA:
+ state->SourceRGB[2] = GL_TEXTURE;
+ state->SourceA[2] = GL_TEXTURE;
+ state->SourceRGB[0] = GL_CONSTANT;
+ state->OperandRGB[2] = GL_SRC_COLOR;
+ break;
+ }
+ break;
+
+ case GL_ADD:
+ mode_rgb = (tex_base_format == GL_ALPHA) ? GL_REPLACE : GL_ADD;
+ mode_a = (tex_base_format == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
+ break;
+
+ default:
+ mode_rgb = GL_REPLACE;
+ mode_a = GL_REPLACE;
+ ASSERT(0);
+ break;
+ }
+
+ state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
+ ? mode_rgb : GL_REPLACE;
+ state->ModeA = (state->SourceA[0] != GL_PREVIOUS)
+ ? mode_a : GL_REPLACE;
+}
+
+void GLAPIENTRY
_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
{
GET_CURRENT_CONTEXT(ctx);
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
texUnit->EnvMode = mode;
+
+ /* FIXME: Is this needed here or is having it in
+ * FIXME: update_texture_state enough?
+ */
+ if ( mode == GL_COMBINE ) {
+ texUnit->_CurrentCombine = & texUnit->Combine;
+ }
+ else if ( texUnit->_Current != NULL ) {
+ calculate_derived_texenv( & texUnit->_EnvMode, mode,
+ texUnit->_Current->Image[0][0]->Format );
+ texUnit->_CurrentCombine = & texUnit->_EnvMode;
+ }
}
else {
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
return;
}
- if (texUnit->CombineModeRGB == mode)
+ if (texUnit->Combine.ModeRGB == mode)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineModeRGB = mode;
+ texUnit->Combine.ModeRGB = mode;
}
else {
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
return;
}
- if (texUnit->CombineModeA == mode)
+ if (texUnit->Combine.ModeA == mode)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineModeA = mode;
+ texUnit->Combine.ModeA = mode;
}
else {
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
(ctx->Extensions.ATI_texture_env_combine3 &&
(source == GL_ZERO || source == GL_ONE))) {
/* legal */
- if (texUnit->CombineSourceRGB[s] == source)
+ if (texUnit->Combine.SourceRGB[s] == source)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineSourceRGB[s] = source;
+ texUnit->Combine.SourceRGB[s] = source;
}
else {
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
(ctx->Extensions.ATI_texture_env_combine3 &&
(source == GL_ZERO || source == GL_ONE))) {
/* legal */
- if (texUnit->CombineSourceA[s] == source)
+ if (texUnit->Combine.SourceA[s] == source)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineSourceA[s] = source;
+ texUnit->Combine.SourceA[s] = source;
}
else {
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
case GL_ONE_MINUS_SRC_COLOR:
case GL_SRC_ALPHA:
case GL_ONE_MINUS_SRC_ALPHA:
- if (texUnit->CombineOperandRGB[s] == operand)
+ if (texUnit->Combine.OperandRGB[s] == operand)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineOperandRGB[s] = operand;
+ texUnit->Combine.OperandRGB[s] = operand;
break;
default:
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
switch (operand) {
case GL_SRC_ALPHA:
case GL_ONE_MINUS_SRC_ALPHA:
- if (texUnit->CombineOperandA[pname-GL_OPERAND0_ALPHA] ==
+ if (texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] ==
operand)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineOperandA[pname-GL_OPERAND0_ALPHA] = operand;
+ texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] = operand;
break;
default:
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
case GL_ONE_MINUS_SRC_COLOR: /* ARB combine only */
case GL_SRC_ALPHA:
case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
- if (texUnit->CombineOperandRGB[2] == operand)
+ if (texUnit->Combine.OperandRGB[2] == operand)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineOperandRGB[2] = operand;
+ texUnit->Combine.OperandRGB[2] = operand;
break;
default:
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
switch (operand) {
case GL_SRC_ALPHA:
case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
- if (texUnit->CombineOperandA[2] == operand)
+ if (texUnit->Combine.OperandA[2] == operand)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineOperandA[2] = operand;
+ texUnit->Combine.OperandA[2] = operand;
break;
default:
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
"glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
return;
}
- if (texUnit->CombineScaleShiftRGB == newshift)
+ if (texUnit->Combine.ScaleShiftRGB == newshift)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineScaleShiftRGB = newshift;
+ texUnit->Combine.ScaleShiftRGB = newshift;
}
else {
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
"glTexEnv(GL_ALPHA_SCALE not 1, 2 or 4)" );
return;
}
- if (texUnit->CombineScaleShiftA == newshift)
+ if (texUnit->Combine.ScaleShiftA == newshift)
return;
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->CombineScaleShiftA = newshift;
+ texUnit->Combine.ScaleShiftA = newshift;
}
else {
TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
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);
case GL_COMBINE_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineModeRGB;
+ *params = (GLfloat) texUnit->Combine.ModeRGB;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_COMBINE_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineModeA;
+ *params = (GLfloat) texUnit->Combine.ModeA;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_SOURCE0_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineSourceRGB[0];
+ *params = (GLfloat) texUnit->Combine.SourceRGB[0];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_SOURCE1_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineSourceRGB[1];
+ *params = (GLfloat) texUnit->Combine.SourceRGB[1];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_SOURCE2_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineSourceRGB[2];
+ *params = (GLfloat) texUnit->Combine.SourceRGB[2];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_SOURCE0_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineSourceA[0];
+ *params = (GLfloat) texUnit->Combine.SourceA[0];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_SOURCE1_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineSourceA[1];
+ *params = (GLfloat) texUnit->Combine.SourceA[1];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_SOURCE2_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineSourceA[2];
+ *params = (GLfloat) texUnit->Combine.SourceA[2];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_OPERAND0_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineOperandRGB[0];
+ *params = (GLfloat) texUnit->Combine.OperandRGB[0];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_OPERAND1_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineOperandRGB[1];
+ *params = (GLfloat) texUnit->Combine.OperandRGB[1];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_OPERAND2_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineOperandRGB[2];
+ *params = (GLfloat) texUnit->Combine.OperandRGB[2];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_OPERAND0_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineOperandA[0];
+ *params = (GLfloat) texUnit->Combine.OperandA[0];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_OPERAND1_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineOperandA[1];
+ *params = (GLfloat) texUnit->Combine.OperandA[1];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_OPERAND2_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->CombineOperandA[2];
+ *params = (GLfloat) texUnit->Combine.OperandA[2];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
case GL_RGB_SCALE:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- if (texUnit->CombineScaleShiftRGB == 0)
+ if (texUnit->Combine.ScaleShiftRGB == 0)
*params = 1.0;
- else if (texUnit->CombineScaleShiftRGB == 1)
+ else if (texUnit->Combine.ScaleShiftRGB == 1)
*params = 2.0;
else
*params = 4.0;
case GL_ALPHA_SCALE:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- if (texUnit->CombineScaleShiftA == 0)
+ if (texUnit->Combine.ScaleShiftA == 0)
*params = 1.0;
- else if (texUnit->CombineScaleShiftA == 1)
+ else if (texUnit->Combine.ScaleShiftA == 1)
*params = 2.0;
else
*params = 4.0;
}
}
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);
case GL_COMBINE_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineModeRGB;
+ *params = (GLint) texUnit->Combine.ModeRGB;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_COMBINE_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineModeA;
+ *params = (GLint) texUnit->Combine.ModeA;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_SOURCE0_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineSourceRGB[0];
+ *params = (GLint) texUnit->Combine.SourceRGB[0];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_SOURCE1_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineSourceRGB[1];
+ *params = (GLint) texUnit->Combine.SourceRGB[1];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_SOURCE2_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineSourceRGB[2];
+ *params = (GLint) texUnit->Combine.SourceRGB[2];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_SOURCE0_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineSourceA[0];
+ *params = (GLint) texUnit->Combine.SourceA[0];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_SOURCE1_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineSourceA[1];
+ *params = (GLint) texUnit->Combine.SourceA[1];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_SOURCE2_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineSourceA[2];
+ *params = (GLint) texUnit->Combine.SourceA[2];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_OPERAND0_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineOperandRGB[0];
+ *params = (GLint) texUnit->Combine.OperandRGB[0];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_OPERAND1_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineOperandRGB[1];
+ *params = (GLint) texUnit->Combine.OperandRGB[1];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_OPERAND2_RGB:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineOperandRGB[2];
+ *params = (GLint) texUnit->Combine.OperandRGB[2];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_OPERAND0_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineOperandA[0];
+ *params = (GLint) texUnit->Combine.OperandA[0];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_OPERAND1_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineOperandA[1];
+ *params = (GLint) texUnit->Combine.OperandA[1];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_OPERAND2_ALPHA:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->CombineOperandA[2];
+ *params = (GLint) texUnit->Combine.OperandA[2];
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
case GL_RGB_SCALE:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- if (texUnit->CombineScaleShiftRGB == 0)
+ if (texUnit->Combine.ScaleShiftRGB == 0)
*params = 1;
- else if (texUnit->CombineScaleShiftRGB == 1)
+ else if (texUnit->Combine.ScaleShiftRGB == 1)
*params = 2;
else
*params = 4;
case GL_ALPHA_SCALE:
if (ctx->Extensions.EXT_texture_env_combine ||
ctx->Extensions.ARB_texture_env_combine) {
- if (texUnit->CombineScaleShiftA == 0)
+ if (texUnit->Combine.ScaleShiftA == 0)
*params = 1;
- else if (texUnit->CombineScaleShiftA == 1)
+ else if (texUnit->Combine.ScaleShiftA == 1)
*params = 2;
else
*params = 4;
}
}
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];
- fparam[0] = (GLfloat) param;
+ if (pname == GL_TEXTURE_PRIORITY)
+ fparam[0] = INT_TO_FLOAT(param);
+ else
+ fparam[0] = (GLfloat) param;
fparam[1] = fparam[2] = fparam[3] = 0.0;
_mesa_TexParameterfv(target, pname, fparam);
}
-void
+void GLAPIENTRY
_mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
{
GLfloat fparam[4];
fparam[3] = INT_TO_FLOAT(params[3]);
}
else {
- fparam[0] = (GLfloat) params[0];
+ if (pname == GL_TEXTURE_PRIORITY)
+ fparam[0] = INT_TO_FLOAT(params[0]);
+ else
+ fparam[0] = (GLfloat) params[0];
fparam[1] = fparam[2] = fparam[3] = 0.0F;
}
_mesa_TexParameterfv(target, pname, fparam);
}
-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;
}
return;
case GL_TEXTURE_PRIORITY:
- *params = (GLint) obj->Priority;
+ *params = FLOAT_TO_INT(obj->Priority);
return;
case GL_TEXTURE_MIN_LOD:
*params = (GLint) obj->MinLod;
/* 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];
p[0] = (GLfloat) params[0];
- p[1] = (GLfloat) params[1];
- p[2] = (GLfloat) params[2];
- p[3] = (GLfloat) params[3];
+ if (pname == GL_TEXTURE_GEN_MODE) {
+ p[1] = p[2] = p[3] = 0.0F;
+ }
+ else {
+ p[1] = (GLfloat) params[1];
+ p[2] = (GLfloat) params[2];
+ p[3] = (GLfloat) params[3];
+ }
_mesa_TexGenfv(coord, pname, p);
}
-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];
p[0] = (GLfloat) params[0];
- p[1] = (GLfloat) params[1];
- p[2] = (GLfloat) params[2];
- p[3] = (GLfloat) params[3];
+ if (pname == GL_TEXTURE_GEN_MODE) {
+ p[1] = p[2] = p[3] = 0.0F;
+ }
+ else {
+ p[1] = (GLfloat) params[1];
+ p[2] = (GLfloat) params[2];
+ p[3] = (GLfloat) params[3];
+ }
_mesa_TexGenfv( coord, pname, p );
}
-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->EnvMode == GL_COMBINE ) {
+ texUnit->_CurrentCombine = & texUnit->Combine;
+ }
+ else {
+ calculate_derived_texenv( & texUnit->_EnvMode,
+ texUnit->EnvMode,
+ texUnit->_Current->Image[0][0]->Format );
+ texUnit->_CurrentCombine = & texUnit->_EnvMode;
+ }
+
+ switch (texUnit->_CurrentCombine->ModeRGB) {
+ case GL_REPLACE:
+ texUnit->_CurrentCombine->_NumArgsRGB = 1;
+ break;
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_SUBTRACT:
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ texUnit->_CurrentCombine->_NumArgsRGB = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ texUnit->_CurrentCombine->_NumArgsRGB = 3;
+ break;
+ default:
+ texUnit->_CurrentCombine->_NumArgsRGB = 0;
+ ASSERT(0);
+ break;
+ }
+
+ switch (texUnit->_CurrentCombine->ModeA) {
+ case GL_REPLACE:
+ texUnit->_CurrentCombine->_NumArgsA = 1;
+ break;
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_SUBTRACT:
+ texUnit->_CurrentCombine->_NumArgsA = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ texUnit->_CurrentCombine->_NumArgsA = 3;
+ break;
+ default:
+ texUnit->_CurrentCombine->_NumArgsA = 0;
+ ASSERT(0);
+ break;
+ }
+
+ 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->Combine = default_combine_state;
+ texUnit->_EnvMode = default_combine_state;
+ texUnit->_CurrentCombine = & texUnit->_EnvMode;
+
+ 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 );
+}