1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg/** 27848b8605Smrg * \file texenv.c 28848b8605Smrg * 29848b8605Smrg * glTexEnv-related functions 30848b8605Smrg */ 31848b8605Smrg 32848b8605Smrg 33848b8605Smrg#include "main/glheader.h" 34848b8605Smrg#include "main/context.h" 35848b8605Smrg#include "main/blend.h" 36848b8605Smrg#include "main/enums.h" 37848b8605Smrg#include "main/macros.h" 38848b8605Smrg#include "main/mtypes.h" 39848b8605Smrg#include "main/state.h" 40848b8605Smrg#include "main/texenv.h" 41848b8605Smrg#include "main/texstate.h" 42848b8605Smrg 43848b8605Smrg 44848b8605Smrg#define TE_ERROR(errCode, msg, value) \ 45b8e80941Smrg _mesa_error(ctx, errCode, msg, _mesa_enum_to_string(value)); 46848b8605Smrg 47848b8605Smrg 48848b8605Smrg/** Set texture env mode */ 49848b8605Smrgstatic void 50848b8605Smrgset_env_mode(struct gl_context *ctx, 51b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit, 52848b8605Smrg GLenum mode) 53848b8605Smrg{ 54848b8605Smrg GLboolean legal; 55848b8605Smrg 56848b8605Smrg if (texUnit->EnvMode == mode) 57848b8605Smrg return; 58848b8605Smrg 59848b8605Smrg switch (mode) { 60848b8605Smrg case GL_MODULATE: 61848b8605Smrg case GL_BLEND: 62848b8605Smrg case GL_DECAL: 63848b8605Smrg case GL_REPLACE: 64848b8605Smrg case GL_ADD: 65848b8605Smrg case GL_COMBINE: 66848b8605Smrg legal = GL_TRUE; 67848b8605Smrg break; 68848b8605Smrg case GL_REPLACE_EXT: 69848b8605Smrg mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */ 70848b8605Smrg legal = GL_TRUE; 71848b8605Smrg break; 72848b8605Smrg case GL_COMBINE4_NV: 73848b8605Smrg legal = ctx->Extensions.NV_texture_env_combine4; 74848b8605Smrg break; 75848b8605Smrg default: 76848b8605Smrg legal = GL_FALSE; 77848b8605Smrg } 78848b8605Smrg 79848b8605Smrg if (legal) { 80b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 81848b8605Smrg texUnit->EnvMode = mode; 82848b8605Smrg } 83848b8605Smrg else { 84848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); 85848b8605Smrg } 86848b8605Smrg} 87848b8605Smrg 88848b8605Smrg 89848b8605Smrgstatic void 90848b8605Smrgset_env_color(struct gl_context *ctx, 91b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit, 92848b8605Smrg const GLfloat *color) 93848b8605Smrg{ 94848b8605Smrg if (TEST_EQ_4V(color, texUnit->EnvColorUnclamped)) 95848b8605Smrg return; 96b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 97848b8605Smrg COPY_4FV(texUnit->EnvColorUnclamped, color); 98848b8605Smrg texUnit->EnvColor[0] = CLAMP(color[0], 0.0F, 1.0F); 99848b8605Smrg texUnit->EnvColor[1] = CLAMP(color[1], 0.0F, 1.0F); 100848b8605Smrg texUnit->EnvColor[2] = CLAMP(color[2], 0.0F, 1.0F); 101848b8605Smrg texUnit->EnvColor[3] = CLAMP(color[3], 0.0F, 1.0F); 102848b8605Smrg} 103848b8605Smrg 104848b8605Smrg 105848b8605Smrg/** Set an RGB or A combiner mode/function */ 106b8e80941Smrgstatic bool 107848b8605Smrgset_combiner_mode(struct gl_context *ctx, 108b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit, 109848b8605Smrg GLenum pname, GLenum mode) 110848b8605Smrg{ 111848b8605Smrg GLboolean legal; 112848b8605Smrg 113848b8605Smrg switch (mode) { 114848b8605Smrg case GL_REPLACE: 115848b8605Smrg case GL_MODULATE: 116848b8605Smrg case GL_ADD: 117848b8605Smrg case GL_ADD_SIGNED: 118848b8605Smrg case GL_INTERPOLATE: 119848b8605Smrg legal = GL_TRUE; 120848b8605Smrg break; 121848b8605Smrg case GL_SUBTRACT: 122848b8605Smrg legal = ctx->Extensions.ARB_texture_env_combine; 123848b8605Smrg break; 124848b8605Smrg case GL_DOT3_RGB_EXT: 125848b8605Smrg case GL_DOT3_RGBA_EXT: 126848b8605Smrg legal = (ctx->API == API_OPENGL_COMPAT && 127848b8605Smrg ctx->Extensions.EXT_texture_env_dot3 && 128848b8605Smrg pname == GL_COMBINE_RGB); 129848b8605Smrg break; 130848b8605Smrg case GL_DOT3_RGB: 131848b8605Smrg case GL_DOT3_RGBA: 132848b8605Smrg legal = (ctx->Extensions.ARB_texture_env_dot3 && 133848b8605Smrg pname == GL_COMBINE_RGB); 134848b8605Smrg break; 135848b8605Smrg case GL_MODULATE_ADD_ATI: 136848b8605Smrg case GL_MODULATE_SIGNED_ADD_ATI: 137848b8605Smrg case GL_MODULATE_SUBTRACT_ATI: 138848b8605Smrg legal = (ctx->API == API_OPENGL_COMPAT && 139848b8605Smrg ctx->Extensions.ATI_texture_env_combine3); 140848b8605Smrg break; 141848b8605Smrg default: 142848b8605Smrg legal = GL_FALSE; 143848b8605Smrg } 144848b8605Smrg 145848b8605Smrg if (!legal) { 146848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); 147b8e80941Smrg return false; 148848b8605Smrg } 149848b8605Smrg 150848b8605Smrg switch (pname) { 151848b8605Smrg case GL_COMBINE_RGB: 152848b8605Smrg if (texUnit->Combine.ModeRGB == mode) 153b8e80941Smrg return true; 154b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 155848b8605Smrg texUnit->Combine.ModeRGB = mode; 156848b8605Smrg break; 157848b8605Smrg 158848b8605Smrg case GL_COMBINE_ALPHA: 159848b8605Smrg if (texUnit->Combine.ModeA == mode) 160b8e80941Smrg return true; 161b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 162848b8605Smrg texUnit->Combine.ModeA = mode; 163848b8605Smrg break; 164848b8605Smrg default: 165848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 166b8e80941Smrg return false; 167848b8605Smrg } 168b8e80941Smrg 169b8e80941Smrg return true; 170848b8605Smrg} 171848b8605Smrg 172848b8605Smrg 173848b8605Smrg 174848b8605Smrg/** Set an RGB or A combiner source term */ 175b8e80941Smrgstatic bool 176848b8605Smrgset_combiner_source(struct gl_context *ctx, 177b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit, 178848b8605Smrg GLenum pname, GLenum param) 179848b8605Smrg{ 180848b8605Smrg GLuint term; 181848b8605Smrg GLboolean alpha, legal; 182848b8605Smrg 183848b8605Smrg /* 184848b8605Smrg * Translate pname to (term, alpha). 185848b8605Smrg * 186848b8605Smrg * The enums were given sequential values for a reason. 187848b8605Smrg */ 188848b8605Smrg switch (pname) { 189848b8605Smrg case GL_SOURCE0_RGB: 190848b8605Smrg case GL_SOURCE1_RGB: 191848b8605Smrg case GL_SOURCE2_RGB: 192848b8605Smrg case GL_SOURCE3_RGB_NV: 193848b8605Smrg term = pname - GL_SOURCE0_RGB; 194848b8605Smrg alpha = GL_FALSE; 195848b8605Smrg break; 196848b8605Smrg case GL_SOURCE0_ALPHA: 197848b8605Smrg case GL_SOURCE1_ALPHA: 198848b8605Smrg case GL_SOURCE2_ALPHA: 199848b8605Smrg case GL_SOURCE3_ALPHA_NV: 200848b8605Smrg term = pname - GL_SOURCE0_ALPHA; 201848b8605Smrg alpha = GL_TRUE; 202848b8605Smrg break; 203848b8605Smrg default: 204848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 205b8e80941Smrg return false; 206848b8605Smrg } 207848b8605Smrg 208848b8605Smrg if ((term == 3) && (ctx->API != API_OPENGL_COMPAT 209848b8605Smrg || !ctx->Extensions.NV_texture_env_combine4)) { 210848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 211b8e80941Smrg return false; 212848b8605Smrg } 213848b8605Smrg 214848b8605Smrg assert(term < MAX_COMBINER_TERMS); 215848b8605Smrg 216848b8605Smrg /* 217848b8605Smrg * Error-check param (the source term) 218848b8605Smrg */ 219848b8605Smrg switch (param) { 220848b8605Smrg case GL_TEXTURE: 221848b8605Smrg case GL_CONSTANT: 222848b8605Smrg case GL_PRIMARY_COLOR: 223848b8605Smrg case GL_PREVIOUS: 224848b8605Smrg legal = GL_TRUE; 225848b8605Smrg break; 226848b8605Smrg case GL_TEXTURE0: 227848b8605Smrg case GL_TEXTURE1: 228848b8605Smrg case GL_TEXTURE2: 229848b8605Smrg case GL_TEXTURE3: 230848b8605Smrg case GL_TEXTURE4: 231848b8605Smrg case GL_TEXTURE5: 232848b8605Smrg case GL_TEXTURE6: 233848b8605Smrg case GL_TEXTURE7: 234848b8605Smrg legal = (ctx->Extensions.ARB_texture_env_crossbar && 235848b8605Smrg param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits); 236848b8605Smrg break; 237848b8605Smrg case GL_ZERO: 238848b8605Smrg legal = (ctx->API == API_OPENGL_COMPAT && 239848b8605Smrg (ctx->Extensions.ATI_texture_env_combine3 || 240848b8605Smrg ctx->Extensions.NV_texture_env_combine4)); 241848b8605Smrg break; 242848b8605Smrg case GL_ONE: 243848b8605Smrg legal = (ctx->API == API_OPENGL_COMPAT && 244848b8605Smrg ctx->Extensions.ATI_texture_env_combine3); 245848b8605Smrg break; 246848b8605Smrg default: 247848b8605Smrg legal = GL_FALSE; 248848b8605Smrg } 249848b8605Smrg 250848b8605Smrg if (!legal) { 251848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param); 252b8e80941Smrg return false; 253848b8605Smrg } 254848b8605Smrg 255b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 256848b8605Smrg 257848b8605Smrg if (alpha) 258848b8605Smrg texUnit->Combine.SourceA[term] = param; 259848b8605Smrg else 260848b8605Smrg texUnit->Combine.SourceRGB[term] = param; 261b8e80941Smrg 262b8e80941Smrg return true; 263848b8605Smrg} 264848b8605Smrg 265848b8605Smrg 266848b8605Smrg/** Set an RGB or A combiner operand term */ 267b8e80941Smrgstatic bool 268848b8605Smrgset_combiner_operand(struct gl_context *ctx, 269b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit, 270848b8605Smrg GLenum pname, GLenum param) 271848b8605Smrg{ 272848b8605Smrg GLuint term; 273848b8605Smrg GLboolean alpha, legal; 274848b8605Smrg 275848b8605Smrg /* The enums were given sequential values for a reason. 276848b8605Smrg */ 277848b8605Smrg switch (pname) { 278848b8605Smrg case GL_OPERAND0_RGB: 279848b8605Smrg case GL_OPERAND1_RGB: 280848b8605Smrg case GL_OPERAND2_RGB: 281848b8605Smrg case GL_OPERAND3_RGB_NV: 282848b8605Smrg term = pname - GL_OPERAND0_RGB; 283848b8605Smrg alpha = GL_FALSE; 284848b8605Smrg break; 285848b8605Smrg case GL_OPERAND0_ALPHA: 286848b8605Smrg case GL_OPERAND1_ALPHA: 287848b8605Smrg case GL_OPERAND2_ALPHA: 288848b8605Smrg case GL_OPERAND3_ALPHA_NV: 289848b8605Smrg term = pname - GL_OPERAND0_ALPHA; 290848b8605Smrg alpha = GL_TRUE; 291848b8605Smrg break; 292848b8605Smrg default: 293848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 294b8e80941Smrg return false; 295848b8605Smrg } 296848b8605Smrg 297848b8605Smrg if ((term == 3) && (ctx->API != API_OPENGL_COMPAT 298848b8605Smrg || !ctx->Extensions.NV_texture_env_combine4)) { 299848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 300b8e80941Smrg return false; 301848b8605Smrg } 302848b8605Smrg 303848b8605Smrg assert(term < MAX_COMBINER_TERMS); 304848b8605Smrg 305848b8605Smrg /* 306848b8605Smrg * Error-check param (the source operand) 307848b8605Smrg */ 308848b8605Smrg switch (param) { 309848b8605Smrg case GL_SRC_COLOR: 310848b8605Smrg case GL_ONE_MINUS_SRC_COLOR: 311848b8605Smrg /* The color input can only be used with GL_OPERAND[01]_RGB in the EXT 312848b8605Smrg * version. In the ARB and NV versions and OpenGL ES 1.x they can be 313848b8605Smrg * used for any RGB operand. 314848b8605Smrg */ 315848b8605Smrg legal = !alpha 316848b8605Smrg && ((term < 2) || ctx->Extensions.ARB_texture_env_combine 317848b8605Smrg || ctx->Extensions.NV_texture_env_combine4); 318848b8605Smrg break; 319848b8605Smrg case GL_ONE_MINUS_SRC_ALPHA: 320848b8605Smrg /* GL_ONE_MINUS_SRC_ALPHA can only be used with 321848b8605Smrg * GL_OPERAND[01]_(RGB|ALPHA) in the EXT version. In the ARB and NV 322848b8605Smrg * versions and OpenGL ES 1.x it can be used for any operand. 323848b8605Smrg */ 324848b8605Smrg legal = (term < 2) || ctx->Extensions.ARB_texture_env_combine 325848b8605Smrg || ctx->Extensions.NV_texture_env_combine4; 326848b8605Smrg break; 327848b8605Smrg case GL_SRC_ALPHA: 328848b8605Smrg legal = GL_TRUE; 329848b8605Smrg break; 330848b8605Smrg default: 331848b8605Smrg legal = GL_FALSE; 332848b8605Smrg } 333848b8605Smrg 334848b8605Smrg if (!legal) { 335848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param); 336b8e80941Smrg return false; 337848b8605Smrg } 338848b8605Smrg 339b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 340848b8605Smrg 341848b8605Smrg if (alpha) 342848b8605Smrg texUnit->Combine.OperandA[term] = param; 343848b8605Smrg else 344848b8605Smrg texUnit->Combine.OperandRGB[term] = param; 345b8e80941Smrg 346b8e80941Smrg return true; 347848b8605Smrg} 348848b8605Smrg 349848b8605Smrg 350b8e80941Smrgstatic bool 351848b8605Smrgset_combiner_scale(struct gl_context *ctx, 352b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit, 353848b8605Smrg GLenum pname, GLfloat scale) 354848b8605Smrg{ 355848b8605Smrg GLuint shift; 356848b8605Smrg 357848b8605Smrg if (scale == 1.0F) { 358848b8605Smrg shift = 0; 359848b8605Smrg } 360848b8605Smrg else if (scale == 2.0F) { 361848b8605Smrg shift = 1; 362848b8605Smrg } 363848b8605Smrg else if (scale == 4.0F) { 364848b8605Smrg shift = 2; 365848b8605Smrg } 366848b8605Smrg else { 367848b8605Smrg _mesa_error( ctx, GL_INVALID_VALUE, 368848b8605Smrg "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" ); 369b8e80941Smrg return false; 370848b8605Smrg } 371848b8605Smrg 372848b8605Smrg switch (pname) { 373848b8605Smrg case GL_RGB_SCALE: 374848b8605Smrg if (texUnit->Combine.ScaleShiftRGB == shift) 375b8e80941Smrg return true; 376b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 377848b8605Smrg texUnit->Combine.ScaleShiftRGB = shift; 378848b8605Smrg break; 379848b8605Smrg case GL_ALPHA_SCALE: 380848b8605Smrg if (texUnit->Combine.ScaleShiftA == shift) 381b8e80941Smrg return true; 382b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 383848b8605Smrg texUnit->Combine.ScaleShiftA = shift; 384848b8605Smrg break; 385848b8605Smrg default: 386848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 387b8e80941Smrg return false; 388848b8605Smrg } 389b8e80941Smrg 390b8e80941Smrg return true; 391848b8605Smrg} 392848b8605Smrg 393848b8605Smrg 394848b8605Smrg 395848b8605Smrgvoid GLAPIENTRY 396848b8605Smrg_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) 397848b8605Smrg{ 398848b8605Smrg const GLint iparam0 = (GLint) param[0]; 399848b8605Smrg GLuint maxUnit; 400848b8605Smrg GET_CURRENT_CONTEXT(ctx); 401848b8605Smrg 402848b8605Smrg maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 403848b8605Smrg ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 404848b8605Smrg if (ctx->Texture.CurrentUnit >= maxUnit) { 405848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)"); 406848b8605Smrg return; 407848b8605Smrg } 408848b8605Smrg 409848b8605Smrg if (target == GL_TEXTURE_ENV) { 410b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit = 411b8e80941Smrg _mesa_get_current_fixedfunc_tex_unit(ctx); 412b8e80941Smrg 413b8e80941Smrg /* The GL spec says that we should report an error if the unit is greater 414b8e80941Smrg * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 415b8e80941Smrg * fixed-function units are usable. This is probably a spec bug. 416b8e80941Smrg * Ignore glTexEnv(GL_TEXTURE_ENV) calls for non-fixed-func units, 417b8e80941Smrg * because we don't want to process calls that have no effect. 418b8e80941Smrg */ 419b8e80941Smrg if (!texUnit) 420b8e80941Smrg return; 421b8e80941Smrg 422848b8605Smrg switch (pname) { 423848b8605Smrg case GL_TEXTURE_ENV_MODE: 424848b8605Smrg set_env_mode(ctx, texUnit, (GLenum) iparam0); 425848b8605Smrg break; 426848b8605Smrg case GL_TEXTURE_ENV_COLOR: 427848b8605Smrg set_env_color(ctx, texUnit, param); 428848b8605Smrg break; 429848b8605Smrg case GL_COMBINE_RGB: 430848b8605Smrg case GL_COMBINE_ALPHA: 431b8e80941Smrg if (!set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0)) 432b8e80941Smrg return; 433848b8605Smrg break; 434848b8605Smrg case GL_SOURCE0_RGB: 435848b8605Smrg case GL_SOURCE1_RGB: 436848b8605Smrg case GL_SOURCE2_RGB: 437848b8605Smrg case GL_SOURCE3_RGB_NV: 438848b8605Smrg case GL_SOURCE0_ALPHA: 439848b8605Smrg case GL_SOURCE1_ALPHA: 440848b8605Smrg case GL_SOURCE2_ALPHA: 441848b8605Smrg case GL_SOURCE3_ALPHA_NV: 442b8e80941Smrg if (!set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0)) 443b8e80941Smrg return; 444848b8605Smrg break; 445848b8605Smrg case GL_OPERAND0_RGB: 446848b8605Smrg case GL_OPERAND1_RGB: 447848b8605Smrg case GL_OPERAND2_RGB: 448848b8605Smrg case GL_OPERAND3_RGB_NV: 449848b8605Smrg case GL_OPERAND0_ALPHA: 450848b8605Smrg case GL_OPERAND1_ALPHA: 451848b8605Smrg case GL_OPERAND2_ALPHA: 452848b8605Smrg case GL_OPERAND3_ALPHA_NV: 453b8e80941Smrg if (!set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0)) 454b8e80941Smrg return; 455848b8605Smrg break; 456848b8605Smrg case GL_RGB_SCALE: 457848b8605Smrg case GL_ALPHA_SCALE: 458b8e80941Smrg if (!set_combiner_scale(ctx, texUnit, pname, param[0])) 459b8e80941Smrg return; 460848b8605Smrg break; 461848b8605Smrg default: 462848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); 463848b8605Smrg return; 464848b8605Smrg } 465848b8605Smrg } 466848b8605Smrg else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 467b8e80941Smrg struct gl_texture_unit *texUnit = 468b8e80941Smrg _mesa_get_current_tex_unit(ctx); 469b8e80941Smrg 470848b8605Smrg if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 471848b8605Smrg if (texUnit->LodBias == param[0]) 472848b8605Smrg return; 473b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT); 474848b8605Smrg texUnit->LodBias = param[0]; 475848b8605Smrg } 476848b8605Smrg else { 477848b8605Smrg TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 478848b8605Smrg return; 479848b8605Smrg } 480848b8605Smrg } 481848b8605Smrg else if (target == GL_POINT_SPRITE_NV) { 482848b8605Smrg /* GL_ARB_point_sprite / GL_NV_point_sprite */ 483848b8605Smrg if (!ctx->Extensions.NV_point_sprite 484848b8605Smrg && !ctx->Extensions.ARB_point_sprite) { 485848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target ); 486848b8605Smrg return; 487848b8605Smrg } 488848b8605Smrg if (pname == GL_COORD_REPLACE_NV) { 489b8e80941Smrg /* It's kind of weird to set point state via glTexEnv, 490b8e80941Smrg * but that's what the spec calls for. 491b8e80941Smrg */ 492b8e80941Smrg if (iparam0 == GL_TRUE) { 493b8e80941Smrg if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 494848b8605Smrg return; 495b8e80941Smrg ctx->Point.CoordReplace |= (1u << ctx->Texture.CurrentUnit); 496b8e80941Smrg } else if (iparam0 == GL_FALSE) { 497b8e80941Smrg if (~(ctx->Point.CoordReplace) & (1u << ctx->Texture.CurrentUnit)) 498b8e80941Smrg return; 499b8e80941Smrg ctx->Point.CoordReplace &= ~(1u << ctx->Texture.CurrentUnit); 500b8e80941Smrg } else { 501848b8605Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0); 502848b8605Smrg return; 503848b8605Smrg } 504b8e80941Smrg FLUSH_VERTICES(ctx, _NEW_POINT); 505848b8605Smrg } 506848b8605Smrg else { 507848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); 508848b8605Smrg return; 509848b8605Smrg } 510848b8605Smrg } 511848b8605Smrg else { 512848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)", 513b8e80941Smrg _mesa_enum_to_string(target)); 514848b8605Smrg return; 515848b8605Smrg } 516848b8605Smrg 517848b8605Smrg if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) 518848b8605Smrg _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", 519b8e80941Smrg _mesa_enum_to_string(target), 520b8e80941Smrg _mesa_enum_to_string(pname), 521848b8605Smrg *param, 522b8e80941Smrg _mesa_enum_to_string((GLenum) iparam0)); 523848b8605Smrg 524848b8605Smrg /* Tell device driver about the new texture environment */ 525848b8605Smrg if (ctx->Driver.TexEnv) { 526b8e80941Smrg ctx->Driver.TexEnv(ctx, target, pname, param); 527848b8605Smrg } 528848b8605Smrg} 529848b8605Smrg 530848b8605Smrg 531848b8605Smrgvoid GLAPIENTRY 532848b8605Smrg_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param ) 533848b8605Smrg{ 534848b8605Smrg GLfloat p[4]; 535848b8605Smrg p[0] = param; 536848b8605Smrg p[1] = p[2] = p[3] = 0.0; 537848b8605Smrg _mesa_TexEnvfv( target, pname, p ); 538848b8605Smrg} 539848b8605Smrg 540848b8605Smrg 541848b8605Smrg 542848b8605Smrgvoid GLAPIENTRY 543848b8605Smrg_mesa_TexEnvi( GLenum target, GLenum pname, GLint param ) 544848b8605Smrg{ 545848b8605Smrg GLfloat p[4]; 546848b8605Smrg p[0] = (GLfloat) param; 547848b8605Smrg p[1] = p[2] = p[3] = 0.0; 548848b8605Smrg _mesa_TexEnvfv( target, pname, p ); 549848b8605Smrg} 550848b8605Smrg 551848b8605Smrg 552848b8605Smrgvoid GLAPIENTRY 553848b8605Smrg_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param ) 554848b8605Smrg{ 555848b8605Smrg GLfloat p[4]; 556848b8605Smrg if (pname == GL_TEXTURE_ENV_COLOR) { 557848b8605Smrg p[0] = INT_TO_FLOAT( param[0] ); 558848b8605Smrg p[1] = INT_TO_FLOAT( param[1] ); 559848b8605Smrg p[2] = INT_TO_FLOAT( param[2] ); 560848b8605Smrg p[3] = INT_TO_FLOAT( param[3] ); 561848b8605Smrg } 562848b8605Smrg else { 563848b8605Smrg p[0] = (GLfloat) param[0]; 564848b8605Smrg p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */ 565848b8605Smrg } 566848b8605Smrg _mesa_TexEnvfv( target, pname, p ); 567848b8605Smrg} 568848b8605Smrg 569848b8605Smrg 570848b8605Smrg 571848b8605Smrg/** 572848b8605Smrg * Helper for glGetTexEnvi/f() 573848b8605Smrg * \return value of queried pname or -1 if error. 574848b8605Smrg */ 575848b8605Smrgstatic GLint 576b8e80941Smrgget_texenvi(struct gl_context *ctx, 577b8e80941Smrg const struct gl_fixedfunc_texture_unit *texUnit, 578848b8605Smrg GLenum pname) 579848b8605Smrg{ 580848b8605Smrg switch (pname) { 581848b8605Smrg case GL_TEXTURE_ENV_MODE: 582848b8605Smrg return texUnit->EnvMode; 583848b8605Smrg break; 584848b8605Smrg case GL_COMBINE_RGB: 585848b8605Smrg return texUnit->Combine.ModeRGB; 586848b8605Smrg case GL_COMBINE_ALPHA: 587848b8605Smrg return texUnit->Combine.ModeA; 588848b8605Smrg case GL_SOURCE0_RGB: 589848b8605Smrg case GL_SOURCE1_RGB: 590848b8605Smrg case GL_SOURCE2_RGB: { 591848b8605Smrg const unsigned rgb_idx = pname - GL_SOURCE0_RGB; 592848b8605Smrg return texUnit->Combine.SourceRGB[rgb_idx]; 593848b8605Smrg } 594848b8605Smrg case GL_SOURCE3_RGB_NV: 595848b8605Smrg if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 596848b8605Smrg return texUnit->Combine.SourceRGB[3]; 597848b8605Smrg } 598848b8605Smrg else { 599848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 600848b8605Smrg } 601848b8605Smrg break; 602848b8605Smrg case GL_SOURCE0_ALPHA: 603848b8605Smrg case GL_SOURCE1_ALPHA: 604848b8605Smrg case GL_SOURCE2_ALPHA: { 605848b8605Smrg const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA; 606848b8605Smrg return texUnit->Combine.SourceA[alpha_idx]; 607848b8605Smrg } 608848b8605Smrg case GL_SOURCE3_ALPHA_NV: 609848b8605Smrg if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 610848b8605Smrg return texUnit->Combine.SourceA[3]; 611848b8605Smrg } 612848b8605Smrg else { 613848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 614848b8605Smrg } 615848b8605Smrg break; 616848b8605Smrg case GL_OPERAND0_RGB: 617848b8605Smrg case GL_OPERAND1_RGB: 618848b8605Smrg case GL_OPERAND2_RGB: { 619848b8605Smrg const unsigned op_rgb = pname - GL_OPERAND0_RGB; 620848b8605Smrg return texUnit->Combine.OperandRGB[op_rgb]; 621848b8605Smrg } 622848b8605Smrg case GL_OPERAND3_RGB_NV: 623848b8605Smrg if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 624848b8605Smrg return texUnit->Combine.OperandRGB[3]; 625848b8605Smrg } 626848b8605Smrg else { 627848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 628848b8605Smrg } 629848b8605Smrg break; 630848b8605Smrg case GL_OPERAND0_ALPHA: 631848b8605Smrg case GL_OPERAND1_ALPHA: 632848b8605Smrg case GL_OPERAND2_ALPHA: { 633848b8605Smrg const unsigned op_alpha = pname - GL_OPERAND0_ALPHA; 634848b8605Smrg return texUnit->Combine.OperandA[op_alpha]; 635848b8605Smrg } 636848b8605Smrg case GL_OPERAND3_ALPHA_NV: 637848b8605Smrg if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 638848b8605Smrg return texUnit->Combine.OperandA[3]; 639848b8605Smrg } 640848b8605Smrg else { 641848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 642848b8605Smrg } 643848b8605Smrg break; 644848b8605Smrg case GL_RGB_SCALE: 645848b8605Smrg return 1 << texUnit->Combine.ScaleShiftRGB; 646848b8605Smrg case GL_ALPHA_SCALE: 647848b8605Smrg return 1 << texUnit->Combine.ScaleShiftA; 648848b8605Smrg default: 649848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 650848b8605Smrg break; 651848b8605Smrg } 652848b8605Smrg 653848b8605Smrg return -1; /* error */ 654848b8605Smrg} 655848b8605Smrg 656848b8605Smrg 657848b8605Smrg 658848b8605Smrgvoid GLAPIENTRY 659848b8605Smrg_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) 660848b8605Smrg{ 661848b8605Smrg GLuint maxUnit; 662848b8605Smrg GET_CURRENT_CONTEXT(ctx); 663848b8605Smrg 664848b8605Smrg maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 665848b8605Smrg ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 666848b8605Smrg if (ctx->Texture.CurrentUnit >= maxUnit) { 667848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)"); 668848b8605Smrg return; 669848b8605Smrg } 670848b8605Smrg 671848b8605Smrg if (target == GL_TEXTURE_ENV) { 672b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit = 673b8e80941Smrg _mesa_get_current_fixedfunc_tex_unit(ctx); 674b8e80941Smrg 675b8e80941Smrg /* The GL spec says that we should report an error if the unit is greater 676b8e80941Smrg * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 677b8e80941Smrg * fixed-function units are usable. This is probably a spec bug. 678b8e80941Smrg * Ignore calls for non-fixed-func units, because we don't process 679b8e80941Smrg * glTexEnv for them either. 680b8e80941Smrg */ 681b8e80941Smrg if (!texUnit) 682b8e80941Smrg return; 683b8e80941Smrg 684848b8605Smrg if (pname == GL_TEXTURE_ENV_COLOR) { 685848b8605Smrg if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) 686848b8605Smrg _mesa_update_state(ctx); 687b8e80941Smrg if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 688848b8605Smrg COPY_4FV( params, texUnit->EnvColor ); 689848b8605Smrg else 690848b8605Smrg COPY_4FV( params, texUnit->EnvColorUnclamped ); 691848b8605Smrg } 692848b8605Smrg else { 693848b8605Smrg GLint val = get_texenvi(ctx, texUnit, pname); 694848b8605Smrg if (val >= 0) { 695848b8605Smrg *params = (GLfloat) val; 696848b8605Smrg } 697848b8605Smrg } 698848b8605Smrg } 699848b8605Smrg else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 700b8e80941Smrg const struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 701b8e80941Smrg 702848b8605Smrg if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 703848b8605Smrg *params = texUnit->LodBias; 704848b8605Smrg } 705848b8605Smrg else { 706848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 707848b8605Smrg return; 708848b8605Smrg } 709848b8605Smrg } 710848b8605Smrg else if (target == GL_POINT_SPRITE_NV) { 711848b8605Smrg /* GL_ARB_point_sprite / GL_NV_point_sprite */ 712848b8605Smrg if (!ctx->Extensions.NV_point_sprite 713848b8605Smrg && !ctx->Extensions.ARB_point_sprite) { 714848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 715848b8605Smrg return; 716848b8605Smrg } 717848b8605Smrg if (pname == GL_COORD_REPLACE_NV) { 718b8e80941Smrg if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 719b8e80941Smrg *params = 1.0f; 720b8e80941Smrg else 721b8e80941Smrg *params = 0.0f; 722848b8605Smrg } 723848b8605Smrg else { 724848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 725848b8605Smrg return; 726848b8605Smrg } 727848b8605Smrg } 728848b8605Smrg else { 729848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 730848b8605Smrg return; 731848b8605Smrg } 732848b8605Smrg} 733848b8605Smrg 734848b8605Smrg 735848b8605Smrgvoid GLAPIENTRY 736848b8605Smrg_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) 737848b8605Smrg{ 738848b8605Smrg GLuint maxUnit; 739848b8605Smrg GET_CURRENT_CONTEXT(ctx); 740848b8605Smrg 741848b8605Smrg maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 742848b8605Smrg ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 743848b8605Smrg if (ctx->Texture.CurrentUnit >= maxUnit) { 744848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)"); 745848b8605Smrg return; 746848b8605Smrg } 747848b8605Smrg 748848b8605Smrg if (target == GL_TEXTURE_ENV) { 749b8e80941Smrg struct gl_fixedfunc_texture_unit *texUnit = 750b8e80941Smrg _mesa_get_current_fixedfunc_tex_unit(ctx); 751b8e80941Smrg 752b8e80941Smrg /* The GL spec says that we should report an error if the unit is greater 753b8e80941Smrg * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 754b8e80941Smrg * fixed-function units are usable. This is probably a spec bug. 755b8e80941Smrg * Ignore calls for non-fixed-func units, because we don't process 756b8e80941Smrg * glTexEnv for them either. 757b8e80941Smrg */ 758b8e80941Smrg if (!texUnit) 759b8e80941Smrg return; 760b8e80941Smrg 761848b8605Smrg if (pname == GL_TEXTURE_ENV_COLOR) { 762848b8605Smrg params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] ); 763848b8605Smrg params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] ); 764848b8605Smrg params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] ); 765848b8605Smrg params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] ); 766848b8605Smrg } 767848b8605Smrg else { 768848b8605Smrg GLint val = get_texenvi(ctx, texUnit, pname); 769848b8605Smrg if (val >= 0) { 770848b8605Smrg *params = val; 771848b8605Smrg } 772848b8605Smrg } 773848b8605Smrg } 774848b8605Smrg else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 775b8e80941Smrg const struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 776b8e80941Smrg 777848b8605Smrg if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 778848b8605Smrg *params = (GLint) texUnit->LodBias; 779848b8605Smrg } 780848b8605Smrg else { 781848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 782848b8605Smrg return; 783848b8605Smrg } 784848b8605Smrg } 785848b8605Smrg else if (target == GL_POINT_SPRITE_NV) { 786848b8605Smrg /* GL_ARB_point_sprite / GL_NV_point_sprite */ 787848b8605Smrg if (!ctx->Extensions.NV_point_sprite 788848b8605Smrg && !ctx->Extensions.ARB_point_sprite) { 789848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 790848b8605Smrg return; 791848b8605Smrg } 792848b8605Smrg if (pname == GL_COORD_REPLACE_NV) { 793b8e80941Smrg if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 794b8e80941Smrg *params = GL_TRUE; 795b8e80941Smrg else 796b8e80941Smrg *params = GL_FALSE; 797848b8605Smrg } 798848b8605Smrg else { 799848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 800848b8605Smrg return; 801848b8605Smrg } 802848b8605Smrg } 803848b8605Smrg else { 804848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 805848b8605Smrg return; 806848b8605Smrg } 807848b8605Smrg} 808848b8605Smrg 809