1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.5 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 /** 27 * \file texparam.c 28 * 29 * glTexParameter-related functions 30 */ 31 32 #include <stdbool.h> 33 #include "main/glheader.h" 34 #include "main/colormac.h" 35 #include "main/context.h" 36 #include "main/enums.h" 37 #include "main/formats.h" 38 #include "main/glformats.h" 39 #include "main/macros.h" 40 #include "main/mfeatures.h" 41 #include "main/mtypes.h" 42 #include "main/state.h" 43 #include "main/texcompress.h" 44 #include "main/texobj.h" 45 #include "main/texparam.h" 46 #include "main/teximage.h" 47 #include "main/texstate.h" 48 #include "program/prog_instruction.h" 49 50 51 /** 52 * Check if a coordinate wrap mode is supported for the texture target. 53 * \return GL_TRUE if legal, GL_FALSE otherwise 54 */ 55 static GLboolean 56 validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap) 57 { 58 const struct gl_extensions * const e = & ctx->Extensions; 59 const bool is_desktop_gl = _mesa_is_desktop_gl(ctx); 60 bool supported; 61 62 switch (wrap) { 63 case GL_CLAMP: 64 /* GL_CLAMP was removed in the core profile, and it has never existed in 65 * OpenGL ES. 66 */ 67 supported = (ctx->API == API_OPENGL) 68 && (target != GL_TEXTURE_EXTERNAL_OES); 69 break; 70 71 case GL_CLAMP_TO_EDGE: 72 supported = true; 73 break; 74 75 case GL_CLAMP_TO_BORDER: 76 supported = is_desktop_gl && e->ARB_texture_border_clamp 77 && (target != GL_TEXTURE_EXTERNAL_OES); 78 break; 79 80 case GL_REPEAT: 81 case GL_MIRRORED_REPEAT: 82 supported = (target != GL_TEXTURE_RECTANGLE_NV) 83 && (target != GL_TEXTURE_EXTERNAL_OES); 84 break; 85 86 case GL_MIRROR_CLAMP_EXT: 87 case GL_MIRROR_CLAMP_TO_EDGE_EXT: 88 supported = is_desktop_gl 89 && (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp) 90 && (target != GL_TEXTURE_RECTANGLE_NV) 91 && (target != GL_TEXTURE_EXTERNAL_OES); 92 break; 93 94 case GL_MIRROR_CLAMP_TO_BORDER_EXT: 95 supported = is_desktop_gl && e->EXT_texture_mirror_clamp 96 && (target != GL_TEXTURE_RECTANGLE_NV) 97 && (target != GL_TEXTURE_EXTERNAL_OES); 98 break; 99 100 default: 101 supported = false; 102 break; 103 } 104 105 if (!supported) 106 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", wrap ); 107 108 return supported; 109 } 110 111 112 /** 113 * Get current texture object for given target. 114 * Return NULL if any error (and record the error). 115 * Note that this is different from _mesa_select_tex_object() in that proxy 116 * targets are not accepted. 117 * Only the glGetTexLevelParameter() functions accept proxy targets. 118 */ 119 static struct gl_texture_object * 120 get_texobj(struct gl_context *ctx, GLenum target, GLboolean get) 121 { 122 struct gl_texture_unit *texUnit; 123 124 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) { 125 _mesa_error(ctx, GL_INVALID_OPERATION, 126 "gl%sTexParameter(current unit)", get ? "Get" : ""); 127 return NULL; 128 } 129 130 texUnit = _mesa_get_current_tex_unit(ctx); 131 132 switch (target) { 133 case GL_TEXTURE_1D: 134 if (_mesa_is_desktop_gl(ctx)) 135 return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 136 break; 137 case GL_TEXTURE_2D: 138 return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 139 case GL_TEXTURE_3D: 140 if (ctx->API != API_OPENGLES) 141 return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 142 break; 143 case GL_TEXTURE_CUBE_MAP: 144 if (ctx->Extensions.ARB_texture_cube_map) { 145 return texUnit->CurrentTex[TEXTURE_CUBE_INDEX]; 146 } 147 break; 148 case GL_TEXTURE_RECTANGLE_NV: 149 if (_mesa_is_desktop_gl(ctx) 150 && ctx->Extensions.NV_texture_rectangle) { 151 return texUnit->CurrentTex[TEXTURE_RECT_INDEX]; 152 } 153 break; 154 case GL_TEXTURE_1D_ARRAY_EXT: 155 if (_mesa_is_desktop_gl(ctx) 156 && (ctx->Extensions.MESA_texture_array || 157 ctx->Extensions.EXT_texture_array)) { 158 return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX]; 159 } 160 break; 161 case GL_TEXTURE_2D_ARRAY_EXT: 162 if ((_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) 163 && (ctx->Extensions.MESA_texture_array || 164 ctx->Extensions.EXT_texture_array)) { 165 return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX]; 166 } 167 break; 168 case GL_TEXTURE_EXTERNAL_OES: 169 if (_mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external) { 170 return texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX]; 171 } 172 break; 173 default: 174 ; 175 } 176 177 _mesa_error(ctx, GL_INVALID_ENUM, 178 "gl%sTexParameter(target)", get ? "Get" : ""); 179 return NULL; 180 } 181 182 183 /** 184 * Convert GL_RED/GREEN/BLUE/ALPHA/ZERO/ONE to SWIZZLE_X/Y/Z/W/ZERO/ONE. 185 * \return -1 if error. 186 */ 187 static GLint 188 comp_to_swizzle(GLenum comp) 189 { 190 switch (comp) { 191 case GL_RED: 192 return SWIZZLE_X; 193 case GL_GREEN: 194 return SWIZZLE_Y; 195 case GL_BLUE: 196 return SWIZZLE_Z; 197 case GL_ALPHA: 198 return SWIZZLE_W; 199 case GL_ZERO: 200 return SWIZZLE_ZERO; 201 case GL_ONE: 202 return SWIZZLE_ONE; 203 default: 204 return -1; 205 } 206 } 207 208 209 static void 210 set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz) 211 { 212 ASSERT(comp < 4); 213 ASSERT(swz <= SWIZZLE_NIL); 214 { 215 GLuint mask = 0x7 << (3 * comp); 216 GLuint s = (*swizzle & ~mask) | (swz << (3 * comp)); 217 *swizzle = s; 218 } 219 } 220 221 222 /** 223 * This is called just prior to changing any texture object state which 224 * will not effect texture completeness. 225 */ 226 static inline void 227 flush(struct gl_context *ctx) 228 { 229 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 230 } 231 232 233 /** 234 * This is called just prior to changing any texture object state which 235 * can effect texture completeness (texture base level, max level). 236 * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE 237 * state flag and then mark the texture object as 'incomplete' so that any 238 * per-texture derived state gets recomputed. 239 */ 240 static inline void 241 incomplete(struct gl_context *ctx, struct gl_texture_object *texObj) 242 { 243 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 244 _mesa_dirty_texobj(ctx, texObj, GL_TRUE); 245 } 246 247 248 /** 249 * Set an integer-valued texture parameter 250 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise 251 */ 252 static GLboolean 253 set_tex_parameteri(struct gl_context *ctx, 254 struct gl_texture_object *texObj, 255 GLenum pname, const GLint *params) 256 { 257 switch (pname) { 258 case GL_TEXTURE_MIN_FILTER: 259 if (texObj->Sampler.MinFilter == params[0]) 260 return GL_FALSE; 261 switch (params[0]) { 262 case GL_NEAREST: 263 case GL_LINEAR: 264 flush(ctx); 265 texObj->Sampler.MinFilter = params[0]; 266 return GL_TRUE; 267 case GL_NEAREST_MIPMAP_NEAREST: 268 case GL_LINEAR_MIPMAP_NEAREST: 269 case GL_NEAREST_MIPMAP_LINEAR: 270 case GL_LINEAR_MIPMAP_LINEAR: 271 if (texObj->Target != GL_TEXTURE_RECTANGLE_NV && 272 texObj->Target != GL_TEXTURE_EXTERNAL_OES) { 273 flush(ctx); 274 texObj->Sampler.MinFilter = params[0]; 275 return GL_TRUE; 276 } 277 /* fall-through */ 278 default: 279 goto invalid_param; 280 } 281 return GL_FALSE; 282 283 case GL_TEXTURE_MAG_FILTER: 284 if (texObj->Sampler.MagFilter == params[0]) 285 return GL_FALSE; 286 switch (params[0]) { 287 case GL_NEAREST: 288 case GL_LINEAR: 289 flush(ctx); /* does not effect completeness */ 290 texObj->Sampler.MagFilter = params[0]; 291 return GL_TRUE; 292 default: 293 goto invalid_param; 294 } 295 return GL_FALSE; 296 297 case GL_TEXTURE_WRAP_S: 298 if (texObj->Sampler.WrapS == params[0]) 299 return GL_FALSE; 300 if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { 301 flush(ctx); 302 texObj->Sampler.WrapS = params[0]; 303 return GL_TRUE; 304 } 305 return GL_FALSE; 306 307 case GL_TEXTURE_WRAP_T: 308 if (texObj->Sampler.WrapT == params[0]) 309 return GL_FALSE; 310 if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { 311 flush(ctx); 312 texObj->Sampler.WrapT = params[0]; 313 return GL_TRUE; 314 } 315 return GL_FALSE; 316 317 case GL_TEXTURE_WRAP_R: 318 if (texObj->Sampler.WrapR == params[0]) 319 return GL_FALSE; 320 if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { 321 flush(ctx); 322 texObj->Sampler.WrapR = params[0]; 323 return GL_TRUE; 324 } 325 return GL_FALSE; 326 327 case GL_TEXTURE_BASE_LEVEL: 328 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 329 goto invalid_pname; 330 331 if (texObj->BaseLevel == params[0]) 332 return GL_FALSE; 333 if (params[0] < 0 || 334 (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) { 335 _mesa_error(ctx, GL_INVALID_VALUE, 336 "glTexParameter(param=%d)", params[0]); 337 return GL_FALSE; 338 } 339 incomplete(ctx, texObj); 340 texObj->BaseLevel = params[0]; 341 return GL_TRUE; 342 343 case GL_TEXTURE_MAX_LEVEL: 344 if (texObj->MaxLevel == params[0]) 345 return GL_FALSE; 346 if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) { 347 _mesa_error(ctx, GL_INVALID_OPERATION, 348 "glTexParameter(param=%d)", params[0]); 349 return GL_FALSE; 350 } 351 incomplete(ctx, texObj); 352 texObj->MaxLevel = params[0]; 353 return GL_TRUE; 354 355 case GL_GENERATE_MIPMAP_SGIS: 356 if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES) 357 goto invalid_pname; 358 359 if (params[0] && texObj->Target == GL_TEXTURE_EXTERNAL_OES) 360 goto invalid_param; 361 if (texObj->GenerateMipmap != params[0]) { 362 /* no flush() */ 363 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE; 364 return GL_TRUE; 365 } 366 return GL_FALSE; 367 368 case GL_TEXTURE_COMPARE_MODE_ARB: 369 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow) 370 || _mesa_is_gles3(ctx)) { 371 if (texObj->Sampler.CompareMode == params[0]) 372 return GL_FALSE; 373 if (params[0] == GL_NONE || 374 params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) { 375 flush(ctx); 376 texObj->Sampler.CompareMode = params[0]; 377 return GL_TRUE; 378 } 379 goto invalid_param; 380 } 381 goto invalid_pname; 382 383 case GL_TEXTURE_COMPARE_FUNC_ARB: 384 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow) 385 || _mesa_is_gles3(ctx)) { 386 if (texObj->Sampler.CompareFunc == params[0]) 387 return GL_FALSE; 388 switch (params[0]) { 389 case GL_LEQUAL: 390 case GL_GEQUAL: 391 flush(ctx); 392 texObj->Sampler.CompareFunc = params[0]; 393 return GL_TRUE; 394 case GL_EQUAL: 395 case GL_NOTEQUAL: 396 case GL_LESS: 397 case GL_GREATER: 398 case GL_ALWAYS: 399 case GL_NEVER: 400 if (ctx->Extensions.EXT_shadow_funcs) { 401 flush(ctx); 402 texObj->Sampler.CompareFunc = params[0]; 403 return GL_TRUE; 404 } 405 /* fall-through */ 406 default: 407 goto invalid_param; 408 } 409 } 410 goto invalid_pname; 411 412 case GL_DEPTH_TEXTURE_MODE_ARB: 413 /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has never 414 * existed in OpenGL ES. 415 */ 416 if (ctx->API == API_OPENGL && ctx->Extensions.ARB_depth_texture) { 417 if (texObj->DepthMode == params[0]) 418 return GL_FALSE; 419 if (params[0] == GL_LUMINANCE || 420 params[0] == GL_INTENSITY || 421 params[0] == GL_ALPHA || 422 (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) { 423 flush(ctx); 424 texObj->DepthMode = params[0]; 425 return GL_TRUE; 426 } 427 goto invalid_param; 428 } 429 goto invalid_pname; 430 431 #if FEATURE_OES_draw_texture 432 case GL_TEXTURE_CROP_RECT_OES: 433 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture) 434 goto invalid_pname; 435 436 texObj->CropRect[0] = params[0]; 437 texObj->CropRect[1] = params[1]; 438 texObj->CropRect[2] = params[2]; 439 texObj->CropRect[3] = params[3]; 440 return GL_TRUE; 441 #endif 442 443 case GL_TEXTURE_SWIZZLE_R_EXT: 444 case GL_TEXTURE_SWIZZLE_G_EXT: 445 case GL_TEXTURE_SWIZZLE_B_EXT: 446 case GL_TEXTURE_SWIZZLE_A_EXT: 447 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_swizzle) 448 || _mesa_is_gles3(ctx)) { 449 const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT; 450 const GLint swz = comp_to_swizzle(params[0]); 451 if (swz < 0) { 452 _mesa_error(ctx, GL_INVALID_OPERATION, 453 "glTexParameter(swizzle 0x%x)", params[0]); 454 return GL_FALSE; 455 } 456 ASSERT(comp < 4); 457 458 flush(ctx); 459 texObj->Swizzle[comp] = params[0]; 460 set_swizzle_component(&texObj->_Swizzle, comp, swz); 461 return GL_TRUE; 462 } 463 goto invalid_pname; 464 465 case GL_TEXTURE_SWIZZLE_RGBA_EXT: 466 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_swizzle) 467 || _mesa_is_gles3(ctx)) { 468 GLuint comp; 469 flush(ctx); 470 for (comp = 0; comp < 4; comp++) { 471 const GLint swz = comp_to_swizzle(params[comp]); 472 if (swz >= 0) { 473 texObj->Swizzle[comp] = params[comp]; 474 set_swizzle_component(&texObj->_Swizzle, comp, swz); 475 } 476 else { 477 _mesa_error(ctx, GL_INVALID_OPERATION, 478 "glTexParameter(swizzle 0x%x)", params[comp]); 479 return GL_FALSE; 480 } 481 } 482 return GL_TRUE; 483 } 484 goto invalid_pname; 485 486 case GL_TEXTURE_SRGB_DECODE_EXT: 487 if (_mesa_is_desktop_gl(ctx) 488 && ctx->Extensions.EXT_texture_sRGB_decode) { 489 GLenum decode = params[0]; 490 if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) { 491 if (texObj->Sampler.sRGBDecode != decode) { 492 flush(ctx); 493 texObj->Sampler.sRGBDecode = decode; 494 } 495 return GL_TRUE; 496 } 497 } 498 goto invalid_pname; 499 500 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 501 if (_mesa_is_desktop_gl(ctx) 502 && ctx->Extensions.AMD_seamless_cubemap_per_texture) { 503 GLenum param = params[0]; 504 if (param != GL_TRUE && param != GL_FALSE) { 505 goto invalid_param; 506 } 507 if (param != texObj->Sampler.CubeMapSeamless) { 508 flush(ctx); 509 texObj->Sampler.CubeMapSeamless = param; 510 } 511 return GL_TRUE; 512 } 513 goto invalid_pname; 514 515 default: 516 goto invalid_pname; 517 } 518 519 invalid_pname: 520 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)", 521 _mesa_lookup_enum_by_nr(pname)); 522 return GL_FALSE; 523 524 invalid_param: 525 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)", 526 _mesa_lookup_enum_by_nr(params[0])); 527 return GL_FALSE; 528 } 529 530 531 /** 532 * Set a float-valued texture parameter 533 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise 534 */ 535 static GLboolean 536 set_tex_parameterf(struct gl_context *ctx, 537 struct gl_texture_object *texObj, 538 GLenum pname, const GLfloat *params) 539 { 540 switch (pname) { 541 case GL_TEXTURE_MIN_LOD: 542 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 543 goto invalid_pname; 544 545 if (texObj->Sampler.MinLod == params[0]) 546 return GL_FALSE; 547 flush(ctx); 548 texObj->Sampler.MinLod = params[0]; 549 return GL_TRUE; 550 551 case GL_TEXTURE_MAX_LOD: 552 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 553 goto invalid_pname; 554 555 if (texObj->Sampler.MaxLod == params[0]) 556 return GL_FALSE; 557 flush(ctx); 558 texObj->Sampler.MaxLod = params[0]; 559 return GL_TRUE; 560 561 case GL_TEXTURE_PRIORITY: 562 if (ctx->API != API_OPENGL) 563 goto invalid_pname; 564 565 flush(ctx); 566 texObj->Priority = CLAMP(params[0], 0.0F, 1.0F); 567 return GL_TRUE; 568 569 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 570 if (ctx->Extensions.EXT_texture_filter_anisotropic) { 571 if (texObj->Sampler.MaxAnisotropy == params[0]) 572 return GL_FALSE; 573 if (params[0] < 1.0) { 574 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); 575 return GL_FALSE; 576 } 577 flush(ctx); 578 /* clamp to max, that's what NVIDIA does */ 579 texObj->Sampler.MaxAnisotropy = MIN2(params[0], 580 ctx->Const.MaxTextureMaxAnisotropy); 581 return GL_TRUE; 582 } 583 else { 584 static GLuint count = 0; 585 if (count++ < 10) 586 goto invalid_pname; 587 } 588 return GL_FALSE; 589 590 case GL_TEXTURE_LOD_BIAS: 591 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias. 592 * It was removed in core-profile, and it has never existed in OpenGL 593 * ES. 594 */ 595 if (ctx->API != API_OPENGL) 596 goto invalid_pname; 597 598 if (texObj->Sampler.LodBias != params[0]) { 599 flush(ctx); 600 texObj->Sampler.LodBias = params[0]; 601 return GL_TRUE; 602 } 603 break; 604 605 case GL_TEXTURE_BORDER_COLOR: 606 if (!_mesa_is_desktop_gl(ctx)) 607 goto invalid_pname; 608 609 flush(ctx); 610 /* ARB_texture_float disables clamping */ 611 if (ctx->Extensions.ARB_texture_float) { 612 texObj->Sampler.BorderColor.f[RCOMP] = params[0]; 613 texObj->Sampler.BorderColor.f[GCOMP] = params[1]; 614 texObj->Sampler.BorderColor.f[BCOMP] = params[2]; 615 texObj->Sampler.BorderColor.f[ACOMP] = params[3]; 616 } else { 617 texObj->Sampler.BorderColor.f[RCOMP] = CLAMP(params[0], 0.0F, 1.0F); 618 texObj->Sampler.BorderColor.f[GCOMP] = CLAMP(params[1], 0.0F, 1.0F); 619 texObj->Sampler.BorderColor.f[BCOMP] = CLAMP(params[2], 0.0F, 1.0F); 620 texObj->Sampler.BorderColor.f[ACOMP] = CLAMP(params[3], 0.0F, 1.0F); 621 } 622 return GL_TRUE; 623 624 default: 625 goto invalid_pname; 626 } 627 return GL_FALSE; 628 629 invalid_pname: 630 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)", 631 _mesa_lookup_enum_by_nr(pname)); 632 return GL_FALSE; 633 } 634 635 636 void GLAPIENTRY 637 _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param) 638 { 639 GLboolean need_update; 640 struct gl_texture_object *texObj; 641 GET_CURRENT_CONTEXT(ctx); 642 ASSERT_OUTSIDE_BEGIN_END(ctx); 643 644 texObj = get_texobj(ctx, target, GL_FALSE); 645 if (!texObj) 646 return; 647 648 switch (pname) { 649 case GL_TEXTURE_MIN_FILTER: 650 case GL_TEXTURE_MAG_FILTER: 651 case GL_TEXTURE_WRAP_S: 652 case GL_TEXTURE_WRAP_T: 653 case GL_TEXTURE_WRAP_R: 654 case GL_TEXTURE_BASE_LEVEL: 655 case GL_TEXTURE_MAX_LEVEL: 656 case GL_GENERATE_MIPMAP_SGIS: 657 case GL_TEXTURE_COMPARE_MODE_ARB: 658 case GL_TEXTURE_COMPARE_FUNC_ARB: 659 case GL_DEPTH_TEXTURE_MODE_ARB: 660 case GL_TEXTURE_SRGB_DECODE_EXT: 661 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 662 { 663 /* convert float param to int */ 664 GLint p[4]; 665 p[0] = (GLint) param; 666 p[1] = p[2] = p[3] = 0; 667 need_update = set_tex_parameteri(ctx, texObj, pname, p); 668 } 669 break; 670 case GL_TEXTURE_SWIZZLE_R_EXT: 671 case GL_TEXTURE_SWIZZLE_G_EXT: 672 case GL_TEXTURE_SWIZZLE_B_EXT: 673 case GL_TEXTURE_SWIZZLE_A_EXT: 674 { 675 GLint p[4]; 676 p[0] = (GLint) param; 677 p[1] = p[2] = p[3] = 0; 678 need_update = set_tex_parameteri(ctx, texObj, pname, p); 679 } 680 break; 681 default: 682 { 683 /* this will generate an error if pname is illegal */ 684 GLfloat p[4]; 685 p[0] = param; 686 p[1] = p[2] = p[3] = 0.0F; 687 need_update = set_tex_parameterf(ctx, texObj, pname, p); 688 } 689 } 690 691 if (ctx->Driver.TexParameter && need_update) { 692 ctx->Driver.TexParameter(ctx, target, texObj, pname, ¶m); 693 } 694 } 695 696 697 void GLAPIENTRY 698 _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params) 699 { 700 GLboolean need_update; 701 struct gl_texture_object *texObj; 702 GET_CURRENT_CONTEXT(ctx); 703 ASSERT_OUTSIDE_BEGIN_END(ctx); 704 705 texObj = get_texobj(ctx, target, GL_FALSE); 706 if (!texObj) 707 return; 708 709 switch (pname) { 710 case GL_TEXTURE_MIN_FILTER: 711 case GL_TEXTURE_MAG_FILTER: 712 case GL_TEXTURE_WRAP_S: 713 case GL_TEXTURE_WRAP_T: 714 case GL_TEXTURE_WRAP_R: 715 case GL_TEXTURE_BASE_LEVEL: 716 case GL_TEXTURE_MAX_LEVEL: 717 case GL_GENERATE_MIPMAP_SGIS: 718 case GL_TEXTURE_COMPARE_MODE_ARB: 719 case GL_TEXTURE_COMPARE_FUNC_ARB: 720 case GL_DEPTH_TEXTURE_MODE_ARB: 721 case GL_TEXTURE_SRGB_DECODE_EXT: 722 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 723 { 724 /* convert float param to int */ 725 GLint p[4]; 726 p[0] = (GLint) params[0]; 727 p[1] = p[2] = p[3] = 0; 728 need_update = set_tex_parameteri(ctx, texObj, pname, p); 729 } 730 break; 731 732 #if FEATURE_OES_draw_texture 733 case GL_TEXTURE_CROP_RECT_OES: 734 { 735 /* convert float params to int */ 736 GLint iparams[4]; 737 iparams[0] = (GLint) params[0]; 738 iparams[1] = (GLint) params[1]; 739 iparams[2] = (GLint) params[2]; 740 iparams[3] = (GLint) params[3]; 741 need_update = set_tex_parameteri(ctx, texObj, pname, iparams); 742 } 743 break; 744 #endif 745 746 case GL_TEXTURE_SWIZZLE_R_EXT: 747 case GL_TEXTURE_SWIZZLE_G_EXT: 748 case GL_TEXTURE_SWIZZLE_B_EXT: 749 case GL_TEXTURE_SWIZZLE_A_EXT: 750 case GL_TEXTURE_SWIZZLE_RGBA_EXT: 751 { 752 GLint p[4] = {0, 0, 0, 0}; 753 p[0] = (GLint) params[0]; 754 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT) { 755 p[1] = (GLint) params[1]; 756 p[2] = (GLint) params[2]; 757 p[3] = (GLint) params[3]; 758 } 759 need_update = set_tex_parameteri(ctx, texObj, pname, p); 760 } 761 break; 762 default: 763 /* this will generate an error if pname is illegal */ 764 need_update = set_tex_parameterf(ctx, texObj, pname, params); 765 } 766 767 if (ctx->Driver.TexParameter && need_update) { 768 ctx->Driver.TexParameter(ctx, target, texObj, pname, params); 769 } 770 } 771 772 773 void GLAPIENTRY 774 _mesa_TexParameteri(GLenum target, GLenum pname, GLint param) 775 { 776 GLboolean need_update; 777 struct gl_texture_object *texObj; 778 GET_CURRENT_CONTEXT(ctx); 779 ASSERT_OUTSIDE_BEGIN_END(ctx); 780 781 texObj = get_texobj(ctx, target, GL_FALSE); 782 if (!texObj) 783 return; 784 785 switch (pname) { 786 case GL_TEXTURE_MIN_LOD: 787 case GL_TEXTURE_MAX_LOD: 788 case GL_TEXTURE_PRIORITY: 789 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 790 case GL_TEXTURE_LOD_BIAS: 791 case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: 792 { 793 GLfloat fparam[4]; 794 fparam[0] = (GLfloat) param; 795 fparam[1] = fparam[2] = fparam[3] = 0.0F; 796 /* convert int param to float */ 797 need_update = set_tex_parameterf(ctx, texObj, pname, fparam); 798 } 799 break; 800 default: 801 /* this will generate an error if pname is illegal */ 802 { 803 GLint iparam[4]; 804 iparam[0] = param; 805 iparam[1] = iparam[2] = iparam[3] = 0; 806 need_update = set_tex_parameteri(ctx, texObj, pname, iparam); 807 } 808 } 809 810 if (ctx->Driver.TexParameter && need_update) { 811 GLfloat fparam = (GLfloat) param; 812 ctx->Driver.TexParameter(ctx, target, texObj, pname, &fparam); 813 } 814 } 815 816 817 void GLAPIENTRY 818 _mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params) 819 { 820 GLboolean need_update; 821 struct gl_texture_object *texObj; 822 GET_CURRENT_CONTEXT(ctx); 823 ASSERT_OUTSIDE_BEGIN_END(ctx); 824 825 texObj = get_texobj(ctx, target, GL_FALSE); 826 if (!texObj) 827 return; 828 829 switch (pname) { 830 case GL_TEXTURE_BORDER_COLOR: 831 { 832 /* convert int params to float */ 833 GLfloat fparams[4]; 834 fparams[0] = INT_TO_FLOAT(params[0]); 835 fparams[1] = INT_TO_FLOAT(params[1]); 836 fparams[2] = INT_TO_FLOAT(params[2]); 837 fparams[3] = INT_TO_FLOAT(params[3]); 838 need_update = set_tex_parameterf(ctx, texObj, pname, fparams); 839 } 840 break; 841 case GL_TEXTURE_MIN_LOD: 842 case GL_TEXTURE_MAX_LOD: 843 case GL_TEXTURE_PRIORITY: 844 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 845 case GL_TEXTURE_LOD_BIAS: 846 case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: 847 { 848 /* convert int param to float */ 849 GLfloat fparams[4]; 850 fparams[0] = (GLfloat) params[0]; 851 fparams[1] = fparams[2] = fparams[3] = 0.0F; 852 need_update = set_tex_parameterf(ctx, texObj, pname, fparams); 853 } 854 break; 855 default: 856 /* this will generate an error if pname is illegal */ 857 need_update = set_tex_parameteri(ctx, texObj, pname, params); 858 } 859 860 if (ctx->Driver.TexParameter && need_update) { 861 GLfloat fparams[4]; 862 fparams[0] = INT_TO_FLOAT(params[0]); 863 if (pname == GL_TEXTURE_BORDER_COLOR || 864 pname == GL_TEXTURE_CROP_RECT_OES) { 865 fparams[1] = INT_TO_FLOAT(params[1]); 866 fparams[2] = INT_TO_FLOAT(params[2]); 867 fparams[3] = INT_TO_FLOAT(params[3]); 868 } 869 ctx->Driver.TexParameter(ctx, target, texObj, pname, fparams); 870 } 871 } 872 873 874 /** 875 * Set tex parameter to integer value(s). Primarily intended to set 876 * integer-valued texture border color (for integer-valued textures). 877 * New in GL 3.0. 878 */ 879 void GLAPIENTRY 880 _mesa_TexParameterIiv(GLenum target, GLenum pname, const GLint *params) 881 { 882 struct gl_texture_object *texObj; 883 GET_CURRENT_CONTEXT(ctx); 884 ASSERT_OUTSIDE_BEGIN_END(ctx); 885 886 texObj = get_texobj(ctx, target, GL_FALSE); 887 if (!texObj) 888 return; 889 890 switch (pname) { 891 case GL_TEXTURE_BORDER_COLOR: 892 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 893 /* set the integer-valued border color */ 894 COPY_4V(texObj->Sampler.BorderColor.i, params); 895 break; 896 default: 897 _mesa_TexParameteriv(target, pname, params); 898 break; 899 } 900 /* XXX no driver hook for TexParameterIiv() yet */ 901 } 902 903 904 /** 905 * Set tex parameter to unsigned integer value(s). Primarily intended to set 906 * uint-valued texture border color (for integer-valued textures). 907 * New in GL 3.0 908 */ 909 void GLAPIENTRY 910 _mesa_TexParameterIuiv(GLenum target, GLenum pname, const GLuint *params) 911 { 912 struct gl_texture_object *texObj; 913 GET_CURRENT_CONTEXT(ctx); 914 ASSERT_OUTSIDE_BEGIN_END(ctx); 915 916 texObj = get_texobj(ctx, target, GL_FALSE); 917 if (!texObj) 918 return; 919 920 switch (pname) { 921 case GL_TEXTURE_BORDER_COLOR: 922 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 923 /* set the unsigned integer-valued border color */ 924 COPY_4V(texObj->Sampler.BorderColor.ui, params); 925 break; 926 default: 927 _mesa_TexParameteriv(target, pname, (const GLint *) params); 928 break; 929 } 930 /* XXX no driver hook for TexParameterIuiv() yet */ 931 } 932 933 934 static GLboolean 935 legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target) 936 { 937 switch (target) { 938 case GL_TEXTURE_1D: 939 case GL_PROXY_TEXTURE_1D: 940 case GL_TEXTURE_2D: 941 case GL_PROXY_TEXTURE_2D: 942 case GL_TEXTURE_3D: 943 case GL_PROXY_TEXTURE_3D: 944 return GL_TRUE; 945 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 946 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 947 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 948 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 949 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 950 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 951 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 952 return ctx->Extensions.ARB_texture_cube_map; 953 case GL_TEXTURE_RECTANGLE_NV: 954 case GL_PROXY_TEXTURE_RECTANGLE_NV: 955 return ctx->Extensions.NV_texture_rectangle; 956 case GL_TEXTURE_1D_ARRAY_EXT: 957 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 958 case GL_TEXTURE_2D_ARRAY_EXT: 959 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 960 return (ctx->Extensions.MESA_texture_array || 961 ctx->Extensions.EXT_texture_array); 962 case GL_TEXTURE_BUFFER: 963 /* GetTexLevelParameter accepts GL_TEXTURE_BUFFER in GL 3.1+ contexts, 964 * but not in earlier versions that expose ARB_texture_buffer_object. 965 * 966 * From the ARB_texture_buffer_object spec: 967 * "(7) Do buffer textures support texture parameters (TexParameter) or 968 * queries (GetTexParameter, GetTexLevelParameter, GetTexImage)? 969 * 970 * RESOLVED: No. [...] Note that the spec edits above don't add 971 * explicit error language for any of these cases. That is because 972 * each of the functions enumerate the set of valid <target> 973 * parameters. Not editing the spec to allow TEXTURE_BUFFER_ARB in 974 * these cases means that target is not legal, and an INVALID_ENUM 975 * error should be generated." 976 * 977 * From the OpenGL 3.1 spec: 978 * "target may also be TEXTURE_BUFFER, indicating the texture buffer." 979 */ 980 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31; 981 default: 982 return GL_FALSE; 983 } 984 } 985 986 987 static void 988 get_tex_level_parameter_image(struct gl_context *ctx, 989 const struct gl_texture_object *texObj, 990 GLenum target, GLint level, 991 GLenum pname, GLint *params) 992 { 993 const struct gl_texture_image *img = NULL; 994 gl_format texFormat; 995 996 img = _mesa_select_tex_image(ctx, texObj, target, level); 997 if (!img || img->TexFormat == MESA_FORMAT_NONE) { 998 /* undefined texture image */ 999 if (pname == GL_TEXTURE_COMPONENTS) 1000 *params = 1; 1001 else 1002 *params = 0; 1003 return; 1004 } 1005 1006 texFormat = img->TexFormat; 1007 1008 switch (pname) { 1009 case GL_TEXTURE_WIDTH: 1010 *params = img->Width; 1011 break; 1012 case GL_TEXTURE_HEIGHT: 1013 *params = img->Height; 1014 break; 1015 case GL_TEXTURE_DEPTH: 1016 *params = img->Depth; 1017 break; 1018 case GL_TEXTURE_INTERNAL_FORMAT: 1019 if (_mesa_is_format_compressed(texFormat)) { 1020 /* need to return the actual compressed format */ 1021 *params = _mesa_compressed_format_to_glenum(ctx, texFormat); 1022 } 1023 else { 1024 /* If the true internal format is not compressed but the user 1025 * requested a generic compressed format, we have to return the 1026 * generic base format that matches. 1027 * 1028 * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec: 1029 * 1030 * "If no specific compressed format is available, 1031 * internalformat is instead replaced by the corresponding base 1032 * internal format." 1033 * 1034 * Otherwise just return the user's requested internal format 1035 */ 1036 const GLenum f = 1037 _mesa_gl_compressed_format_base_format(img->InternalFormat); 1038 1039 *params = (f != 0) ? f : img->InternalFormat; 1040 } 1041 break; 1042 case GL_TEXTURE_BORDER: 1043 *params = img->Border; 1044 break; 1045 case GL_TEXTURE_RED_SIZE: 1046 case GL_TEXTURE_GREEN_SIZE: 1047 case GL_TEXTURE_BLUE_SIZE: 1048 case GL_TEXTURE_ALPHA_SIZE: 1049 if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) 1050 *params = _mesa_get_format_bits(texFormat, pname); 1051 else 1052 *params = 0; 1053 break; 1054 case GL_TEXTURE_INTENSITY_SIZE: 1055 case GL_TEXTURE_LUMINANCE_SIZE: 1056 if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) { 1057 *params = _mesa_get_format_bits(texFormat, pname); 1058 if (*params == 0) { 1059 /* intensity or luminance is probably stored as RGB[A] */ 1060 *params = MIN2(_mesa_get_format_bits(texFormat, 1061 GL_TEXTURE_RED_SIZE), 1062 _mesa_get_format_bits(texFormat, 1063 GL_TEXTURE_GREEN_SIZE)); 1064 } 1065 } 1066 else { 1067 *params = 0; 1068 } 1069 break; 1070 case GL_TEXTURE_DEPTH_SIZE_ARB: 1071 if (!ctx->Extensions.ARB_depth_texture) 1072 goto invalid_pname; 1073 *params = _mesa_get_format_bits(texFormat, pname); 1074 break; 1075 case GL_TEXTURE_STENCIL_SIZE_EXT: 1076 if (!ctx->Extensions.EXT_packed_depth_stencil && 1077 !ctx->Extensions.ARB_framebuffer_object) 1078 goto invalid_pname; 1079 *params = _mesa_get_format_bits(texFormat, pname); 1080 break; 1081 case GL_TEXTURE_SHARED_SIZE: 1082 if (ctx->Version < 30 && 1083 !ctx->Extensions.EXT_texture_shared_exponent) 1084 goto invalid_pname; 1085 *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0; 1086 break; 1087 1088 /* GL_ARB_texture_compression */ 1089 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: 1090 if (_mesa_is_format_compressed(texFormat) && 1091 !_mesa_is_proxy_texture(target)) { 1092 *params = _mesa_format_image_size(texFormat, img->Width, 1093 img->Height, img->Depth); 1094 } 1095 else { 1096 _mesa_error(ctx, GL_INVALID_OPERATION, 1097 "glGetTexLevelParameter[if]v(pname)"); 1098 } 1099 break; 1100 case GL_TEXTURE_COMPRESSED: 1101 *params = (GLint) _mesa_is_format_compressed(texFormat); 1102 break; 1103 1104 /* GL_ARB_texture_float */ 1105 case GL_TEXTURE_RED_TYPE_ARB: 1106 case GL_TEXTURE_GREEN_TYPE_ARB: 1107 case GL_TEXTURE_BLUE_TYPE_ARB: 1108 case GL_TEXTURE_ALPHA_TYPE_ARB: 1109 case GL_TEXTURE_LUMINANCE_TYPE_ARB: 1110 case GL_TEXTURE_INTENSITY_TYPE_ARB: 1111 case GL_TEXTURE_DEPTH_TYPE_ARB: 1112 if (!ctx->Extensions.ARB_texture_float) 1113 goto invalid_pname; 1114 if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) 1115 *params = _mesa_get_format_datatype(texFormat); 1116 else 1117 *params = GL_NONE; 1118 break; 1119 1120 default: 1121 goto invalid_pname; 1122 } 1123 1124 /* no error if we get here */ 1125 return; 1126 1127 invalid_pname: 1128 _mesa_error(ctx, GL_INVALID_ENUM, 1129 "glGetTexLevelParameter[if]v(pname=%s)", 1130 _mesa_lookup_enum_by_nr(pname)); 1131 } 1132 1133 1134 static void 1135 get_tex_level_parameter_buffer(struct gl_context *ctx, 1136 const struct gl_texture_object *texObj, 1137 GLenum pname, GLint *params) 1138 { 1139 const struct gl_buffer_object *bo = texObj->BufferObject; 1140 gl_format texFormat = texObj->_BufferObjectFormat; 1141 GLenum internalFormat = texObj->BufferObjectFormat; 1142 GLenum baseFormat = _mesa_get_format_base_format(texFormat); 1143 1144 if (!bo) { 1145 /* undefined texture buffer object */ 1146 *params = pname == GL_TEXTURE_COMPONENTS ? 1 : 0; 1147 return; 1148 } 1149 1150 switch (pname) { 1151 case GL_TEXTURE_BUFFER_DATA_STORE_BINDING: 1152 *params = bo->Name; 1153 break; 1154 case GL_TEXTURE_WIDTH: 1155 *params = bo->Size; 1156 break; 1157 case GL_TEXTURE_HEIGHT: 1158 case GL_TEXTURE_DEPTH: 1159 case GL_TEXTURE_BORDER: 1160 case GL_TEXTURE_SHARED_SIZE: 1161 case GL_TEXTURE_COMPRESSED: 1162 *params = 0; 1163 break; 1164 case GL_TEXTURE_INTERNAL_FORMAT: 1165 *params = internalFormat; 1166 break; 1167 case GL_TEXTURE_RED_SIZE: 1168 case GL_TEXTURE_GREEN_SIZE: 1169 case GL_TEXTURE_BLUE_SIZE: 1170 case GL_TEXTURE_ALPHA_SIZE: 1171 if (_mesa_base_format_has_channel(baseFormat, pname)) 1172 *params = _mesa_get_format_bits(texFormat, pname); 1173 else 1174 *params = 0; 1175 break; 1176 case GL_TEXTURE_INTENSITY_SIZE: 1177 case GL_TEXTURE_LUMINANCE_SIZE: 1178 if (_mesa_base_format_has_channel(baseFormat, pname)) { 1179 *params = _mesa_get_format_bits(texFormat, pname); 1180 if (*params == 0) { 1181 /* intensity or luminance is probably stored as RGB[A] */ 1182 *params = MIN2(_mesa_get_format_bits(texFormat, 1183 GL_TEXTURE_RED_SIZE), 1184 _mesa_get_format_bits(texFormat, 1185 GL_TEXTURE_GREEN_SIZE)); 1186 } 1187 } else { 1188 *params = 0; 1189 } 1190 break; 1191 case GL_TEXTURE_DEPTH_SIZE_ARB: 1192 case GL_TEXTURE_STENCIL_SIZE_EXT: 1193 *params = _mesa_get_format_bits(texFormat, pname); 1194 break; 1195 1196 /* GL_ARB_texture_compression */ 1197 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: 1198 /* Always illegal for GL_TEXTURE_BUFFER */ 1199 _mesa_error(ctx, GL_INVALID_OPERATION, 1200 "glGetTexLevelParameter[if]v(pname)"); 1201 break; 1202 1203 /* GL_ARB_texture_float */ 1204 case GL_TEXTURE_RED_TYPE_ARB: 1205 case GL_TEXTURE_GREEN_TYPE_ARB: 1206 case GL_TEXTURE_BLUE_TYPE_ARB: 1207 case GL_TEXTURE_ALPHA_TYPE_ARB: 1208 case GL_TEXTURE_LUMINANCE_TYPE_ARB: 1209 case GL_TEXTURE_INTENSITY_TYPE_ARB: 1210 case GL_TEXTURE_DEPTH_TYPE_ARB: 1211 if (!ctx->Extensions.ARB_texture_float) 1212 goto invalid_pname; 1213 if (_mesa_base_format_has_channel(baseFormat, pname)) 1214 *params = _mesa_get_format_datatype(texFormat); 1215 else 1216 *params = GL_NONE; 1217 break; 1218 1219 default: 1220 goto invalid_pname; 1221 } 1222 1223 /* no error if we get here */ 1224 return; 1225 1226 invalid_pname: 1227 _mesa_error(ctx, GL_INVALID_ENUM, 1228 "glGetTexLevelParameter[if]v(pname=%s)", 1229 _mesa_lookup_enum_by_nr(pname)); 1230 } 1231 1232 1233 void GLAPIENTRY 1234 _mesa_GetTexLevelParameterfv( GLenum target, GLint level, 1235 GLenum pname, GLfloat *params ) 1236 { 1237 GLint iparam; 1238 _mesa_GetTexLevelParameteriv( target, level, pname, &iparam ); 1239 *params = (GLfloat) iparam; 1240 } 1241 1242 1243 void GLAPIENTRY 1244 _mesa_GetTexLevelParameteriv( GLenum target, GLint level, 1245 GLenum pname, GLint *params ) 1246 { 1247 const struct gl_texture_unit *texUnit; 1248 struct gl_texture_object *texObj; 1249 GLint maxLevels; 1250 GET_CURRENT_CONTEXT(ctx); 1251 ASSERT_OUTSIDE_BEGIN_END(ctx); 1252 1253 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) { 1254 _mesa_error(ctx, GL_INVALID_OPERATION, 1255 "glGetTexLevelParameteriv(current unit)"); 1256 return; 1257 } 1258 1259 texUnit = _mesa_get_current_tex_unit(ctx); 1260 1261 if (!legal_get_tex_level_parameter_target(ctx, target)) { 1262 _mesa_error(ctx, GL_INVALID_ENUM, 1263 "glGetTexLevelParameter[if]v(target=0x%x)", target); 1264 return; 1265 } 1266 1267 maxLevels = _mesa_max_texture_levels(ctx, target); 1268 assert(maxLevels != 0); 1269 1270 if (level < 0 || level >= maxLevels) { 1271 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" ); 1272 return; 1273 } 1274 1275 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1276 1277 if (target == GL_TEXTURE_BUFFER) 1278 get_tex_level_parameter_buffer(ctx, texObj, pname, params); 1279 else 1280 get_tex_level_parameter_image(ctx, texObj, target, level, pname, params); 1281 } 1282 1283 1284 void GLAPIENTRY 1285 _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) 1286 { 1287 struct gl_texture_object *obj; 1288 GET_CURRENT_CONTEXT(ctx); 1289 ASSERT_OUTSIDE_BEGIN_END(ctx); 1290 1291 obj = get_texobj(ctx, target, GL_TRUE); 1292 if (!obj) 1293 return; 1294 1295 _mesa_lock_texture(ctx, obj); 1296 switch (pname) { 1297 case GL_TEXTURE_MAG_FILTER: 1298 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter); 1299 break; 1300 case GL_TEXTURE_MIN_FILTER: 1301 *params = ENUM_TO_FLOAT(obj->Sampler.MinFilter); 1302 break; 1303 case GL_TEXTURE_WRAP_S: 1304 *params = ENUM_TO_FLOAT(obj->Sampler.WrapS); 1305 break; 1306 case GL_TEXTURE_WRAP_T: 1307 *params = ENUM_TO_FLOAT(obj->Sampler.WrapT); 1308 break; 1309 case GL_TEXTURE_WRAP_R: 1310 *params = ENUM_TO_FLOAT(obj->Sampler.WrapR); 1311 break; 1312 case GL_TEXTURE_BORDER_COLOR: 1313 if (!_mesa_is_desktop_gl(ctx)) 1314 goto invalid_pname; 1315 1316 if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) 1317 _mesa_update_state_locked(ctx); 1318 if (ctx->Color._ClampFragmentColor) { 1319 params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F); 1320 params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F); 1321 params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F); 1322 params[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F); 1323 } 1324 else { 1325 params[0] = obj->Sampler.BorderColor.f[0]; 1326 params[1] = obj->Sampler.BorderColor.f[1]; 1327 params[2] = obj->Sampler.BorderColor.f[2]; 1328 params[3] = obj->Sampler.BorderColor.f[3]; 1329 } 1330 break; 1331 case GL_TEXTURE_RESIDENT: 1332 if (ctx->API != API_OPENGL) 1333 goto invalid_pname; 1334 1335 *params = 1.0F; 1336 break; 1337 case GL_TEXTURE_PRIORITY: 1338 if (ctx->API != API_OPENGL) 1339 goto invalid_pname; 1340 1341 *params = obj->Priority; 1342 break; 1343 case GL_TEXTURE_MIN_LOD: 1344 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 1345 goto invalid_pname; 1346 1347 *params = obj->Sampler.MinLod; 1348 break; 1349 case GL_TEXTURE_MAX_LOD: 1350 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 1351 goto invalid_pname; 1352 1353 *params = obj->Sampler.MaxLod; 1354 break; 1355 case GL_TEXTURE_BASE_LEVEL: 1356 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 1357 goto invalid_pname; 1358 1359 *params = (GLfloat) obj->BaseLevel; 1360 break; 1361 case GL_TEXTURE_MAX_LEVEL: 1362 *params = (GLfloat) obj->MaxLevel; 1363 break; 1364 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1365 if (!ctx->Extensions.EXT_texture_filter_anisotropic) 1366 goto invalid_pname; 1367 *params = obj->Sampler.MaxAnisotropy; 1368 break; 1369 case GL_GENERATE_MIPMAP_SGIS: 1370 if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES) 1371 goto invalid_pname; 1372 1373 *params = (GLfloat) obj->GenerateMipmap; 1374 break; 1375 case GL_TEXTURE_COMPARE_MODE_ARB: 1376 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow) 1377 && !_mesa_is_gles3(ctx)) 1378 goto invalid_pname; 1379 *params = (GLfloat) obj->Sampler.CompareMode; 1380 break; 1381 case GL_TEXTURE_COMPARE_FUNC_ARB: 1382 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow) 1383 && !_mesa_is_gles3(ctx)) 1384 goto invalid_pname; 1385 *params = (GLfloat) obj->Sampler.CompareFunc; 1386 break; 1387 case GL_DEPTH_TEXTURE_MODE_ARB: 1388 /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has 1389 * never existed in OpenGL ES. 1390 */ 1391 if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_depth_texture) 1392 goto invalid_pname; 1393 *params = (GLfloat) obj->DepthMode; 1394 break; 1395 case GL_TEXTURE_LOD_BIAS: 1396 if (ctx->API != API_OPENGL) 1397 goto invalid_pname; 1398 1399 *params = obj->Sampler.LodBias; 1400 break; 1401 #if FEATURE_OES_draw_texture 1402 case GL_TEXTURE_CROP_RECT_OES: 1403 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture) 1404 goto invalid_pname; 1405 1406 params[0] = obj->CropRect[0]; 1407 params[1] = obj->CropRect[1]; 1408 params[2] = obj->CropRect[2]; 1409 params[3] = obj->CropRect[3]; 1410 break; 1411 #endif 1412 1413 case GL_TEXTURE_SWIZZLE_R_EXT: 1414 case GL_TEXTURE_SWIZZLE_G_EXT: 1415 case GL_TEXTURE_SWIZZLE_B_EXT: 1416 case GL_TEXTURE_SWIZZLE_A_EXT: 1417 if ((!_mesa_is_desktop_gl(ctx) 1418 || !ctx->Extensions.EXT_texture_swizzle) 1419 && !_mesa_is_gles3(ctx)) 1420 goto invalid_pname; 1421 *params = (GLfloat) obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT]; 1422 break; 1423 1424 case GL_TEXTURE_SWIZZLE_RGBA_EXT: 1425 if ((!_mesa_is_desktop_gl(ctx) 1426 || !ctx->Extensions.EXT_texture_swizzle) 1427 && !_mesa_is_gles3(ctx)) { 1428 goto invalid_pname; 1429 } 1430 else { 1431 GLuint comp; 1432 for (comp = 0; comp < 4; comp++) { 1433 params[comp] = (GLfloat) obj->Swizzle[comp]; 1434 } 1435 } 1436 break; 1437 1438 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1439 if (!_mesa_is_desktop_gl(ctx) 1440 || !ctx->Extensions.AMD_seamless_cubemap_per_texture) 1441 goto invalid_pname; 1442 *params = (GLfloat) obj->Sampler.CubeMapSeamless; 1443 break; 1444 1445 case GL_TEXTURE_IMMUTABLE_FORMAT: 1446 if (!ctx->Extensions.ARB_texture_storage) 1447 goto invalid_pname; 1448 *params = (GLfloat) obj->Immutable; 1449 break; 1450 1451 case GL_TEXTURE_SRGB_DECODE_EXT: 1452 if (!ctx->Extensions.EXT_texture_sRGB_decode) 1453 goto invalid_pname; 1454 *params = (GLfloat) obj->Sampler.sRGBDecode; 1455 break; 1456 1457 default: 1458 goto invalid_pname; 1459 } 1460 1461 /* no error if we get here */ 1462 _mesa_unlock_texture(ctx, obj); 1463 return; 1464 1465 invalid_pname: 1466 _mesa_unlock_texture(ctx, obj); 1467 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname); 1468 } 1469 1470 1471 void GLAPIENTRY 1472 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ) 1473 { 1474 struct gl_texture_object *obj; 1475 GET_CURRENT_CONTEXT(ctx); 1476 ASSERT_OUTSIDE_BEGIN_END(ctx); 1477 1478 obj = get_texobj(ctx, target, GL_TRUE); 1479 if (!obj) 1480 return; 1481 1482 _mesa_lock_texture(ctx, obj); 1483 switch (pname) { 1484 case GL_TEXTURE_MAG_FILTER: 1485 *params = (GLint) obj->Sampler.MagFilter; 1486 break; 1487 case GL_TEXTURE_MIN_FILTER: 1488 *params = (GLint) obj->Sampler.MinFilter; 1489 break; 1490 case GL_TEXTURE_WRAP_S: 1491 *params = (GLint) obj->Sampler.WrapS; 1492 break; 1493 case GL_TEXTURE_WRAP_T: 1494 *params = (GLint) obj->Sampler.WrapT; 1495 break; 1496 case GL_TEXTURE_WRAP_R: 1497 *params = (GLint) obj->Sampler.WrapR; 1498 break; 1499 case GL_TEXTURE_BORDER_COLOR: 1500 if (!_mesa_is_desktop_gl(ctx)) 1501 goto invalid_pname; 1502 1503 { 1504 GLfloat b[4]; 1505 b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F); 1506 b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F); 1507 b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F); 1508 b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F); 1509 params[0] = FLOAT_TO_INT(b[0]); 1510 params[1] = FLOAT_TO_INT(b[1]); 1511 params[2] = FLOAT_TO_INT(b[2]); 1512 params[3] = FLOAT_TO_INT(b[3]); 1513 } 1514 break; 1515 case GL_TEXTURE_RESIDENT: 1516 if (ctx->API != API_OPENGL) 1517 goto invalid_pname; 1518 1519 *params = 1; 1520 break; 1521 case GL_TEXTURE_PRIORITY: 1522 if (ctx->API != API_OPENGL) 1523 goto invalid_pname; 1524 1525 *params = FLOAT_TO_INT(obj->Priority); 1526 break; 1527 case GL_TEXTURE_MIN_LOD: 1528 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 1529 goto invalid_pname; 1530 1531 *params = (GLint) obj->Sampler.MinLod; 1532 break; 1533 case GL_TEXTURE_MAX_LOD: 1534 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 1535 goto invalid_pname; 1536 1537 *params = (GLint) obj->Sampler.MaxLod; 1538 break; 1539 case GL_TEXTURE_BASE_LEVEL: 1540 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 1541 goto invalid_pname; 1542 1543 *params = obj->BaseLevel; 1544 break; 1545 case GL_TEXTURE_MAX_LEVEL: 1546 *params = obj->MaxLevel; 1547 break; 1548 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1549 if (!ctx->Extensions.EXT_texture_filter_anisotropic) 1550 goto invalid_pname; 1551 *params = (GLint) obj->Sampler.MaxAnisotropy; 1552 break; 1553 case GL_GENERATE_MIPMAP_SGIS: 1554 if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES) 1555 goto invalid_pname; 1556 1557 *params = (GLint) obj->GenerateMipmap; 1558 break; 1559 case GL_TEXTURE_COMPARE_MODE_ARB: 1560 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow) 1561 && !_mesa_is_gles3(ctx)) 1562 goto invalid_pname; 1563 *params = (GLint) obj->Sampler.CompareMode; 1564 break; 1565 case GL_TEXTURE_COMPARE_FUNC_ARB: 1566 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow) 1567 && !_mesa_is_gles3(ctx)) 1568 goto invalid_pname; 1569 *params = (GLint) obj->Sampler.CompareFunc; 1570 break; 1571 case GL_DEPTH_TEXTURE_MODE_ARB: 1572 if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_depth_texture) 1573 goto invalid_pname; 1574 *params = (GLint) obj->DepthMode; 1575 break; 1576 case GL_TEXTURE_LOD_BIAS: 1577 if (ctx->API != API_OPENGL) 1578 goto invalid_pname; 1579 1580 *params = (GLint) obj->Sampler.LodBias; 1581 break; 1582 #if FEATURE_OES_draw_texture 1583 case GL_TEXTURE_CROP_RECT_OES: 1584 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture) 1585 goto invalid_pname; 1586 1587 params[0] = obj->CropRect[0]; 1588 params[1] = obj->CropRect[1]; 1589 params[2] = obj->CropRect[2]; 1590 params[3] = obj->CropRect[3]; 1591 break; 1592 #endif 1593 case GL_TEXTURE_SWIZZLE_R_EXT: 1594 case GL_TEXTURE_SWIZZLE_G_EXT: 1595 case GL_TEXTURE_SWIZZLE_B_EXT: 1596 case GL_TEXTURE_SWIZZLE_A_EXT: 1597 if ((!_mesa_is_desktop_gl(ctx) 1598 || !ctx->Extensions.EXT_texture_swizzle) 1599 && !_mesa_is_gles3(ctx)) 1600 goto invalid_pname; 1601 *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT]; 1602 break; 1603 1604 case GL_TEXTURE_SWIZZLE_RGBA_EXT: 1605 if ((!_mesa_is_desktop_gl(ctx) 1606 || !ctx->Extensions.EXT_texture_swizzle) 1607 && !_mesa_is_gles3(ctx)) 1608 goto invalid_pname; 1609 COPY_4V(params, obj->Swizzle); 1610 break; 1611 1612 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1613 if (!_mesa_is_desktop_gl(ctx) 1614 || !ctx->Extensions.AMD_seamless_cubemap_per_texture) 1615 goto invalid_pname; 1616 *params = (GLint) obj->Sampler.CubeMapSeamless; 1617 break; 1618 1619 case GL_TEXTURE_IMMUTABLE_FORMAT: 1620 if (!ctx->Extensions.ARB_texture_storage) 1621 goto invalid_pname; 1622 *params = (GLint) obj->Immutable; 1623 break; 1624 1625 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: 1626 if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external) 1627 goto invalid_pname; 1628 *params = obj->RequiredTextureImageUnits; 1629 break; 1630 1631 case GL_TEXTURE_SRGB_DECODE_EXT: 1632 if (!ctx->Extensions.EXT_texture_sRGB_decode) 1633 goto invalid_pname; 1634 *params = obj->Sampler.sRGBDecode; 1635 break; 1636 1637 default: 1638 goto invalid_pname; 1639 } 1640 1641 /* no error if we get here */ 1642 _mesa_unlock_texture(ctx, obj); 1643 return; 1644 1645 invalid_pname: 1646 _mesa_unlock_texture(ctx, obj); 1647 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname); 1648 } 1649 1650 1651 /** New in GL 3.0 */ 1652 void GLAPIENTRY 1653 _mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params) 1654 { 1655 struct gl_texture_object *texObj; 1656 GET_CURRENT_CONTEXT(ctx); 1657 ASSERT_OUTSIDE_BEGIN_END(ctx); 1658 1659 texObj = get_texobj(ctx, target, GL_TRUE); 1660 if (!texObj) 1661 return; 1662 1663 switch (pname) { 1664 case GL_TEXTURE_BORDER_COLOR: 1665 COPY_4V(params, texObj->Sampler.BorderColor.i); 1666 break; 1667 default: 1668 _mesa_GetTexParameteriv(target, pname, params); 1669 } 1670 } 1671 1672 1673 /** New in GL 3.0 */ 1674 void GLAPIENTRY 1675 _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params) 1676 { 1677 struct gl_texture_object *texObj; 1678 GET_CURRENT_CONTEXT(ctx); 1679 ASSERT_OUTSIDE_BEGIN_END(ctx); 1680 1681 texObj = get_texobj(ctx, target, GL_TRUE); 1682 if (!texObj) 1683 return; 1684 1685 switch (pname) { 1686 case GL_TEXTURE_BORDER_COLOR: 1687 COPY_4V(params, texObj->Sampler.BorderColor.i); 1688 break; 1689 default: 1690 { 1691 GLint ip[4]; 1692 _mesa_GetTexParameteriv(target, pname, ip); 1693 params[0] = ip[0]; 1694 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT || 1695 pname == GL_TEXTURE_CROP_RECT_OES) { 1696 params[1] = ip[1]; 1697 params[2] = ip[2]; 1698 params[3] = ip[3]; 1699 } 1700 } 1701 } 1702 } 1703