texenv.c revision 7ec681f3
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26/** 27 * \file texenv.c 28 * 29 * glTexEnv-related functions 30 */ 31 32 33#include "main/glheader.h" 34#include "main/context.h" 35#include "main/blend.h" 36#include "main/enums.h" 37#include "main/macros.h" 38#include "main/mtypes.h" 39#include "main/state.h" 40#include "main/texenv.h" 41#include "main/texstate.h" 42 43 44#define TE_ERROR(errCode, msg, value) \ 45 _mesa_error(ctx, errCode, msg, _mesa_enum_to_string(value)); 46 47 48/** Set texture env mode */ 49static void 50set_env_mode(struct gl_context *ctx, 51 struct gl_fixedfunc_texture_unit *texUnit, 52 GLenum mode) 53{ 54 GLboolean legal; 55 56 if (texUnit->EnvMode == mode) 57 return; 58 59 switch (mode) { 60 case GL_MODULATE: 61 case GL_BLEND: 62 case GL_DECAL: 63 case GL_REPLACE: 64 case GL_ADD: 65 case GL_COMBINE: 66 legal = GL_TRUE; 67 break; 68 case GL_REPLACE_EXT: 69 mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */ 70 legal = GL_TRUE; 71 break; 72 case GL_COMBINE4_NV: 73 legal = ctx->Extensions.NV_texture_env_combine4; 74 break; 75 default: 76 legal = GL_FALSE; 77 } 78 79 if (legal) { 80 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 81 texUnit->EnvMode = mode; 82 } 83 else { 84 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); 85 } 86} 87 88 89static void 90set_env_color(struct gl_context *ctx, 91 struct gl_fixedfunc_texture_unit *texUnit, 92 const GLfloat *color) 93{ 94 if (TEST_EQ_4V(color, texUnit->EnvColorUnclamped)) 95 return; 96 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 97 COPY_4FV(texUnit->EnvColorUnclamped, color); 98 texUnit->EnvColor[0] = CLAMP(color[0], 0.0F, 1.0F); 99 texUnit->EnvColor[1] = CLAMP(color[1], 0.0F, 1.0F); 100 texUnit->EnvColor[2] = CLAMP(color[2], 0.0F, 1.0F); 101 texUnit->EnvColor[3] = CLAMP(color[3], 0.0F, 1.0F); 102} 103 104 105/** Set an RGB or A combiner mode/function */ 106static bool 107set_combiner_mode(struct gl_context *ctx, 108 struct gl_fixedfunc_texture_unit *texUnit, 109 GLenum pname, GLenum mode) 110{ 111 GLboolean legal; 112 113 switch (mode) { 114 case GL_REPLACE: 115 case GL_MODULATE: 116 case GL_ADD: 117 case GL_ADD_SIGNED: 118 case GL_INTERPOLATE: 119 legal = GL_TRUE; 120 break; 121 case GL_SUBTRACT: 122 legal = ctx->Extensions.ARB_texture_env_combine; 123 break; 124 case GL_DOT3_RGB_EXT: 125 case GL_DOT3_RGBA_EXT: 126 legal = (ctx->API == API_OPENGL_COMPAT && 127 ctx->Extensions.EXT_texture_env_dot3 && 128 pname == GL_COMBINE_RGB); 129 break; 130 case GL_DOT3_RGB: 131 case GL_DOT3_RGBA: 132 legal = (ctx->Extensions.ARB_texture_env_dot3 && 133 pname == GL_COMBINE_RGB); 134 break; 135 case GL_MODULATE_ADD_ATI: 136 case GL_MODULATE_SIGNED_ADD_ATI: 137 case GL_MODULATE_SUBTRACT_ATI: 138 legal = (ctx->API == API_OPENGL_COMPAT && 139 ctx->Extensions.ATI_texture_env_combine3); 140 break; 141 default: 142 legal = GL_FALSE; 143 } 144 145 if (!legal) { 146 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); 147 return false; 148 } 149 150 switch (pname) { 151 case GL_COMBINE_RGB: 152 if (texUnit->Combine.ModeRGB == mode) 153 return true; 154 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 155 texUnit->Combine.ModeRGB = mode; 156 break; 157 158 case GL_COMBINE_ALPHA: 159 if (texUnit->Combine.ModeA == mode) 160 return true; 161 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 162 texUnit->Combine.ModeA = mode; 163 break; 164 default: 165 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 166 return false; 167 } 168 169 return true; 170} 171 172 173 174/** Set an RGB or A combiner source term */ 175static bool 176set_combiner_source(struct gl_context *ctx, 177 struct gl_fixedfunc_texture_unit *texUnit, 178 GLenum pname, GLenum param) 179{ 180 GLuint term; 181 GLboolean alpha, legal; 182 183 /* 184 * Translate pname to (term, alpha). 185 * 186 * The enums were given sequential values for a reason. 187 */ 188 switch (pname) { 189 case GL_SOURCE0_RGB: 190 case GL_SOURCE1_RGB: 191 case GL_SOURCE2_RGB: 192 case GL_SOURCE3_RGB_NV: 193 term = pname - GL_SOURCE0_RGB; 194 alpha = GL_FALSE; 195 break; 196 case GL_SOURCE0_ALPHA: 197 case GL_SOURCE1_ALPHA: 198 case GL_SOURCE2_ALPHA: 199 case GL_SOURCE3_ALPHA_NV: 200 term = pname - GL_SOURCE0_ALPHA; 201 alpha = GL_TRUE; 202 break; 203 default: 204 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 205 return false; 206 } 207 208 if ((term == 3) && (ctx->API != API_OPENGL_COMPAT 209 || !ctx->Extensions.NV_texture_env_combine4)) { 210 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 211 return false; 212 } 213 214 assert(term < MAX_COMBINER_TERMS); 215 216 /* 217 * Error-check param (the source term) 218 */ 219 switch (param) { 220 case GL_TEXTURE: 221 case GL_CONSTANT: 222 case GL_PRIMARY_COLOR: 223 case GL_PREVIOUS: 224 legal = GL_TRUE; 225 break; 226 case GL_TEXTURE0: 227 case GL_TEXTURE1: 228 case GL_TEXTURE2: 229 case GL_TEXTURE3: 230 case GL_TEXTURE4: 231 case GL_TEXTURE5: 232 case GL_TEXTURE6: 233 case GL_TEXTURE7: 234 legal = (ctx->Extensions.ARB_texture_env_crossbar && 235 param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits); 236 break; 237 case GL_ZERO: 238 legal = (ctx->API == API_OPENGL_COMPAT && 239 (ctx->Extensions.ATI_texture_env_combine3 || 240 ctx->Extensions.NV_texture_env_combine4)); 241 break; 242 case GL_ONE: 243 legal = (ctx->API == API_OPENGL_COMPAT && 244 ctx->Extensions.ATI_texture_env_combine3); 245 break; 246 default: 247 legal = GL_FALSE; 248 } 249 250 if (!legal) { 251 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param); 252 return false; 253 } 254 255 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 256 257 if (alpha) 258 texUnit->Combine.SourceA[term] = param; 259 else 260 texUnit->Combine.SourceRGB[term] = param; 261 262 return true; 263} 264 265 266/** Set an RGB or A combiner operand term */ 267static bool 268set_combiner_operand(struct gl_context *ctx, 269 struct gl_fixedfunc_texture_unit *texUnit, 270 GLenum pname, GLenum param) 271{ 272 GLuint term; 273 GLboolean alpha, legal; 274 275 /* The enums were given sequential values for a reason. 276 */ 277 switch (pname) { 278 case GL_OPERAND0_RGB: 279 case GL_OPERAND1_RGB: 280 case GL_OPERAND2_RGB: 281 case GL_OPERAND3_RGB_NV: 282 term = pname - GL_OPERAND0_RGB; 283 alpha = GL_FALSE; 284 break; 285 case GL_OPERAND0_ALPHA: 286 case GL_OPERAND1_ALPHA: 287 case GL_OPERAND2_ALPHA: 288 case GL_OPERAND3_ALPHA_NV: 289 term = pname - GL_OPERAND0_ALPHA; 290 alpha = GL_TRUE; 291 break; 292 default: 293 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 294 return false; 295 } 296 297 if ((term == 3) && (ctx->API != API_OPENGL_COMPAT 298 || !ctx->Extensions.NV_texture_env_combine4)) { 299 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 300 return false; 301 } 302 303 assert(term < MAX_COMBINER_TERMS); 304 305 /* 306 * Error-check param (the source operand) 307 */ 308 switch (param) { 309 case GL_SRC_COLOR: 310 case GL_ONE_MINUS_SRC_COLOR: 311 /* The color input can only be used with GL_OPERAND[01]_RGB in the EXT 312 * version. In the ARB and NV versions and OpenGL ES 1.x they can be 313 * used for any RGB operand. 314 */ 315 legal = !alpha 316 && ((term < 2) || ctx->Extensions.ARB_texture_env_combine 317 || ctx->Extensions.NV_texture_env_combine4); 318 break; 319 case GL_ONE_MINUS_SRC_ALPHA: 320 /* GL_ONE_MINUS_SRC_ALPHA can only be used with 321 * GL_OPERAND[01]_(RGB|ALPHA) in the EXT version. In the ARB and NV 322 * versions and OpenGL ES 1.x it can be used for any operand. 323 */ 324 legal = (term < 2) || ctx->Extensions.ARB_texture_env_combine 325 || ctx->Extensions.NV_texture_env_combine4; 326 break; 327 case GL_SRC_ALPHA: 328 legal = GL_TRUE; 329 break; 330 default: 331 legal = GL_FALSE; 332 } 333 334 if (!legal) { 335 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param); 336 return false; 337 } 338 339 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 340 341 if (alpha) 342 texUnit->Combine.OperandA[term] = param; 343 else 344 texUnit->Combine.OperandRGB[term] = param; 345 346 return true; 347} 348 349 350static bool 351set_combiner_scale(struct gl_context *ctx, 352 struct gl_fixedfunc_texture_unit *texUnit, 353 GLenum pname, GLfloat scale) 354{ 355 GLuint shift; 356 357 if (scale == 1.0F) { 358 shift = 0; 359 } 360 else if (scale == 2.0F) { 361 shift = 1; 362 } 363 else if (scale == 4.0F) { 364 shift = 2; 365 } 366 else { 367 _mesa_error( ctx, GL_INVALID_VALUE, 368 "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" ); 369 return false; 370 } 371 372 switch (pname) { 373 case GL_RGB_SCALE: 374 if (texUnit->Combine.ScaleShiftRGB == shift) 375 return true; 376 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 377 texUnit->Combine.ScaleShiftRGB = shift; 378 break; 379 case GL_ALPHA_SCALE: 380 if (texUnit->Combine.ScaleShiftA == shift) 381 return true; 382 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 383 texUnit->Combine.ScaleShiftA = shift; 384 break; 385 default: 386 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 387 return false; 388 } 389 390 return true; 391} 392 393 394static void 395_mesa_texenvfv_indexed( struct gl_context* ctx, GLuint texunit, GLenum target, 396 GLenum pname, const GLfloat *param ) 397{ 398 const GLint iparam0 = (GLint) param[0]; 399 GLuint maxUnit; 400 401 maxUnit = (target == GL_POINT_SPRITE && pname == GL_COORD_REPLACE) 402 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 403 if (texunit >= maxUnit) { 404 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(texunit=%d)", texunit); 405 return; 406 } 407 408 if (target == GL_TEXTURE_ENV) { 409 struct gl_fixedfunc_texture_unit *texUnit = 410 _mesa_get_fixedfunc_tex_unit(ctx, texunit); 411 412 /* The GL spec says that we should report an error if the unit is greater 413 * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 414 * fixed-function units are usable. This is probably a spec bug. 415 * Ignore glTexEnv(GL_TEXTURE_ENV) calls for non-fixed-func units, 416 * because we don't want to process calls that have no effect. 417 */ 418 if (!texUnit) 419 return; 420 421 switch (pname) { 422 case GL_TEXTURE_ENV_MODE: 423 set_env_mode(ctx, texUnit, (GLenum) iparam0); 424 break; 425 case GL_TEXTURE_ENV_COLOR: 426 set_env_color(ctx, texUnit, param); 427 break; 428 case GL_COMBINE_RGB: 429 case GL_COMBINE_ALPHA: 430 if (!set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0)) 431 return; 432 break; 433 case GL_SOURCE0_RGB: 434 case GL_SOURCE1_RGB: 435 case GL_SOURCE2_RGB: 436 case GL_SOURCE3_RGB_NV: 437 case GL_SOURCE0_ALPHA: 438 case GL_SOURCE1_ALPHA: 439 case GL_SOURCE2_ALPHA: 440 case GL_SOURCE3_ALPHA_NV: 441 if (!set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0)) 442 return; 443 break; 444 case GL_OPERAND0_RGB: 445 case GL_OPERAND1_RGB: 446 case GL_OPERAND2_RGB: 447 case GL_OPERAND3_RGB_NV: 448 case GL_OPERAND0_ALPHA: 449 case GL_OPERAND1_ALPHA: 450 case GL_OPERAND2_ALPHA: 451 case GL_OPERAND3_ALPHA_NV: 452 if (!set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0)) 453 return; 454 break; 455 case GL_RGB_SCALE: 456 case GL_ALPHA_SCALE: 457 if (!set_combiner_scale(ctx, texUnit, pname, param[0])) 458 return; 459 break; 460 default: 461 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); 462 return; 463 } 464 } 465 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 466 struct gl_texture_unit *texUnit = 467 _mesa_get_tex_unit(ctx, texunit); 468 469 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 470 if (texUnit->LodBias == param[0]) 471 return; 472 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT); 473 texUnit->LodBias = param[0]; 474 texUnit->LodBiasQuantized = util_quantize_lod_bias(param[0]); 475 } 476 else { 477 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 478 return; 479 } 480 } 481 else if (target == GL_POINT_SPRITE) { 482 /* GL_ARB_point_sprite */ 483 if (!ctx->Extensions.ARB_point_sprite) { 484 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target ); 485 return; 486 } 487 if (pname == GL_COORD_REPLACE) { 488 /* It's kind of weird to set point state via glTexEnv, 489 * but that's what the spec calls for. 490 */ 491 if (iparam0 == GL_TRUE) { 492 if (ctx->Point.CoordReplace & (1u << texunit)) 493 return; 494 FLUSH_VERTICES(ctx, _NEW_POINT | _NEW_FF_VERT_PROGRAM, 495 GL_POINT_BIT); 496 ctx->Point.CoordReplace |= (1u << texunit); 497 } else if (iparam0 == GL_FALSE) { 498 if (~(ctx->Point.CoordReplace) & (1u << texunit)) 499 return; 500 FLUSH_VERTICES(ctx, _NEW_POINT | _NEW_FF_VERT_PROGRAM, 501 GL_POINT_BIT); 502 ctx->Point.CoordReplace &= ~(1u << texunit); 503 } else { 504 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0); 505 return; 506 } 507 } 508 else { 509 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); 510 return; 511 } 512 } 513 else { 514 _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)", 515 _mesa_enum_to_string(target)); 516 return; 517 } 518 519 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) 520 _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", 521 _mesa_enum_to_string(target), 522 _mesa_enum_to_string(pname), 523 *param, 524 _mesa_enum_to_string((GLenum) iparam0)); 525 526 /* Tell device driver about the new texture environment */ 527 if (ctx->Driver.TexEnv) { 528 ctx->Driver.TexEnv(ctx, target, pname, param); 529 } 530} 531 532 533void GLAPIENTRY 534_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) 535{ 536 GET_CURRENT_CONTEXT(ctx); 537 _mesa_texenvfv_indexed(ctx, ctx->Texture.CurrentUnit, target, pname, param); 538} 539 540 541void GLAPIENTRY 542_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param ) 543{ 544 GLfloat p[4]; 545 p[0] = param; 546 p[1] = p[2] = p[3] = 0.0; 547 _mesa_TexEnvfv( target, pname, p ); 548} 549 550 551void GLAPIENTRY 552_mesa_TexEnvi( GLenum target, GLenum pname, GLint param ) 553{ 554 GLfloat p[4]; 555 p[0] = (GLfloat) param; 556 p[1] = p[2] = p[3] = 0.0; 557 _mesa_TexEnvfv( target, pname, p ); 558} 559 560 561void GLAPIENTRY 562_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param ) 563{ 564 GLfloat p[4]; 565 if (pname == GL_TEXTURE_ENV_COLOR) { 566 p[0] = INT_TO_FLOAT( param[0] ); 567 p[1] = INT_TO_FLOAT( param[1] ); 568 p[2] = INT_TO_FLOAT( param[2] ); 569 p[3] = INT_TO_FLOAT( param[3] ); 570 } 571 else { 572 p[0] = (GLfloat) param[0]; 573 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */ 574 } 575 _mesa_TexEnvfv( target, pname, p ); 576} 577 578 579void GLAPIENTRY 580_mesa_MultiTexEnvfEXT( GLenum texunit, GLenum target, 581 GLenum pname, GLfloat param ) 582{ 583 GET_CURRENT_CONTEXT(ctx); 584 GLfloat p[4]; 585 p[0] = param; 586 p[1] = p[2] = p[3] = 0.0; 587 _mesa_texenvfv_indexed(ctx, texunit - GL_TEXTURE0, target, pname, p); 588} 589 590void GLAPIENTRY 591_mesa_MultiTexEnvfvEXT( GLenum texunit, GLenum target, 592 GLenum pname, const GLfloat *param ) 593{ 594 GET_CURRENT_CONTEXT(ctx); 595 _mesa_texenvfv_indexed(ctx, texunit - GL_TEXTURE0, target, pname, param); 596} 597 598 599void GLAPIENTRY 600_mesa_MultiTexEnviEXT( GLenum texunit, GLenum target, 601 GLenum pname, GLint param ) 602{ 603 GET_CURRENT_CONTEXT(ctx); 604 GLfloat p[4]; 605 p[0] = (GLfloat) param; 606 p[1] = p[2] = p[3] = 0.0; 607 _mesa_texenvfv_indexed( ctx, texunit - GL_TEXTURE0, target, pname, p ); 608} 609 610 611void GLAPIENTRY 612_mesa_MultiTexEnvivEXT( GLenum texunit, GLenum target, 613 GLenum pname, const GLint *param ) 614{ 615 GET_CURRENT_CONTEXT(ctx); 616 GLfloat p[4]; 617 if (pname == GL_TEXTURE_ENV_COLOR) { 618 p[0] = INT_TO_FLOAT( param[0] ); 619 p[1] = INT_TO_FLOAT( param[1] ); 620 p[2] = INT_TO_FLOAT( param[2] ); 621 p[3] = INT_TO_FLOAT( param[3] ); 622 } 623 else { 624 p[0] = (GLfloat) param[0]; 625 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */ 626 } 627 _mesa_texenvfv_indexed( ctx, texunit - GL_TEXTURE0, target, pname, p ); 628} 629 630 631 632 633/** 634 * Helper for glGetTexEnvi/f() 635 * \return value of queried pname or -1 if error. 636 */ 637static GLint 638get_texenvi(struct gl_context *ctx, 639 const struct gl_fixedfunc_texture_unit *texUnit, 640 GLenum pname) 641{ 642 switch (pname) { 643 case GL_TEXTURE_ENV_MODE: 644 return texUnit->EnvMode; 645 break; 646 case GL_COMBINE_RGB: 647 return texUnit->Combine.ModeRGB; 648 case GL_COMBINE_ALPHA: 649 return texUnit->Combine.ModeA; 650 case GL_SOURCE0_RGB: 651 case GL_SOURCE1_RGB: 652 case GL_SOURCE2_RGB: { 653 const unsigned rgb_idx = pname - GL_SOURCE0_RGB; 654 return texUnit->Combine.SourceRGB[rgb_idx]; 655 } 656 case GL_SOURCE3_RGB_NV: 657 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 658 return texUnit->Combine.SourceRGB[3]; 659 } 660 else { 661 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 662 } 663 break; 664 case GL_SOURCE0_ALPHA: 665 case GL_SOURCE1_ALPHA: 666 case GL_SOURCE2_ALPHA: { 667 const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA; 668 return texUnit->Combine.SourceA[alpha_idx]; 669 } 670 case GL_SOURCE3_ALPHA_NV: 671 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 672 return texUnit->Combine.SourceA[3]; 673 } 674 else { 675 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 676 } 677 break; 678 case GL_OPERAND0_RGB: 679 case GL_OPERAND1_RGB: 680 case GL_OPERAND2_RGB: { 681 const unsigned op_rgb = pname - GL_OPERAND0_RGB; 682 return texUnit->Combine.OperandRGB[op_rgb]; 683 } 684 case GL_OPERAND3_RGB_NV: 685 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 686 return texUnit->Combine.OperandRGB[3]; 687 } 688 else { 689 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 690 } 691 break; 692 case GL_OPERAND0_ALPHA: 693 case GL_OPERAND1_ALPHA: 694 case GL_OPERAND2_ALPHA: { 695 const unsigned op_alpha = pname - GL_OPERAND0_ALPHA; 696 return texUnit->Combine.OperandA[op_alpha]; 697 } 698 case GL_OPERAND3_ALPHA_NV: 699 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 700 return texUnit->Combine.OperandA[3]; 701 } 702 else { 703 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 704 } 705 break; 706 case GL_RGB_SCALE: 707 return 1 << texUnit->Combine.ScaleShiftRGB; 708 case GL_ALPHA_SCALE: 709 return 1 << texUnit->Combine.ScaleShiftA; 710 default: 711 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 712 break; 713 } 714 715 return -1; /* error */ 716} 717 718 719static void 720_mesa_gettexenvfv_indexed( GLuint texunit, GLenum target, GLenum pname, GLfloat *params ) 721{ 722 GLuint maxUnit; 723 GET_CURRENT_CONTEXT(ctx); 724 725 maxUnit = (target == GL_POINT_SPRITE && pname == GL_COORD_REPLACE) 726 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 727 if (texunit >= maxUnit) { 728 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(texunit=%d)", texunit); 729 return; 730 } 731 732 if (target == GL_TEXTURE_ENV) { 733 struct gl_fixedfunc_texture_unit *texUnit = 734 _mesa_get_fixedfunc_tex_unit(ctx, texunit); 735 736 /* The GL spec says that we should report an error if the unit is greater 737 * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 738 * fixed-function units are usable. This is probably a spec bug. 739 * Ignore calls for non-fixed-func units, because we don't process 740 * glTexEnv for them either. 741 */ 742 if (!texUnit) 743 return; 744 745 if (pname == GL_TEXTURE_ENV_COLOR) { 746 if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 747 COPY_4FV( params, texUnit->EnvColor ); 748 else 749 COPY_4FV( params, texUnit->EnvColorUnclamped ); 750 } 751 else { 752 GLint val = get_texenvi(ctx, texUnit, pname); 753 if (val >= 0) { 754 *params = (GLfloat) val; 755 } 756 } 757 } 758 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 759 const struct gl_texture_unit *texUnit = _mesa_get_tex_unit(ctx, texunit); 760 761 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 762 *params = texUnit->LodBias; 763 } 764 else { 765 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 766 return; 767 } 768 } 769 else if (target == GL_POINT_SPRITE) { 770 /* GL_ARB_point_sprite */ 771 if (!ctx->Extensions.ARB_point_sprite) { 772 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 773 return; 774 } 775 if (pname == GL_COORD_REPLACE) { 776 if (ctx->Point.CoordReplace & (1u << texunit)) 777 *params = 1.0f; 778 else 779 *params = 0.0f; 780 } 781 else { 782 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 783 return; 784 } 785 } 786 else { 787 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 788 return; 789 } 790} 791 792 793static void 794_mesa_gettexenviv_indexed( GLuint texunit, GLenum target, 795 GLenum pname, GLint *params ) 796{ 797 GLuint maxUnit; 798 GET_CURRENT_CONTEXT(ctx); 799 800 maxUnit = (target == GL_POINT_SPRITE && pname == GL_COORD_REPLACE) 801 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 802 if (texunit >= maxUnit) { 803 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(texunit=%d)", 804 texunit); 805 return; 806 } 807 808 if (target == GL_TEXTURE_ENV) { 809 struct gl_fixedfunc_texture_unit *texUnit = 810 _mesa_get_fixedfunc_tex_unit(ctx, texunit); 811 812 /* The GL spec says that we should report an error if the unit is greater 813 * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 814 * fixed-function units are usable. This is probably a spec bug. 815 * Ignore calls for non-fixed-func units, because we don't process 816 * glTexEnv for them either. 817 */ 818 if (!texUnit) 819 return; 820 821 if (pname == GL_TEXTURE_ENV_COLOR) { 822 params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] ); 823 params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] ); 824 params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] ); 825 params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] ); 826 } 827 else { 828 GLint val = get_texenvi(ctx, texUnit, pname); 829 if (val >= 0) { 830 *params = val; 831 } 832 } 833 } 834 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 835 const struct gl_texture_unit *texUnit = _mesa_get_tex_unit(ctx, texunit); 836 837 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 838 *params = (GLint) texUnit->LodBias; 839 } 840 else { 841 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 842 return; 843 } 844 } 845 else if (target == GL_POINT_SPRITE) { 846 /* GL_ARB_point_sprite */ 847 if (!ctx->Extensions.ARB_point_sprite) { 848 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 849 return; 850 } 851 if (pname == GL_COORD_REPLACE) { 852 if (ctx->Point.CoordReplace & (1u << texunit)) 853 *params = GL_TRUE; 854 else 855 *params = GL_FALSE; 856 } 857 else { 858 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 859 return; 860 } 861 } 862 else { 863 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 864 return; 865 } 866} 867 868 869void GLAPIENTRY 870_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) 871{ 872 GET_CURRENT_CONTEXT(ctx); 873 _mesa_gettexenvfv_indexed(ctx->Texture.CurrentUnit, target, pname, params); 874} 875 876 877void GLAPIENTRY 878_mesa_GetMultiTexEnvfvEXT( GLenum texunit, GLenum target, 879 GLenum pname, GLfloat *params ) 880{ 881 _mesa_gettexenvfv_indexed(texunit - GL_TEXTURE0, target, pname, params); 882} 883 884 885void GLAPIENTRY 886_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) 887{ 888 GET_CURRENT_CONTEXT(ctx); 889 _mesa_gettexenviv_indexed(ctx->Texture.CurrentUnit, target, pname, params); 890} 891 892 893void GLAPIENTRY 894_mesa_GetMultiTexEnvivEXT( GLenum texunit, GLenum target, 895 GLenum pname, GLint *params ) 896{ 897 _mesa_gettexenviv_indexed(texunit - GL_TEXTURE0, target, pname, params); 898} 899