texenv.c revision af69d88d
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_lookup_enum_by_nr(value)); 46 47 48/** Set texture env mode */ 49static void 50set_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 89static void 90set_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 */ 106static void 107set_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 */ 172static void 173set_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 */ 262static void 263set_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 343static void 344set_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 385void 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 if (iparam0 == GL_TRUE || iparam0 == GL_FALSE) { 464 /* It's kind of weird to set point state via glTexEnv, 465 * but that's what the spec calls for. 466 */ 467 const GLboolean state = (GLboolean) iparam0; 468 if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state) 469 return; 470 FLUSH_VERTICES(ctx, _NEW_POINT); 471 ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state; 472 } 473 else { 474 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0); 475 return; 476 } 477 } 478 else { 479 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); 480 return; 481 } 482 } 483 else { 484 _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)", 485 _mesa_lookup_enum_by_nr(target)); 486 return; 487 } 488 489 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) 490 _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", 491 _mesa_lookup_enum_by_nr(target), 492 _mesa_lookup_enum_by_nr(pname), 493 *param, 494 _mesa_lookup_enum_by_nr((GLenum) iparam0)); 495 496 /* Tell device driver about the new texture environment */ 497 if (ctx->Driver.TexEnv) { 498 (*ctx->Driver.TexEnv)( ctx, target, pname, param ); 499 } 500} 501 502 503void GLAPIENTRY 504_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param ) 505{ 506 GLfloat p[4]; 507 p[0] = param; 508 p[1] = p[2] = p[3] = 0.0; 509 _mesa_TexEnvfv( target, pname, p ); 510} 511 512 513 514void GLAPIENTRY 515_mesa_TexEnvi( GLenum target, GLenum pname, GLint param ) 516{ 517 GLfloat p[4]; 518 p[0] = (GLfloat) param; 519 p[1] = p[2] = p[3] = 0.0; 520 _mesa_TexEnvfv( target, pname, p ); 521} 522 523 524void GLAPIENTRY 525_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param ) 526{ 527 GLfloat p[4]; 528 if (pname == GL_TEXTURE_ENV_COLOR) { 529 p[0] = INT_TO_FLOAT( param[0] ); 530 p[1] = INT_TO_FLOAT( param[1] ); 531 p[2] = INT_TO_FLOAT( param[2] ); 532 p[3] = INT_TO_FLOAT( param[3] ); 533 } 534 else { 535 p[0] = (GLfloat) param[0]; 536 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */ 537 } 538 _mesa_TexEnvfv( target, pname, p ); 539} 540 541 542 543/** 544 * Helper for glGetTexEnvi/f() 545 * \return value of queried pname or -1 if error. 546 */ 547static GLint 548get_texenvi(struct gl_context *ctx, const struct gl_texture_unit *texUnit, 549 GLenum pname) 550{ 551 switch (pname) { 552 case GL_TEXTURE_ENV_MODE: 553 return texUnit->EnvMode; 554 break; 555 case GL_COMBINE_RGB: 556 return texUnit->Combine.ModeRGB; 557 case GL_COMBINE_ALPHA: 558 return texUnit->Combine.ModeA; 559 case GL_SOURCE0_RGB: 560 case GL_SOURCE1_RGB: 561 case GL_SOURCE2_RGB: { 562 const unsigned rgb_idx = pname - GL_SOURCE0_RGB; 563 return texUnit->Combine.SourceRGB[rgb_idx]; 564 } 565 case GL_SOURCE3_RGB_NV: 566 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 567 return texUnit->Combine.SourceRGB[3]; 568 } 569 else { 570 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 571 } 572 break; 573 case GL_SOURCE0_ALPHA: 574 case GL_SOURCE1_ALPHA: 575 case GL_SOURCE2_ALPHA: { 576 const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA; 577 return texUnit->Combine.SourceA[alpha_idx]; 578 } 579 case GL_SOURCE3_ALPHA_NV: 580 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 581 return texUnit->Combine.SourceA[3]; 582 } 583 else { 584 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 585 } 586 break; 587 case GL_OPERAND0_RGB: 588 case GL_OPERAND1_RGB: 589 case GL_OPERAND2_RGB: { 590 const unsigned op_rgb = pname - GL_OPERAND0_RGB; 591 return texUnit->Combine.OperandRGB[op_rgb]; 592 } 593 case GL_OPERAND3_RGB_NV: 594 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 595 return texUnit->Combine.OperandRGB[3]; 596 } 597 else { 598 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 599 } 600 break; 601 case GL_OPERAND0_ALPHA: 602 case GL_OPERAND1_ALPHA: 603 case GL_OPERAND2_ALPHA: { 604 const unsigned op_alpha = pname - GL_OPERAND0_ALPHA; 605 return texUnit->Combine.OperandA[op_alpha]; 606 } 607 case GL_OPERAND3_ALPHA_NV: 608 if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) { 609 return texUnit->Combine.OperandA[3]; 610 } 611 else { 612 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 613 } 614 break; 615 case GL_RGB_SCALE: 616 return 1 << texUnit->Combine.ScaleShiftRGB; 617 case GL_ALPHA_SCALE: 618 return 1 << texUnit->Combine.ScaleShiftA; 619 default: 620 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 621 break; 622 } 623 624 return -1; /* error */ 625} 626 627 628 629void GLAPIENTRY 630_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) 631{ 632 GLuint maxUnit; 633 const struct gl_texture_unit *texUnit; 634 GET_CURRENT_CONTEXT(ctx); 635 636 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 637 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 638 if (ctx->Texture.CurrentUnit >= maxUnit) { 639 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)"); 640 return; 641 } 642 643 texUnit = _mesa_get_current_tex_unit(ctx); 644 645 if (target == GL_TEXTURE_ENV) { 646 if (pname == GL_TEXTURE_ENV_COLOR) { 647 if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) 648 _mesa_update_state(ctx); 649 if (_mesa_get_clamp_fragment_color(ctx)) 650 COPY_4FV( params, texUnit->EnvColor ); 651 else 652 COPY_4FV( params, texUnit->EnvColorUnclamped ); 653 } 654 else { 655 GLint val = get_texenvi(ctx, texUnit, pname); 656 if (val >= 0) { 657 *params = (GLfloat) val; 658 } 659 } 660 } 661 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 662 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 663 *params = texUnit->LodBias; 664 } 665 else { 666 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 667 return; 668 } 669 } 670 else if (target == GL_POINT_SPRITE_NV) { 671 /* GL_ARB_point_sprite / GL_NV_point_sprite */ 672 if (!ctx->Extensions.NV_point_sprite 673 && !ctx->Extensions.ARB_point_sprite) { 674 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 675 return; 676 } 677 if (pname == GL_COORD_REPLACE_NV) { 678 *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit]; 679 } 680 else { 681 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); 682 return; 683 } 684 } 685 else { 686 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); 687 return; 688 } 689} 690 691 692void GLAPIENTRY 693_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) 694{ 695 GLuint maxUnit; 696 const struct gl_texture_unit *texUnit; 697 GET_CURRENT_CONTEXT(ctx); 698 699 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) 700 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; 701 if (ctx->Texture.CurrentUnit >= maxUnit) { 702 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)"); 703 return; 704 } 705 706 texUnit = _mesa_get_current_tex_unit(ctx); 707 708 if (target == GL_TEXTURE_ENV) { 709 if (pname == GL_TEXTURE_ENV_COLOR) { 710 params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] ); 711 params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] ); 712 params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] ); 713 params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] ); 714 } 715 else { 716 GLint val = get_texenvi(ctx, texUnit, pname); 717 if (val >= 0) { 718 *params = val; 719 } 720 } 721 } 722 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { 723 if (pname == GL_TEXTURE_LOD_BIAS_EXT) { 724 *params = (GLint) texUnit->LodBias; 725 } 726 else { 727 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 728 return; 729 } 730 } 731 else if (target == GL_POINT_SPRITE_NV) { 732 /* GL_ARB_point_sprite / GL_NV_point_sprite */ 733 if (!ctx->Extensions.NV_point_sprite 734 && !ctx->Extensions.ARB_point_sprite) { 735 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 736 return; 737 } 738 if (pname == GL_COORD_REPLACE_NV) { 739 *params = (GLint) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit]; 740 } 741 else { 742 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); 743 return; 744 } 745 } 746 else { 747 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); 748 return; 749 } 750} 751 752