/** Set an RGB or A combiner mode/function */ static void set_combiner_mode(struct gl_context *ctx, struct gl_texture_unit *texUnit, GLenum pname, GLenum mode) { GLboolean legal; switch (mode) { case GL_REPLACE: case GL_MODULATE: case GL_ADD: case GL_ADD_SIGNED: case GL_INTERPOLATE: legal = GL_TRUE; break; case GL_SUBTRACT: legal = ctx->Extensions.ARB_texture_env_combine; break; case GL_DOT3_RGB: // case GL_DOT3_RGBA: legal = (ctx->Extensions.EXT_texture_env_dot3 && pname == GL_COMBINE_RGB); break; // case GL_MODULATE_ADD_ATI: // case GL_MODULATE_SIGNED_ADD_ATI: // case GL_MODULATE_SUBTRACT_ATI: // legal = (ctx->API == API_OPENGL_COMPAT && // ctx->Extensions.ATI_texture_env_combine3); // break; default: legal = GL_FALSE; } if (!legal) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } switch (pname) { case GL_COMBINE_RGB: if (texUnit->Combine.ModeRGB == mode) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ModeRGB = mode; break; case GL_COMBINE_ALPHA: if (texUnit->Combine.ModeA == mode) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ModeA = mode; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); } }
static void set_combiner_scale(GLcontext *ctx, struct gl_texture_unit *texUnit, GLenum pname, GLfloat scale) { GLuint shift; if (!ctx->Extensions.EXT_texture_env_combine && !ctx->Extensions.ARB_texture_env_combine) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)"); return; } if (scale == 1.0F) { shift = 0; } else if (scale == 2.0F) { shift = 1; } else if (scale == 4.0F) { shift = 2; } else { _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" ); return; } switch (pname) { case GL_RGB_SCALE: if (texUnit->Combine.ScaleShiftRGB == shift) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ScaleShiftRGB = shift; break; case GL_ALPHA_SCALE: if (texUnit->Combine.ScaleShiftA == shift) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ScaleShiftA = shift; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); } }
/** Set texture env mode */ static void set_env_mode(GLcontext *ctx, struct gl_texture_unit *texUnit, GLenum mode) { GLboolean legal; if (texUnit->EnvMode == mode) return; switch (mode) { case GL_MODULATE: case GL_BLEND: case GL_DECAL: case GL_REPLACE: legal = GL_TRUE; break; case GL_REPLACE_EXT: mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */ legal = GL_TRUE; break; case GL_ADD: legal = ctx->Extensions.EXT_texture_env_add; break; case GL_COMBINE: legal = (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine); break; case GL_COMBINE4_NV: legal = ctx->Extensions.NV_texture_env_combine4; break; default: legal = GL_FALSE; } if (legal) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->EnvMode = mode; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); } }
void GLAPIENTRY _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) { GLuint maxUnit; GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit; ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)"); return; } texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; #define TE_ERROR(errCode, msg, value) \ _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value)); if (target == GL_TEXTURE_ENV) { switch (pname) { case GL_TEXTURE_ENV_MODE: { GLenum mode = (GLenum) (GLint) *param; if (mode == GL_REPLACE_EXT) mode = GL_REPLACE; if (texUnit->EnvMode == mode) return; if (mode == GL_MODULATE || mode == GL_BLEND || mode == GL_DECAL || mode == GL_REPLACE || (mode == GL_ADD && ctx->Extensions.EXT_texture_env_add) || (mode == GL_COMBINE && (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine))) { /* legal */ FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->EnvMode = mode; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } } break; case GL_TEXTURE_ENV_COLOR: { GLfloat tmp[4]; tmp[0] = CLAMP( param[0], 0.0F, 1.0F ); tmp[1] = CLAMP( param[1], 0.0F, 1.0F ); tmp[2] = CLAMP( param[2], 0.0F, 1.0F ); tmp[3] = CLAMP( param[3], 0.0F, 1.0F ); if (TEST_EQ_4V(tmp, texUnit->EnvColor)) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); COPY_4FV(texUnit->EnvColor, tmp); } break; case GL_COMBINE_RGB: if (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine) { const GLenum mode = (GLenum) (GLint) *param; if (texUnit->Combine.ModeRGB == mode) return; switch (mode) { case GL_REPLACE: case GL_MODULATE: case GL_ADD: case GL_ADD_SIGNED: case GL_INTERPOLATE: /* OK */ break; case GL_SUBTRACT: if (!ctx->Extensions.ARB_texture_env_combine) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } break; case GL_DOT3_RGB_EXT: case GL_DOT3_RGBA_EXT: if (!ctx->Extensions.EXT_texture_env_dot3) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } break; case GL_DOT3_RGB: case GL_DOT3_RGBA: if (!ctx->Extensions.ARB_texture_env_dot3) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } break; case GL_MODULATE_ADD_ATI: case GL_MODULATE_SIGNED_ADD_ATI: case GL_MODULATE_SUBTRACT_ATI: if (!ctx->Extensions.ATI_texture_env_combine3) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ModeRGB = mode; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_COMBINE_ALPHA: if (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine) { const GLenum mode = (GLenum) (GLint) *param; if (texUnit->Combine.ModeA == mode) return; switch (mode) { case GL_REPLACE: case GL_MODULATE: case GL_ADD: case GL_ADD_SIGNED: case GL_INTERPOLATE: /* OK */ break; case GL_SUBTRACT: if (!ctx->Extensions.ARB_texture_env_combine) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } break; case GL_MODULATE_ADD_ATI: case GL_MODULATE_SIGNED_ADD_ATI: case GL_MODULATE_SUBTRACT_ATI: if (!ctx->Extensions.ATI_texture_env_combine3) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ModeA = mode; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_SOURCE0_RGB: case GL_SOURCE1_RGB: case GL_SOURCE2_RGB: if (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine) { const GLenum source = (GLenum) (GLint) *param; const GLuint s = pname - GL_SOURCE0_RGB; if (texUnit->Combine.SourceRGB[s] == source) return; if (source == GL_TEXTURE || source == GL_CONSTANT || source == GL_PRIMARY_COLOR || source == GL_PREVIOUS || (ctx->Extensions.ARB_texture_env_crossbar && source >= GL_TEXTURE0 && source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) || (ctx->Extensions.ATI_texture_env_combine3 && (source == GL_ZERO || source == GL_ONE))) { /* legal */ FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.SourceRGB[s] = source; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source); return; } } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_SOURCE0_ALPHA: case GL_SOURCE1_ALPHA: case GL_SOURCE2_ALPHA: if (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine) { const GLenum source = (GLenum) (GLint) *param; const GLuint s = pname - GL_SOURCE0_ALPHA; if (texUnit->Combine.SourceA[s] == source) return; if (source == GL_TEXTURE || source == GL_CONSTANT || source == GL_PRIMARY_COLOR || source == GL_PREVIOUS || (ctx->Extensions.ARB_texture_env_crossbar && source >= GL_TEXTURE0 && source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) || (ctx->Extensions.ATI_texture_env_combine3 && (source == GL_ZERO || source == GL_ONE))) { /* legal */ FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.SourceA[s] = source; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source); return; } } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_OPERAND0_RGB: case GL_OPERAND1_RGB: if (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine) { const GLenum operand = (GLenum) (GLint) *param; const GLuint s = pname - GL_OPERAND0_RGB; if (texUnit->Combine.OperandRGB[s] == operand) return; switch (operand) { case GL_SRC_COLOR: case GL_ONE_MINUS_SRC_COLOR: case GL_SRC_ALPHA: case GL_ONE_MINUS_SRC_ALPHA: FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.OperandRGB[s] = operand; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); return; } } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_OPERAND0_ALPHA: case GL_OPERAND1_ALPHA: if (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine) { const GLenum operand = (GLenum) (GLint) *param; if (texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] == operand) return; switch (operand) { case GL_SRC_ALPHA: case GL_ONE_MINUS_SRC_ALPHA: FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] = operand; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); return; } } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_OPERAND2_RGB: if (ctx->Extensions.ARB_texture_env_combine) { const GLenum operand = (GLenum) (GLint) *param; if (texUnit->Combine.OperandRGB[2] == operand) return; switch (operand) { case GL_SRC_COLOR: /* ARB combine only */ case GL_ONE_MINUS_SRC_COLOR: /* ARB combine only */ case GL_SRC_ALPHA: case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */ FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.OperandRGB[2] = operand; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); return; } } else if (ctx->Extensions.EXT_texture_env_combine) { const GLenum operand = (GLenum) (GLint) *param; if (texUnit->Combine.OperandRGB[2] == operand) return; /* operand must be GL_SRC_ALPHA which is the initial value - thus don't need to actually compare the operand to the possible value */ else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); return; } } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_OPERAND2_ALPHA: if (ctx->Extensions.ARB_texture_env_combine) { const GLenum operand = (GLenum) (GLint) *param; if (texUnit->Combine.OperandA[2] == operand) return; switch (operand) { case GL_SRC_ALPHA: case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */ FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.OperandA[2] = operand; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); return; } } else if (ctx->Extensions.EXT_texture_env_combine) { const GLenum operand = (GLenum) (GLint) *param; if (texUnit->Combine.OperandA[2] == operand) return; /* operand must be GL_SRC_ALPHA which is the initial value - thus don't need to actually compare the operand to the possible value */ else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); return; } } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_RGB_SCALE: if (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine) { GLuint newshift; if (*param == 1.0) { newshift = 0; } else if (*param == 2.0) { newshift = 1; } else if (*param == 4.0) { newshift = 2; } else { _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" ); return; } if (texUnit->Combine.ScaleShiftRGB == newshift) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ScaleShiftRGB = newshift; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; case GL_ALPHA_SCALE: if (ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine) { GLuint newshift; if (*param == 1.0) { newshift = 0; } else if (*param == 2.0) { newshift = 1; } else if (*param == 4.0) { newshift = 2; } else { _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(GL_ALPHA_SCALE not 1, 2 or 4)" ); return; } if (texUnit->Combine.ScaleShiftA == newshift) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ScaleShiftA = newshift; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } break; default: _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); return; } } else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { /* GL_EXT_texture_lod_bias */ if (!ctx->Extensions.EXT_texture_lod_bias) { _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target ); return; } if (pname == GL_TEXTURE_LOD_BIAS_EXT) { if (texUnit->LodBias == param[0]) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->LodBias = param[0]; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } } else if (target == GL_POINT_SPRITE_NV) { /* 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; } if (pname == GL_COORD_REPLACE_NV) { const GLenum value = (GLenum) param[0]; if (value == GL_TRUE || value == GL_FALSE) { /* It's kind of weird to set point state via glTexEnv, * but that's what the spec calls for. */ const GLboolean state = (GLboolean) value; if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state) return; FLUSH_VERTICES(ctx, _NEW_POINT); ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state; } else { _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value); return; } } else { _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); return; } } else { _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target ); return; } if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", _mesa_lookup_enum_by_nr(target), _mesa_lookup_enum_by_nr(pname), *param, _mesa_lookup_enum_by_nr((GLenum) (GLint) *param)); /* Tell device driver about the new texture environment */ if (ctx->Driver.TexEnv) { (*ctx->Driver.TexEnv)( ctx, target, pname, param ); } }
void GLAPIENTRY _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) { GLuint maxUnit; GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit; ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)"); return; } texUnit = _mesa_get_current_tex_unit(ctx); if (target == GL_TEXTURE_ENV) { switch (pname) { case GL_TEXTURE_ENV_MODE: set_env_mode(ctx, texUnit, (GLenum) (GLint) param[0]); break; case GL_TEXTURE_ENV_COLOR: set_env_color(ctx, texUnit, param); break; case GL_COMBINE_RGB: case GL_COMBINE_ALPHA: set_combiner_mode(ctx, texUnit, pname, (GLenum) (GLint) param[0]); break; case GL_SOURCE0_RGB: case GL_SOURCE1_RGB: case GL_SOURCE2_RGB: case GL_SOURCE3_RGB_NV: case GL_SOURCE0_ALPHA: case GL_SOURCE1_ALPHA: case GL_SOURCE2_ALPHA: case GL_SOURCE3_ALPHA_NV: set_combiner_source(ctx, texUnit, pname, (GLenum) (GLint) param[0]); break; case GL_OPERAND0_RGB: case GL_OPERAND1_RGB: case GL_OPERAND2_RGB: case GL_OPERAND3_RGB_NV: case GL_OPERAND0_ALPHA: case GL_OPERAND1_ALPHA: case GL_OPERAND2_ALPHA: case GL_OPERAND3_ALPHA_NV: set_combiner_operand(ctx, texUnit, pname, (GLenum) (GLint) param[0]); break; case GL_RGB_SCALE: case GL_ALPHA_SCALE: set_combiner_scale(ctx, texUnit, pname, param[0]); break; case GL_BUMP_TARGET_ATI: if (!ctx->Extensions.ATI_envmap_bumpmap) { _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); return; } if (((GLenum) (GLint) param[0] < GL_TEXTURE0) || ((GLenum) (GLint) param[0] > GL_TEXTURE31)) { /* spec doesn't say this but it seems logical */ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]); return; } if (!((1 << ((GLenum) (GLint) param[0] - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) { _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]); return; } else { FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->BumpTarget = (GLenum) (GLint) param[0]; } break; default: _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); return; } } else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { /* GL_EXT_texture_lod_bias */ if (!ctx->Extensions.EXT_texture_lod_bias) { _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target ); return; } if (pname == GL_TEXTURE_LOD_BIAS_EXT) { if (texUnit->LodBias == param[0]) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->LodBias = param[0]; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } } else if (target == GL_POINT_SPRITE_NV) { /* 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; } if (pname == GL_COORD_REPLACE_NV) { const GLenum value = (GLenum) param[0]; if (value == GL_TRUE || value == GL_FALSE) { /* It's kind of weird to set point state via glTexEnv, * but that's what the spec calls for. */ const GLboolean state = (GLboolean) value; if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state) return; FLUSH_VERTICES(ctx, _NEW_POINT); ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state; } else { _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value); return; } } else { _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); return; } } else { _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target ); return; } if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", _mesa_lookup_enum_by_nr(target), _mesa_lookup_enum_by_nr(pname), *param, _mesa_lookup_enum_by_nr((GLenum) (GLint) *param)); /* Tell device driver about the new texture environment */ if (ctx->Driver.TexEnv) { (*ctx->Driver.TexEnv)( ctx, target, pname, param ); } }
/** Set an RGB or A combiner operand term */ static void set_combiner_operand(GLcontext *ctx, struct gl_texture_unit *texUnit, GLenum pname, GLenum param) { GLuint term; GLboolean alpha, legal; if (!ctx->Extensions.EXT_texture_env_combine && !ctx->Extensions.ARB_texture_env_combine) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)"); return; } /* The enums were given sequential values for a reason. */ switch (pname) { case GL_OPERAND0_RGB: case GL_OPERAND1_RGB: case GL_OPERAND2_RGB: case GL_OPERAND3_RGB_NV: term = pname - GL_OPERAND0_RGB; alpha = GL_FALSE; break; case GL_OPERAND0_ALPHA: case GL_OPERAND1_ALPHA: case GL_OPERAND2_ALPHA: case GL_OPERAND3_ALPHA_NV: term = pname - GL_OPERAND0_ALPHA; alpha = GL_TRUE; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } if ((term == 3) && !ctx->Extensions.NV_texture_env_combine4) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } assert(term < MAX_COMBINER_TERMS); /* * Error-check param (the source operand) */ switch (param) { case GL_SRC_COLOR: case GL_ONE_MINUS_SRC_COLOR: /* The color input can only be used with GL_OPERAND[01]_RGB in the EXT * version. In the ARB and NV versions they can be used for any RGB * operand. */ legal = !alpha && ((term < 2) || ctx->Extensions.ARB_texture_env_combine || ctx->Extensions.NV_texture_env_combine4); break; case GL_ONE_MINUS_SRC_ALPHA: /* GL_ONE_MINUS_SRC_ALPHA can only be used with * GL_OPERAND[01]_(RGB|ALPHA) in the EXT version. In the ARB and NV * versions it can be used for any operand. */ legal = (term < 2) || ctx->Extensions.ARB_texture_env_combine || ctx->Extensions.NV_texture_env_combine4; break; case GL_SRC_ALPHA: legal = GL_TRUE; break; default: legal = GL_FALSE; } if (!legal) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param); return; } FLUSH_VERTICES(ctx, _NEW_TEXTURE); if (alpha) texUnit->Combine.OperandA[term] = param; else texUnit->Combine.OperandRGB[term] = param; }
/** Set an RGB or A combiner source term */ static void set_combiner_source(GLcontext *ctx, struct gl_texture_unit *texUnit, GLenum pname, GLenum param) { GLuint term; GLboolean alpha, legal; if (!ctx->Extensions.EXT_texture_env_combine && !ctx->Extensions.ARB_texture_env_combine) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)"); return; } /* * Translate pname to (term, alpha). * * The enums were given sequential values for a reason. */ switch (pname) { case GL_SOURCE0_RGB: case GL_SOURCE1_RGB: case GL_SOURCE2_RGB: case GL_SOURCE3_RGB_NV: term = pname - GL_SOURCE0_RGB; alpha = GL_FALSE; break; case GL_SOURCE0_ALPHA: case GL_SOURCE1_ALPHA: case GL_SOURCE2_ALPHA: case GL_SOURCE3_ALPHA_NV: term = pname - GL_SOURCE0_ALPHA; alpha = GL_TRUE; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } if ((term == 3) && !ctx->Extensions.NV_texture_env_combine4) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } assert(term < MAX_COMBINER_TERMS); /* * Error-check param (the source term) */ switch (param) { case GL_TEXTURE: case GL_CONSTANT: case GL_PRIMARY_COLOR: case GL_PREVIOUS: legal = GL_TRUE; break; case GL_TEXTURE0: case GL_TEXTURE1: case GL_TEXTURE2: case GL_TEXTURE3: case GL_TEXTURE4: case GL_TEXTURE5: case GL_TEXTURE6: case GL_TEXTURE7: legal = (ctx->Extensions.ARB_texture_env_crossbar && param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits); break; case GL_ZERO: legal = (ctx->Extensions.ATI_texture_env_combine3 || ctx->Extensions.NV_texture_env_combine4); break; case GL_ONE: legal = ctx->Extensions.ATI_texture_env_combine3; break; default: legal = GL_FALSE; } if (!legal) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param); return; } FLUSH_VERTICES(ctx, _NEW_TEXTURE); if (alpha) texUnit->Combine.SourceA[term] = param; else texUnit->Combine.SourceRGB[term] = param; }
/** Set an RGB or A combiner mode/function */ static void set_combiner_mode(GLcontext *ctx, struct gl_texture_unit *texUnit, GLenum pname, GLenum mode) { GLboolean legal; if (!ctx->Extensions.EXT_texture_env_combine && !ctx->Extensions.ARB_texture_env_combine) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)"); return; } switch (mode) { case GL_REPLACE: case GL_MODULATE: case GL_ADD: case GL_ADD_SIGNED: case GL_INTERPOLATE: legal = GL_TRUE; break; case GL_SUBTRACT: legal = ctx->Extensions.ARB_texture_env_combine; break; case GL_DOT3_RGB_EXT: case GL_DOT3_RGBA_EXT: legal = (ctx->Extensions.EXT_texture_env_dot3 && pname == GL_COMBINE_RGB); break; case GL_DOT3_RGB: case GL_DOT3_RGBA: legal = (ctx->Extensions.ARB_texture_env_dot3 && pname == GL_COMBINE_RGB); break; case GL_MODULATE_ADD_ATI: case GL_MODULATE_SIGNED_ADD_ATI: case GL_MODULATE_SUBTRACT_ATI: legal = ctx->Extensions.ATI_texture_env_combine3; break; case GL_BUMP_ENVMAP_ATI: legal = (ctx->Extensions.ATI_envmap_bumpmap && pname == GL_COMBINE_RGB); break; default: legal = GL_FALSE; } if (!legal) { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); return; } switch (pname) { case GL_COMBINE_RGB: if (texUnit->Combine.ModeRGB == mode) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ModeRGB = mode; break; case GL_COMBINE_ALPHA: if (texUnit->Combine.ModeA == mode) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->Combine.ModeA = mode; break; default: TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); } }
void glTexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) { const GLint iparam0 = (GLint) param[0]; struct gl_texture_unit *texUnit; GLuint maxUnit; GET_CURRENT_CONTEXT(ctx); maxUnit = ctx->Const.MaxCombinedTextureImageUnits; // maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) // ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)"); return; } texUnit = _mesa_get_current_tex_unit(ctx); if (target == GL_TEXTURE_ENV) { switch (pname) { case GL_TEXTURE_ENV_MODE: set_env_mode(ctx, texUnit, (GLenum) iparam0); break; case GL_TEXTURE_ENV_COLOR: set_env_color(ctx, texUnit, param); break; case GL_COMBINE_RGB: case GL_COMBINE_ALPHA: set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0); break; case GL_SOURCE0_RGB: case GL_SOURCE1_RGB: case GL_SOURCE2_RGB: // case GL_SOURCE3_RGB_NV: case GL_SOURCE0_ALPHA: case GL_SOURCE1_ALPHA: case GL_SOURCE2_ALPHA: // case GL_SOURCE3_ALPHA_NV: set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0); break; case GL_OPERAND0_RGB: case GL_OPERAND1_RGB: case GL_OPERAND2_RGB: // case GL_OPERAND3_RGB_NV: case GL_OPERAND0_ALPHA: case GL_OPERAND1_ALPHA: case GL_OPERAND2_ALPHA: // case GL_OPERAND3_ALPHA_NV: set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0); break; case GL_RGB_SCALE: case GL_ALPHA_SCALE: set_combiner_scale(ctx, texUnit, pname, param[0]); break; default: _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); return; } } else if (target == GL_TEXTURE_FILTER_CONTROL) { if (pname == GL_TEXTURE_LOD_BIAS) { if (texUnit->LodBias == param[0]) return; FLUSH_VERTICES(ctx, _NEW_TEXTURE); texUnit->LodBias = param[0]; } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); return; } } // else if (target == GL_POINT_SPRITE_NV) { // /* 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; // } // if (pname == GL_COORD_REPLACE_NV) { // if (iparam0 == GL_TRUE || iparam0 == GL_FALSE) { // /* It's kind of weird to set point state via glTexEnv, // * but that's what the spec calls for. // */ // const GLboolean state = (GLboolean) iparam0; // if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state) // return; // FLUSH_VERTICES(ctx, _NEW_POINT); // ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state; // } // else { // _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0); // return; // } // } // else { // _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); // return; // } // } else { _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)", _mesa_lookup_enum_by_nr(target)); return; } if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", _mesa_lookup_enum_by_nr(target), _mesa_lookup_enum_by_nr(pname), *param, _mesa_lookup_enum_by_nr((GLenum) iparam0)); /* Tell device driver about the new texture environment */ if (ctx->Driver.TexEnv) { (*ctx->Driver.TexEnv)( ctx, target, pname, param ); } }