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 */ 49 static void 50 set_env_mode(struct gl_context *ctx, 51 struct gl_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); 81 texUnit->EnvMode = mode; 82 } 83 else { 84 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); 85 } 86 } 87 88 89 static void 90 set_env_color(struct gl_context *ctx, 91 struct gl_texture_unit *texUnit, 92 const GLfloat *color) 93 { 94 if (TEST_EQ_4V(color, texUnit->EnvColorUnclamped)) 95 return; 96 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 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 */ 106 static void 107 set_combiner_mode(struct gl_context *ctx, 108 struct gl_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; 148 } 149 150 switch (pname) { 151 case GL_COMBINE_RGB: 152 if (texUnit->Combine.ModeRGB == mode) 153 return; 154 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 155 texUnit->Combine.ModeRGB = mode; 156 break; 157 158 case GL_COMBINE_ALPHA: 159 if (texUnit->Combine.ModeA == mode) 160 return; 161 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 162 texUnit->Combine.ModeA = mode; 163 break; 164 default: 165 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 166 } 167 } 168 169 170 171 /** Set an RGB or A combiner source term */ 172 static void 173 set_combiner_source(struct gl_context *ctx, 174 struct gl_texture_unit *texUnit, 175 GLenum pname, GLenum param) 176 { 177 GLuint term; 178 GLboolean alpha, legal; 179 180 /* 181 * Translate pname to (term, alpha). 182 * 183 * The enums were given sequential values for a reason. 184 */ 185 switch (pname) { 186 case GL_SOURCE0_RGB: 187 case GL_SOURCE1_RGB: 188 case GL_SOURCE2_RGB: 189 case GL_SOURCE3_RGB_NV: 190 term = pname - GL_SOURCE0_RGB; 191 alpha = GL_FALSE; 192 break; 193 case GL_SOURCE0_ALPHA: 194 case GL_SOURCE1_ALPHA: 195 case GL_SOURCE2_ALPHA: 196 case GL_SOURCE3_ALPHA_NV: 197 term = pname - GL_SOURCE0_ALPHA; 198 alpha = GL_TRUE; 199 break; 200 default: 201 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 202 return; 203 } 204 205 if ((term == 3) && (ctx->API != API_OPENGL_COMPAT 206 || !ctx->Extensions.NV_texture_env_combine4)) { 207 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 208 return; 209 } 210 211 assert(term < MAX_COMBINER_TERMS); 212 213 /* 214 * Error-check param (the source term) 215 */ 216 switch (param) { 217 case GL_TEXTURE: 218 case GL_CONSTANT: 219 case GL_PRIMARY_COLOR: 220 case GL_PREVIOUS: 221 legal = GL_TRUE; 222 break; 223 case GL_TEXTURE0: 224 case GL_TEXTURE1: 225 case GL_TEXTURE2: 226 case GL_TEXTURE3: 227 case GL_TEXTURE4: 228 case GL_TEXTURE5: 229 case GL_TEXTURE6: 230 case GL_TEXTURE7: 231 legal = (ctx->Extensions.ARB_texture_env_crossbar && 232 param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits); 233 break; 234 case GL_ZERO: 235 legal = (ctx->API == API_OPENGL_COMPAT && 236 (ctx->Extensions.ATI_texture_env_combine3 || 237 ctx->Extensions.NV_texture_env_combine4)); 238 break; 239 case GL_ONE: 240 legal = (ctx->API == API_OPENGL_COMPAT && 241 ctx->Extensions.ATI_texture_env_combine3); 242 break; 243 default: 244 legal = GL_FALSE; 245 } 246 247 if (!legal) { 248 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param); 249 return; 250 } 251 252 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 253 254 if (alpha) 255 texUnit->Combine.SourceA[term] = param; 256 else 257 texUnit->Combine.SourceRGB[term] = param; 258 } 259 260 261 /** Set an RGB or A combiner operand term */ 262 static void 263 set_combiner_operand(struct gl_context *ctx, 264 struct gl_texture_unit *texUnit, 265 GLenum pname, GLenum param) 266 { 267 GLuint term; 268 GLboolean alpha, legal; 269 270 /* The enums were given sequential values for a reason. 271 */ 272 switch (pname) { 273 case GL_OPERAND0_RGB: 274 case GL_OPERAND1_RGB: 275 case GL_OPERAND2_RGB: 276 case GL_OPERAND3_RGB_NV: 277 term = pname - GL_OPERAND0_RGB; 278 alpha = GL_FALSE; 279 break; 280 case GL_OPERAND0_ALPHA: 281 case GL_OPERAND1_ALPHA: 282 case GL_OPERAND2_ALPHA: 283 case GL_OPERAND3_ALPHA_NV: 284 term = pname - GL_OPERAND0_ALPHA; 285 alpha = GL_TRUE; 286 break; 287 default: 288 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 289 return; 290 } 291 292 if ((term == 3) && (ctx->API != API_OPENGL_COMPAT 293 || !ctx->Extensions.NV_texture_env_combine4)) { 294 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 295 return; 296 } 297 298 assert(term < MAX_COMBINER_TERMS); 299 300 /* 301 * Error-check param (the source operand) 302 */ 303 switch (param) { 304 case GL_SRC_COLOR: 305 case GL_ONE_MINUS_SRC_COLOR: 306 /* The color input can only be used with GL_OPERAND[01]_RGB in the EXT 307 * version. In the ARB and NV versions and OpenGL ES 1.x they can be 308 * used for any RGB operand. 309 */ 310 legal = !alpha 311 && ((term < 2) || ctx->Extensions.ARB_texture_env_combine 312 || ctx->Extensions.NV_texture_env_combine4); 313 break; 314 case GL_ONE_MINUS_SRC_ALPHA: 315 /* GL_ONE_MINUS_SRC_ALPHA can only be used with 316 * GL_OPERAND[01]_(RGB|ALPHA) in the EXT version. In the ARB and NV 317 * versions and OpenGL ES 1.x it can be used for any operand. 318 */ 319 legal = (term < 2) || ctx->Extensions.ARB_texture_env_combine 320 || ctx->Extensions.NV_texture_env_combine4; 321 break; 322 case GL_SRC_ALPHA: 323 legal = GL_TRUE; 324 break; 325 default: 326 legal = GL_FALSE; 327 } 328 329 if (!legal) { 330 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param); 331 return; 332 } 333 334 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 335 336 if (alpha) 337 texUnit->Combine.OperandA[term] = param; 338 else 339 texUnit->Combine.OperandRGB[term] = param; 340 } 341 342 343 static void 344 set_combiner_scale(struct gl_context *ctx, 345 struct gl_texture_unit *texUnit, 346 GLenum pname, GLfloat scale) 347 { 348 GLuint shift; 349 350 if (scale == 1.0F) { 351 shift = 0; 352 } 353 else if (scale == 2.0F) { 354 shift = 1; 355 } 356 else if (scale == 4.0F) { 357 shift = 2; 358 } 359 else { 360 _mesa_error( ctx, GL_INVALID_VALUE, 361 "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" ); 362 return; 363 } 364 365 switch (pname) { 366 case GL_RGB_SCALE: 367 if (texUnit->Combine.ScaleShiftRGB == shift) 368 return; 369 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 370 texUnit->Combine.ScaleShiftRGB = shift; 371 break; 372 case GL_ALPHA_SCALE: 373 if (texUnit->Combine.ScaleShiftA == shift) 374 return; 375 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 376 texUnit->Combine.ScaleShiftA = shift; 377 break; 378 default: 379 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 380 } 381 } 382 383 384 385 void GLAPIENTRY 386 _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) 387 { 388 const GLint iparam0 = (GLint) param[0]; 389 struct gl_texture_unit *texUnit; 390 GLuint maxUnit; 391 GET_CURRENT_CONTEXT(ctx); 392 393 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 394 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 395 if (ctx->Texture.CurrentUnit >= maxUnit) { 396 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)"); 397 return; 398 } 399 400 texUnit = _mesa_get_current_tex_unit(ctx); 401 402 if (target == GL_TEXTURE_ENV) { 403 switch (pname) { 404 case GL_TEXTURE_ENV_MODE: 405 set_env_mode(ctx, texUnit, (GLenum) iparam0); 406 break; 407 case GL_TEXTURE_ENV_COLOR: 408 set_env_color(ctx, texUnit, param); 409 break; 410 case GL_COMBINE_RGB: 411 case GL_COMBINE_ALPHA: 412 set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0); 413 break; 414 case GL_SOURCE0_RGB: 415 case GL_SOURCE1_RGB: 416 case GL_SOURCE2_RGB: 417 case GL_SOURCE3_RGB_NV: 418 case GL_SOURCE0_ALPHA: 419 case GL_SOURCE1_ALPHA: 420 case GL_SOURCE2_ALPHA: 421 case GL_SOURCE3_ALPHA_NV: 422 set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0); 423 break; 424 case GL_OPERAND0_RGB: 425 case GL_OPERAND1_RGB: 426 case GL_OPERAND2_RGB: 427 case GL_OPERAND3_RGB_NV: 428 case GL_OPERAND0_ALPHA: 429 case GL_OPERAND1_ALPHA: 430 case GL_OPERAND2_ALPHA: 431 case GL_OPERAND3_ALPHA_NV: 432 set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0); 433 break; 434 case GL_RGB_SCALE: 435 case GL_ALPHA_SCALE: 436 set_combiner_scale(ctx, texUnit, pname, param[0]); 437 break; 438 default: 439 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); 440 return; 441 } 442 } 443 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 444 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 445 if (texUnit->LodBias == param[0]) 446 return; 447 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 448 texUnit->LodBias = param[0]; 449 } 450 else { 451 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); 452 return; 453 } 454 } 455 else if (target == GL_POINT_SPRITE_NV) { 456 /* GL_ARB_point_sprite / GL_NV_point_sprite */ 457 if (!ctx->Extensions.NV_point_sprite 458 && !ctx->Extensions.ARB_point_sprite) { 459 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target ); 460 return; 461 } 462 if (pname == GL_COORD_REPLACE_NV) { 463 /* It's kind of weird to set point state via glTexEnv, 464 * but that's what the spec calls for. 465 */ 466 if (iparam0 == GL_TRUE) { 467 if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 468 return; 469 ctx->Point.CoordReplace |= (1u << ctx->Texture.CurrentUnit); 470 } else if (iparam0 == GL_FALSE) { 471 if (~(ctx->Point.CoordReplace) & (1u << ctx->Texture.CurrentUnit)) 472 return; 473 ctx->Point.CoordReplace &= ~(1u << ctx->Texture.CurrentUnit); 474 } else { 475 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0); 476 return; 477 } 478 FLUSH_VERTICES(ctx, _NEW_POINT); 479 } 480 else { 481 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); 482 return; 483 } 484 } 485 else { 486 _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)", 487 _mesa_enum_to_string(target)); 488 return; 489 } 490 491 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) 492 _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", 493 _mesa_enum_to_string(target), 494 _mesa_enum_to_string(pname), 495 *param, 496 _mesa_enum_to_string((GLenum) iparam0)); 497 498 /* Tell device driver about the new texture environment */ 499 if (ctx->Driver.TexEnv) { 500 ctx->Driver.TexEnv(ctx, target, pname, param); 501 } 502 } 503 504 505 void GLAPIENTRY 506 _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param ) 507 { 508 GLfloat p[4]; 509 p[0] = param; 510 p[1] = p[2] = p[3] = 0.0; 511 _mesa_TexEnvfv( target, pname, p ); 512 } 513 514 515 516 void GLAPIENTRY 517 _mesa_TexEnvi( GLenum target, GLenum pname, GLint param ) 518 { 519 GLfloat p[4]; 520 p[0] = (GLfloat) param; 521 p[1] = p[2] = p[3] = 0.0; 522 _mesa_TexEnvfv( target, pname, p ); 523 } 524 525 526 void GLAPIENTRY 527 _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param ) 528 { 529 GLfloat p[4]; 530 if (pname == GL_TEXTURE_ENV_COLOR) { 531 p[0] = INT_TO_FLOAT( param[0] ); 532 p[1] = INT_TO_FLOAT( param[1] ); 533 p[2] = INT_TO_FLOAT( param[2] ); 534 p[3] = INT_TO_FLOAT( param[3] ); 535 } 536 else { 537 p[0] = (GLfloat) param[0]; 538 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */ 539 } 540 _mesa_TexEnvfv( target, pname, p ); 541 } 542 543 544 545 /** 546 * Helper for glGetTexEnvi/f() 547 * \return value of queried pname or -1 if error. 548 */ 549 static GLint 550 get_texenvi(struct gl_context *ctx, const struct gl_texture_unit *texUnit, 551 GLenum pname) 552 { 553 switch (pname) { 554 case GL_TEXTURE_ENV_MODE: 555 return texUnit->EnvMode; 556 break; 557 case GL_COMBINE_RGB: 558 return texUnit->Combine.ModeRGB; 559 case GL_COMBINE_ALPHA: 560 return texUnit->Combine.ModeA; 561 case GL_SOURCE0_RGB: 562 case GL_SOURCE1_RGB: 563 case GL_SOURCE2_RGB: { 564 const unsigned rgb_idx = pname - GL_SOURCE0_RGB; 565 return texUnit->Combine.SourceRGB[rgb_idx]; 566 } 567 case GL_SOURCE3_RGB_NV: 568 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 569 return texUnit->Combine.SourceRGB[3]; 570 } 571 else { 572 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 573 } 574 break; 575 case GL_SOURCE0_ALPHA: 576 case GL_SOURCE1_ALPHA: 577 case GL_SOURCE2_ALPHA: { 578 const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA; 579 return texUnit->Combine.SourceA[alpha_idx]; 580 } 581 case GL_SOURCE3_ALPHA_NV: 582 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 583 return texUnit->Combine.SourceA[3]; 584 } 585 else { 586 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 587 } 588 break; 589 case GL_OPERAND0_RGB: 590 case GL_OPERAND1_RGB: 591 case GL_OPERAND2_RGB: { 592 const unsigned op_rgb = pname - GL_OPERAND0_RGB; 593 return texUnit->Combine.OperandRGB[op_rgb]; 594 } 595 case GL_OPERAND3_RGB_NV: 596 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 597 return texUnit->Combine.OperandRGB[3]; 598 } 599 else { 600 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 601 } 602 break; 603 case GL_OPERAND0_ALPHA: 604 case GL_OPERAND1_ALPHA: 605 case GL_OPERAND2_ALPHA: { 606 const unsigned op_alpha = pname - GL_OPERAND0_ALPHA; 607 return texUnit->Combine.OperandA[op_alpha]; 608 } 609 case GL_OPERAND3_ALPHA_NV: 610 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 611 return texUnit->Combine.OperandA[3]; 612 } 613 else { 614 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 615 } 616 break; 617 case GL_RGB_SCALE: 618 return 1 << texUnit->Combine.ScaleShiftRGB; 619 case GL_ALPHA_SCALE: 620 return 1 << texUnit->Combine.ScaleShiftA; 621 default: 622 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 623 break; 624 } 625 626 return -1; /* error */ 627 } 628 629 630 631 void GLAPIENTRY 632 _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) 633 { 634 GLuint maxUnit; 635 const struct gl_texture_unit *texUnit; 636 GET_CURRENT_CONTEXT(ctx); 637 638 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 639 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 640 if (ctx->Texture.CurrentUnit >= maxUnit) { 641 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)"); 642 return; 643 } 644 645 texUnit = _mesa_get_current_tex_unit(ctx); 646 647 if (target == GL_TEXTURE_ENV) { 648 if (pname == GL_TEXTURE_ENV_COLOR) { 649 if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) 650 _mesa_update_state(ctx); 651 if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 652 COPY_4FV( params, texUnit->EnvColor ); 653 else 654 COPY_4FV( params, texUnit->EnvColorUnclamped ); 655 } 656 else { 657 GLint val = get_texenvi(ctx, texUnit, pname); 658 if (val >= 0) { 659 *params = (GLfloat) val; 660 } 661 } 662 } 663 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 664 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 665 *params = texUnit->LodBias; 666 } 667 else { 668 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 669 return; 670 } 671 } 672 else if (target == GL_POINT_SPRITE_NV) { 673 /* GL_ARB_point_sprite / GL_NV_point_sprite */ 674 if (!ctx->Extensions.NV_point_sprite 675 && !ctx->Extensions.ARB_point_sprite) { 676 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 677 return; 678 } 679 if (pname == GL_COORD_REPLACE_NV) { 680 if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 681 *params = 1.0f; 682 else 683 *params = 0.0f; 684 } 685 else { 686 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 687 return; 688 } 689 } 690 else { 691 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 692 return; 693 } 694 } 695 696 697 void GLAPIENTRY 698 _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) 699 { 700 GLuint maxUnit; 701 const struct gl_texture_unit *texUnit; 702 GET_CURRENT_CONTEXT(ctx); 703 704 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 705 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 706 if (ctx->Texture.CurrentUnit >= maxUnit) { 707 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)"); 708 return; 709 } 710 711 texUnit = _mesa_get_current_tex_unit(ctx); 712 713 if (target == GL_TEXTURE_ENV) { 714 if (pname == GL_TEXTURE_ENV_COLOR) { 715 params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] ); 716 params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] ); 717 params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] ); 718 params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] ); 719 } 720 else { 721 GLint val = get_texenvi(ctx, texUnit, pname); 722 if (val >= 0) { 723 *params = val; 724 } 725 } 726 } 727 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 728 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 729 *params = (GLint) texUnit->LodBias; 730 } 731 else { 732 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 733 return; 734 } 735 } 736 else if (target == GL_POINT_SPRITE_NV) { 737 /* GL_ARB_point_sprite / GL_NV_point_sprite */ 738 if (!ctx->Extensions.NV_point_sprite 739 && !ctx->Extensions.ARB_point_sprite) { 740 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 741 return; 742 } 743 if (pname == GL_COORD_REPLACE_NV) { 744 if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit)) 745 *params = GL_TRUE; 746 else 747 *params = GL_FALSE; 748 } 749 else { 750 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 751 return; 752 } 753 } 754 else { 755 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 756 return; 757 } 758 } 759 760