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); 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); 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); 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); 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); 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); 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); 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); 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 394 395void GLAPIENTRY 396_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) 397{ 398 const GLint iparam0 = (GLint) param[0]; 399 GLuint maxUnit; 400 GET_CURRENT_CONTEXT(ctx); 401 402 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 403 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 404 if (ctx->Texture.CurrentUnit >= maxUnit) { 405 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)"); 406 return; 407 } 408 409 if (target == GL_TEXTURE_ENV) { 410 struct gl_fixedfunc_texture_unit *texUnit = 411 _mesa_get_current_fixedfunc_tex_unit(ctx); 412 413 /* The GL spec says that we should report an error if the unit is greater 414 * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 415 * fixed-function units are usable. This is probably a spec bug. 416 * Ignore glTexEnv(GL_TEXTURE_ENV) calls for non-fixed-func units, 417 * because we don't want to process calls that have no effect. 418 */ 419 if (!texUnit) 420 return; 421 422 switch (pname) { 423 case GL_TEXTURE_ENV_MODE: 424 set_env_mode(ctx, texUnit, (GLenum) iparam0); 425 break; 426 case GL_TEXTURE_ENV_COLOR: 427 set_env_color(ctx, texUnit, param); 428 break; 429 case GL_COMBINE_RGB: 430 case GL_COMBINE_ALPHA: 431 if (!set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0)) 432 return; 433 break; 434 case GL_SOURCE0_RGB: 435 case GL_SOURCE1_RGB: 436 case GL_SOURCE2_RGB: 437 case GL_SOURCE3_RGB_NV: 438 case GL_SOURCE0_ALPHA: 439 case GL_SOURCE1_ALPHA: 440 case GL_SOURCE2_ALPHA: 441 case GL_SOURCE3_ALPHA_NV: 442 if (!set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0)) 443 return; 444 break; 445 case GL_OPERAND0_RGB: 446 case GL_OPERAND1_RGB: 447 case GL_OPERAND2_RGB: 448 case GL_OPERAND3_RGB_NV: 449 case GL_OPERAND0_ALPHA: 450 case GL_OPERAND1_ALPHA: 451 case GL_OPERAND2_ALPHA: 452 case GL_OPERAND3_ALPHA_NV: 453 if (!set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0)) 454 return; 455 break; 456 case GL_RGB_SCALE: 457 case GL_ALPHA_SCALE: 458 if (!set_combiner_scale(ctx, texUnit, pname, param[0])) 459 return; 460 break; 461 default: 462 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); 463 return; 464 } 465 } 466 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 467 struct gl_texture_unit *texUnit = 468 _mesa_get_current_tex_unit(ctx); 469 470 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 471 if (texUnit->LodBias == param[0]) 472 return; 473 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT); 474 texUnit->LodBias = 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_NV) { 482 /* GL_ARB_point_sprite / GL_NV_point_sprite */ 483 if (!ctx->Extensions.NV_point_sprite 484 && !ctx->Extensions.ARB_point_sprite) { 485 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target ); 486 return; 487 } 488 if (pname == GL_COORD_REPLACE_NV) { 489 /* It's kind of weird to set point state via glTexEnv, 490 * but that's what the spec calls for. 491 */ 492 if (iparam0 == GL_TRUE) { 493 if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 494 return; 495 ctx->Point.CoordReplace |= (1u << ctx->Texture.CurrentUnit); 496 } else if (iparam0 == GL_FALSE) { 497 if (~(ctx->Point.CoordReplace) & (1u << ctx->Texture.CurrentUnit)) 498 return; 499 ctx->Point.CoordReplace &= ~(1u << ctx->Texture.CurrentUnit); 500 } else { 501 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0); 502 return; 503 } 504 FLUSH_VERTICES(ctx, _NEW_POINT); 505 } 506 else { 507 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); 508 return; 509 } 510 } 511 else { 512 _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)", 513 _mesa_enum_to_string(target)); 514 return; 515 } 516 517 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) 518 _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", 519 _mesa_enum_to_string(target), 520 _mesa_enum_to_string(pname), 521 *param, 522 _mesa_enum_to_string((GLenum) iparam0)); 523 524 /* Tell device driver about the new texture environment */ 525 if (ctx->Driver.TexEnv) { 526 ctx->Driver.TexEnv(ctx, target, pname, param); 527 } 528} 529 530 531void GLAPIENTRY 532_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param ) 533{ 534 GLfloat p[4]; 535 p[0] = param; 536 p[1] = p[2] = p[3] = 0.0; 537 _mesa_TexEnvfv( target, pname, p ); 538} 539 540 541 542void GLAPIENTRY 543_mesa_TexEnvi( GLenum target, GLenum pname, GLint param ) 544{ 545 GLfloat p[4]; 546 p[0] = (GLfloat) param; 547 p[1] = p[2] = p[3] = 0.0; 548 _mesa_TexEnvfv( target, pname, p ); 549} 550 551 552void GLAPIENTRY 553_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param ) 554{ 555 GLfloat p[4]; 556 if (pname == GL_TEXTURE_ENV_COLOR) { 557 p[0] = INT_TO_FLOAT( param[0] ); 558 p[1] = INT_TO_FLOAT( param[1] ); 559 p[2] = INT_TO_FLOAT( param[2] ); 560 p[3] = INT_TO_FLOAT( param[3] ); 561 } 562 else { 563 p[0] = (GLfloat) param[0]; 564 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */ 565 } 566 _mesa_TexEnvfv( target, pname, p ); 567} 568 569 570 571/** 572 * Helper for glGetTexEnvi/f() 573 * \return value of queried pname or -1 if error. 574 */ 575static GLint 576get_texenvi(struct gl_context *ctx, 577 const struct gl_fixedfunc_texture_unit *texUnit, 578 GLenum pname) 579{ 580 switch (pname) { 581 case GL_TEXTURE_ENV_MODE: 582 return texUnit->EnvMode; 583 break; 584 case GL_COMBINE_RGB: 585 return texUnit->Combine.ModeRGB; 586 case GL_COMBINE_ALPHA: 587 return texUnit->Combine.ModeA; 588 case GL_SOURCE0_RGB: 589 case GL_SOURCE1_RGB: 590 case GL_SOURCE2_RGB: { 591 const unsigned rgb_idx = pname - GL_SOURCE0_RGB; 592 return texUnit->Combine.SourceRGB[rgb_idx]; 593 } 594 case GL_SOURCE3_RGB_NV: 595 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 596 return texUnit->Combine.SourceRGB[3]; 597 } 598 else { 599 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 600 } 601 break; 602 case GL_SOURCE0_ALPHA: 603 case GL_SOURCE1_ALPHA: 604 case GL_SOURCE2_ALPHA: { 605 const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA; 606 return texUnit->Combine.SourceA[alpha_idx]; 607 } 608 case GL_SOURCE3_ALPHA_NV: 609 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 610 return texUnit->Combine.SourceA[3]; 611 } 612 else { 613 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 614 } 615 break; 616 case GL_OPERAND0_RGB: 617 case GL_OPERAND1_RGB: 618 case GL_OPERAND2_RGB: { 619 const unsigned op_rgb = pname - GL_OPERAND0_RGB; 620 return texUnit->Combine.OperandRGB[op_rgb]; 621 } 622 case GL_OPERAND3_RGB_NV: 623 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 624 return texUnit->Combine.OperandRGB[3]; 625 } 626 else { 627 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 628 } 629 break; 630 case GL_OPERAND0_ALPHA: 631 case GL_OPERAND1_ALPHA: 632 case GL_OPERAND2_ALPHA: { 633 const unsigned op_alpha = pname - GL_OPERAND0_ALPHA; 634 return texUnit->Combine.OperandA[op_alpha]; 635 } 636 case GL_OPERAND3_ALPHA_NV: 637 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 638 return texUnit->Combine.OperandA[3]; 639 } 640 else { 641 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 642 } 643 break; 644 case GL_RGB_SCALE: 645 return 1 << texUnit->Combine.ScaleShiftRGB; 646 case GL_ALPHA_SCALE: 647 return 1 << texUnit->Combine.ScaleShiftA; 648 default: 649 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 650 break; 651 } 652 653 return -1; /* error */ 654} 655 656 657 658void GLAPIENTRY 659_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) 660{ 661 GLuint maxUnit; 662 GET_CURRENT_CONTEXT(ctx); 663 664 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 665 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 666 if (ctx->Texture.CurrentUnit >= maxUnit) { 667 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)"); 668 return; 669 } 670 671 if (target == GL_TEXTURE_ENV) { 672 struct gl_fixedfunc_texture_unit *texUnit = 673 _mesa_get_current_fixedfunc_tex_unit(ctx); 674 675 /* The GL spec says that we should report an error if the unit is greater 676 * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 677 * fixed-function units are usable. This is probably a spec bug. 678 * Ignore calls for non-fixed-func units, because we don't process 679 * glTexEnv for them either. 680 */ 681 if (!texUnit) 682 return; 683 684 if (pname == GL_TEXTURE_ENV_COLOR) { 685 if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) 686 _mesa_update_state(ctx); 687 if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 688 COPY_4FV( params, texUnit->EnvColor ); 689 else 690 COPY_4FV( params, texUnit->EnvColorUnclamped ); 691 } 692 else { 693 GLint val = get_texenvi(ctx, texUnit, pname); 694 if (val >= 0) { 695 *params = (GLfloat) val; 696 } 697 } 698 } 699 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 700 const struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 701 702 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 703 *params = texUnit->LodBias; 704 } 705 else { 706 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 707 return; 708 } 709 } 710 else if (target == GL_POINT_SPRITE_NV) { 711 /* GL_ARB_point_sprite / GL_NV_point_sprite */ 712 if (!ctx->Extensions.NV_point_sprite 713 && !ctx->Extensions.ARB_point_sprite) { 714 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 715 return; 716 } 717 if (pname == GL_COORD_REPLACE_NV) { 718 if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 719 *params = 1.0f; 720 else 721 *params = 0.0f; 722 } 723 else { 724 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 725 return; 726 } 727 } 728 else { 729 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 730 return; 731 } 732} 733 734 735void GLAPIENTRY 736_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) 737{ 738 GLuint maxUnit; 739 GET_CURRENT_CONTEXT(ctx); 740 741 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 742 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 743 if (ctx->Texture.CurrentUnit >= maxUnit) { 744 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)"); 745 return; 746 } 747 748 if (target == GL_TEXTURE_ENV) { 749 struct gl_fixedfunc_texture_unit *texUnit = 750 _mesa_get_current_fixedfunc_tex_unit(ctx); 751 752 /* The GL spec says that we should report an error if the unit is greater 753 * than GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, but in practice, only 754 * fixed-function units are usable. This is probably a spec bug. 755 * Ignore calls for non-fixed-func units, because we don't process 756 * glTexEnv for them either. 757 */ 758 if (!texUnit) 759 return; 760 761 if (pname == GL_TEXTURE_ENV_COLOR) { 762 params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] ); 763 params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] ); 764 params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] ); 765 params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] ); 766 } 767 else { 768 GLint val = get_texenvi(ctx, texUnit, pname); 769 if (val >= 0) { 770 *params = val; 771 } 772 } 773 } 774 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 775 const struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 776 777 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 778 *params = (GLint) texUnit->LodBias; 779 } 780 else { 781 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 782 return; 783 } 784 } 785 else if (target == GL_POINT_SPRITE_NV) { 786 /* GL_ARB_point_sprite / GL_NV_point_sprite */ 787 if (!ctx->Extensions.NV_point_sprite 788 && !ctx->Extensions.ARB_point_sprite) { 789 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 790 return; 791 } 792 if (pname == GL_COORD_REPLACE_NV) { 793 if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 794 *params = GL_TRUE; 795 else 796 *params = GL_FALSE; 797 } 798 else { 799 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 800 return; 801 } 802 } 803 else { 804 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 805 return; 806 } 807} 808 809