1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2011 VMware, Inc. All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26 /** 27 * \file samplerobj.c 28 * \brief Functions for the GL_ARB_sampler_objects extension. 29 * \author Brian Paul 30 */ 31 32 33 #include "main/glheader.h" 34 #include "main/context.h" 35 #include "main/dispatch.h" 36 #include "main/enums.h" 37 #include "main/hash.h" 38 #include "main/macros.h" 39 #include "main/mtypes.h" 40 #include "main/samplerobj.h" 41 #include "main/texturebindless.h" 42 43 44 struct gl_sampler_object * 45 _mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name) 46 { 47 if (name == 0) 48 return NULL; 49 else 50 return (struct gl_sampler_object *) 51 _mesa_HashLookup(ctx->Shared->SamplerObjects, name); 52 } 53 54 static inline struct gl_sampler_object * 55 lookup_samplerobj_locked(struct gl_context *ctx, GLuint name) 56 { 57 return (struct gl_sampler_object *) 58 _mesa_HashLookupLocked(ctx->Shared->SamplerObjects, name); 59 } 60 61 static void 62 delete_sampler_object(struct gl_context *ctx, 63 struct gl_sampler_object *sampObj) 64 { 65 _mesa_delete_sampler_handles(ctx, sampObj); 66 simple_mtx_destroy(&sampObj->Mutex); 67 free(sampObj->Label); 68 free(sampObj); 69 } 70 71 /** 72 * Handle reference counting. 73 */ 74 void 75 _mesa_reference_sampler_object_(struct gl_context *ctx, 76 struct gl_sampler_object **ptr, 77 struct gl_sampler_object *samp) 78 { 79 assert(*ptr != samp); /* The inline wrapper should prevent no-op calls */ 80 81 if (*ptr) { 82 /* Unreference the old sampler */ 83 GLboolean deleteFlag = GL_FALSE; 84 struct gl_sampler_object *oldSamp = *ptr; 85 86 simple_mtx_lock(&oldSamp->Mutex); 87 assert(oldSamp->RefCount > 0); 88 oldSamp->RefCount--; 89 deleteFlag = (oldSamp->RefCount == 0); 90 simple_mtx_unlock(&oldSamp->Mutex); 91 92 if (deleteFlag) 93 delete_sampler_object(ctx, oldSamp); 94 95 *ptr = NULL; 96 } 97 assert(!*ptr); 98 99 if (samp) { 100 /* reference new sampler */ 101 simple_mtx_lock(&samp->Mutex); 102 assert(samp->RefCount > 0); 103 104 samp->RefCount++; 105 *ptr = samp; 106 simple_mtx_unlock(&samp->Mutex); 107 } 108 } 109 110 111 /** 112 * Initialize the fields of the given sampler object. 113 */ 114 static void 115 _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name) 116 { 117 simple_mtx_init(&sampObj->Mutex, mtx_plain); 118 sampObj->Name = name; 119 sampObj->RefCount = 1; 120 sampObj->WrapS = GL_REPEAT; 121 sampObj->WrapT = GL_REPEAT; 122 sampObj->WrapR = GL_REPEAT; 123 sampObj->MinFilter = GL_NEAREST_MIPMAP_LINEAR; 124 sampObj->MagFilter = GL_LINEAR; 125 sampObj->BorderColor.f[0] = 0.0; 126 sampObj->BorderColor.f[1] = 0.0; 127 sampObj->BorderColor.f[2] = 0.0; 128 sampObj->BorderColor.f[3] = 0.0; 129 sampObj->MinLod = -1000.0F; 130 sampObj->MaxLod = 1000.0F; 131 sampObj->LodBias = 0.0F; 132 sampObj->MaxAnisotropy = 1.0F; 133 sampObj->CompareMode = GL_NONE; 134 sampObj->CompareFunc = GL_LEQUAL; 135 sampObj->sRGBDecode = GL_DECODE_EXT; 136 sampObj->CubeMapSeamless = GL_FALSE; 137 sampObj->HandleAllocated = GL_FALSE; 138 139 /* GL_ARB_bindless_texture */ 140 _mesa_init_sampler_handles(sampObj); 141 } 142 143 /** 144 * Fallback for ctx->Driver.NewSamplerObject(); 145 */ 146 struct gl_sampler_object * 147 _mesa_new_sampler_object(struct gl_context *ctx, GLuint name) 148 { 149 struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object); 150 if (sampObj) { 151 _mesa_init_sampler_object(sampObj, name); 152 } 153 return sampObj; 154 } 155 156 static void 157 create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers, 158 const char *caller) 159 { 160 GLuint first; 161 GLint i; 162 163 if (!samplers) 164 return; 165 166 _mesa_HashLockMutex(ctx->Shared->SamplerObjects); 167 168 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count); 169 170 /* Insert the ID and pointer to new sampler object into hash table */ 171 for (i = 0; i < count; i++) { 172 struct gl_sampler_object *sampObj; 173 GLuint name = first + i; 174 175 sampObj = ctx->Driver.NewSamplerObject(ctx, name); 176 if (!sampObj) { 177 _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); 178 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 179 return; 180 } 181 182 _mesa_HashInsertLocked(ctx->Shared->SamplerObjects, name, sampObj); 183 samplers[i] = name; 184 } 185 186 _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); 187 } 188 189 static void 190 create_samplers_err(struct gl_context *ctx, GLsizei count, GLuint *samplers, 191 const char *caller) 192 { 193 194 if (MESA_VERBOSE & VERBOSE_API) 195 _mesa_debug(ctx, "%s(%d)\n", caller, count); 196 197 if (count < 0) { 198 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller); 199 return; 200 } 201 202 create_samplers(ctx, count, samplers, caller); 203 } 204 205 void GLAPIENTRY 206 _mesa_GenSamplers_no_error(GLsizei count, GLuint *samplers) 207 { 208 GET_CURRENT_CONTEXT(ctx); 209 create_samplers(ctx, count, samplers, "glGenSamplers"); 210 } 211 212 void GLAPIENTRY 213 _mesa_GenSamplers(GLsizei count, GLuint *samplers) 214 { 215 GET_CURRENT_CONTEXT(ctx); 216 create_samplers_err(ctx, count, samplers, "glGenSamplers"); 217 } 218 219 void GLAPIENTRY 220 _mesa_CreateSamplers_no_error(GLsizei count, GLuint *samplers) 221 { 222 GET_CURRENT_CONTEXT(ctx); 223 create_samplers(ctx, count, samplers, "glCreateSamplers"); 224 } 225 226 void GLAPIENTRY 227 _mesa_CreateSamplers(GLsizei count, GLuint *samplers) 228 { 229 GET_CURRENT_CONTEXT(ctx); 230 create_samplers_err(ctx, count, samplers, "glCreateSamplers"); 231 } 232 233 234 static void 235 delete_samplers(struct gl_context *ctx, GLsizei count, const GLuint *samplers) 236 { 237 FLUSH_VERTICES(ctx, 0); 238 239 _mesa_HashLockMutex(ctx->Shared->SamplerObjects); 240 241 for (GLsizei i = 0; i < count; i++) { 242 if (samplers[i]) { 243 GLuint j; 244 struct gl_sampler_object *sampObj = 245 lookup_samplerobj_locked(ctx, samplers[i]); 246 247 if (sampObj) { 248 /* If the sampler is currently bound, unbind it. */ 249 for (j = 0; j < ctx->Const.MaxCombinedTextureImageUnits; j++) { 250 if (ctx->Texture.Unit[j].Sampler == sampObj) { 251 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT); 252 _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[j].Sampler, NULL); 253 } 254 } 255 256 /* The ID is immediately freed for re-use */ 257 _mesa_HashRemoveLocked(ctx->Shared->SamplerObjects, samplers[i]); 258 /* But the object exists until its reference count goes to zero */ 259 _mesa_reference_sampler_object(ctx, &sampObj, NULL); 260 } 261 } 262 } 263 264 _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); 265 } 266 267 268 void GLAPIENTRY 269 _mesa_DeleteSamplers_no_error(GLsizei count, const GLuint *samplers) 270 { 271 GET_CURRENT_CONTEXT(ctx); 272 delete_samplers(ctx, count, samplers); 273 } 274 275 276 void GLAPIENTRY 277 _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers) 278 { 279 GET_CURRENT_CONTEXT(ctx); 280 281 if (count < 0) { 282 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)"); 283 return; 284 } 285 286 delete_samplers(ctx, count, samplers); 287 } 288 289 290 GLboolean GLAPIENTRY 291 _mesa_IsSampler(GLuint sampler) 292 { 293 GET_CURRENT_CONTEXT(ctx); 294 295 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 296 297 return _mesa_lookup_samplerobj(ctx, sampler) != NULL; 298 } 299 300 void 301 _mesa_bind_sampler(struct gl_context *ctx, GLuint unit, 302 struct gl_sampler_object *sampObj) 303 { 304 if (ctx->Texture.Unit[unit].Sampler != sampObj) { 305 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT); 306 } 307 308 _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler, 309 sampObj); 310 } 311 312 static ALWAYS_INLINE void 313 bind_sampler(struct gl_context *ctx, GLuint unit, GLuint sampler, bool no_error) 314 { 315 struct gl_sampler_object *sampObj; 316 317 if (sampler == 0) { 318 /* Use the default sampler object, the one contained in the texture 319 * object. 320 */ 321 sampObj = NULL; 322 } else { 323 /* user-defined sampler object */ 324 sampObj = _mesa_lookup_samplerobj(ctx, sampler); 325 if (!no_error && !sampObj) { 326 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)"); 327 return; 328 } 329 } 330 331 /* bind new sampler */ 332 _mesa_bind_sampler(ctx, unit, sampObj); 333 } 334 335 void GLAPIENTRY 336 _mesa_BindSampler_no_error(GLuint unit, GLuint sampler) 337 { 338 GET_CURRENT_CONTEXT(ctx); 339 bind_sampler(ctx, unit, sampler, true); 340 } 341 342 void GLAPIENTRY 343 _mesa_BindSampler(GLuint unit, GLuint sampler) 344 { 345 GET_CURRENT_CONTEXT(ctx); 346 347 if (unit >= ctx->Const.MaxCombinedTextureImageUnits) { 348 _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit); 349 return; 350 } 351 352 bind_sampler(ctx, unit, sampler, false); 353 } 354 355 356 static ALWAYS_INLINE void 357 bind_samplers(struct gl_context *ctx, GLuint first, GLsizei count, 358 const GLuint *samplers, bool no_error) 359 { 360 GLsizei i; 361 362 FLUSH_VERTICES(ctx, 0); 363 364 if (samplers) { 365 /* Note that the error semantics for multi-bind commands differ from 366 * those of other GL commands. 367 * 368 * The Issues section in the ARB_multi_bind spec says: 369 * 370 * "(11) Typically, OpenGL specifies that if an error is generated by 371 * a command, that command has no effect. This is somewhat 372 * unfortunate for multi-bind commands, because it would require 373 * a first pass to scan the entire list of bound objects for 374 * errors and then a second pass to actually perform the 375 * bindings. Should we have different error semantics? 376 * 377 * RESOLVED: Yes. In this specification, when the parameters for 378 * one of the <count> binding points are invalid, that binding 379 * point is not updated and an error will be generated. However, 380 * other binding points in the same command will be updated if 381 * their parameters are valid and no other error occurs." 382 */ 383 384 _mesa_HashLockMutex(ctx->Shared->SamplerObjects); 385 386 for (i = 0; i < count; i++) { 387 const GLuint unit = first + i; 388 struct gl_sampler_object * const currentSampler = 389 ctx->Texture.Unit[unit].Sampler; 390 struct gl_sampler_object *sampObj; 391 392 if (samplers[i] != 0) { 393 if (currentSampler && currentSampler->Name == samplers[i]) 394 sampObj = currentSampler; 395 else 396 sampObj = lookup_samplerobj_locked(ctx, samplers[i]); 397 398 /* The ARB_multi_bind spec says: 399 * 400 * "An INVALID_OPERATION error is generated if any value 401 * in <samplers> is not zero or the name of an existing 402 * sampler object (per binding)." 403 */ 404 if (!no_error && !sampObj) { 405 _mesa_error(ctx, GL_INVALID_OPERATION, 406 "glBindSamplers(samplers[%d]=%u is not zero or " 407 "the name of an existing sampler object)", 408 i, samplers[i]); 409 continue; 410 } 411 } else { 412 sampObj = NULL; 413 } 414 415 /* Bind the new sampler */ 416 if (sampObj != currentSampler) { 417 _mesa_reference_sampler_object(ctx, 418 &ctx->Texture.Unit[unit].Sampler, 419 sampObj); 420 ctx->NewState |= _NEW_TEXTURE_OBJECT; 421 } 422 } 423 424 _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); 425 } else { 426 /* Unbind all samplers in the range <first> through <first>+<count>-1 */ 427 for (i = 0; i < count; i++) { 428 const GLuint unit = first + i; 429 430 if (ctx->Texture.Unit[unit].Sampler) { 431 _mesa_reference_sampler_object(ctx, 432 &ctx->Texture.Unit[unit].Sampler, 433 NULL); 434 ctx->NewState |= _NEW_TEXTURE_OBJECT; 435 } 436 } 437 } 438 } 439 440 441 void GLAPIENTRY 442 _mesa_BindSamplers_no_error(GLuint first, GLsizei count, const GLuint *samplers) 443 { 444 GET_CURRENT_CONTEXT(ctx); 445 bind_samplers(ctx, first, count, samplers, true); 446 } 447 448 449 void GLAPIENTRY 450 _mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers) 451 { 452 GET_CURRENT_CONTEXT(ctx); 453 454 /* The ARB_multi_bind spec says: 455 * 456 * "An INVALID_OPERATION error is generated if <first> + <count> is 457 * greater than the number of texture image units supported by 458 * the implementation." 459 */ 460 if (first + count > ctx->Const.MaxCombinedTextureImageUnits) { 461 _mesa_error(ctx, GL_INVALID_OPERATION, 462 "glBindSamplers(first=%u + count=%d > the value of " 463 "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)", 464 first, count, ctx->Const.MaxCombinedTextureImageUnits); 465 return; 466 } 467 468 bind_samplers(ctx, first, count, samplers, false); 469 } 470 471 472 /** 473 * Check if a coordinate wrap mode is legal. 474 * \return GL_TRUE if legal, GL_FALSE otherwise 475 */ 476 static GLboolean 477 validate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap) 478 { 479 const struct gl_extensions * const e = &ctx->Extensions; 480 481 switch (wrap) { 482 case GL_CLAMP: 483 case GL_CLAMP_TO_EDGE: 484 case GL_REPEAT: 485 case GL_MIRRORED_REPEAT: 486 return GL_TRUE; 487 case GL_CLAMP_TO_BORDER: 488 return e->ARB_texture_border_clamp; 489 case GL_MIRROR_CLAMP_EXT: 490 return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp; 491 case GL_MIRROR_CLAMP_TO_EDGE_EXT: 492 return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp || e->ARB_texture_mirror_clamp_to_edge; 493 case GL_MIRROR_CLAMP_TO_BORDER_EXT: 494 return e->EXT_texture_mirror_clamp; 495 default: 496 return GL_FALSE; 497 } 498 } 499 500 501 /** 502 * This is called just prior to changing any sampler object state. 503 */ 504 static inline void 505 flush(struct gl_context *ctx) 506 { 507 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT); 508 } 509 510 void 511 _mesa_set_sampler_wrap(struct gl_context *ctx, struct gl_sampler_object *samp, 512 GLenum s, GLenum t, GLenum r) 513 { 514 assert(validate_texture_wrap_mode(ctx, s)); 515 assert(validate_texture_wrap_mode(ctx, t)); 516 assert(validate_texture_wrap_mode(ctx, r)); 517 518 if (samp->WrapS == s && samp->WrapT == t && samp->WrapR == r) 519 return; 520 521 flush(ctx); 522 samp->WrapS = s; 523 samp->WrapT = t; 524 samp->WrapR = r; 525 } 526 527 #define INVALID_PARAM 0x100 528 #define INVALID_PNAME 0x101 529 #define INVALID_VALUE 0x102 530 531 static GLuint 532 set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp, 533 GLint param) 534 { 535 if (samp->WrapS == param) 536 return GL_FALSE; 537 if (validate_texture_wrap_mode(ctx, param)) { 538 flush(ctx); 539 samp->WrapS = param; 540 return GL_TRUE; 541 } 542 return INVALID_PARAM; 543 } 544 545 546 static GLuint 547 set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp, 548 GLint param) 549 { 550 if (samp->WrapT == param) 551 return GL_FALSE; 552 if (validate_texture_wrap_mode(ctx, param)) { 553 flush(ctx); 554 samp->WrapT = param; 555 return GL_TRUE; 556 } 557 return INVALID_PARAM; 558 } 559 560 561 static GLuint 562 set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp, 563 GLint param) 564 { 565 if (samp->WrapR == param) 566 return GL_FALSE; 567 if (validate_texture_wrap_mode(ctx, param)) { 568 flush(ctx); 569 samp->WrapR = param; 570 return GL_TRUE; 571 } 572 return INVALID_PARAM; 573 } 574 575 void 576 _mesa_set_sampler_filters(struct gl_context *ctx, 577 struct gl_sampler_object *samp, 578 GLenum min_filter, GLenum mag_filter) 579 { 580 assert(min_filter == GL_NEAREST || 581 min_filter == GL_LINEAR || 582 min_filter == GL_NEAREST_MIPMAP_NEAREST || 583 min_filter == GL_LINEAR_MIPMAP_NEAREST || 584 min_filter == GL_NEAREST_MIPMAP_LINEAR || 585 min_filter == GL_LINEAR_MIPMAP_LINEAR); 586 assert(mag_filter == GL_NEAREST || 587 mag_filter == GL_LINEAR); 588 589 if (samp->MinFilter == min_filter && samp->MagFilter == mag_filter) 590 return; 591 592 flush(ctx); 593 samp->MinFilter = min_filter; 594 samp->MagFilter = mag_filter; 595 } 596 597 static GLuint 598 set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp, 599 GLint param) 600 { 601 if (samp->MinFilter == param) 602 return GL_FALSE; 603 604 switch (param) { 605 case GL_NEAREST: 606 case GL_LINEAR: 607 case GL_NEAREST_MIPMAP_NEAREST: 608 case GL_LINEAR_MIPMAP_NEAREST: 609 case GL_NEAREST_MIPMAP_LINEAR: 610 case GL_LINEAR_MIPMAP_LINEAR: 611 flush(ctx); 612 samp->MinFilter = param; 613 return GL_TRUE; 614 default: 615 return INVALID_PARAM; 616 } 617 } 618 619 620 static GLuint 621 set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp, 622 GLint param) 623 { 624 if (samp->MagFilter == param) 625 return GL_FALSE; 626 627 switch (param) { 628 case GL_NEAREST: 629 case GL_LINEAR: 630 flush(ctx); 631 samp->MagFilter = param; 632 return GL_TRUE; 633 default: 634 return INVALID_PARAM; 635 } 636 } 637 638 639 static GLuint 640 set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp, 641 GLfloat param) 642 { 643 if (samp->LodBias == param) 644 return GL_FALSE; 645 646 flush(ctx); 647 samp->LodBias = param; 648 return GL_TRUE; 649 } 650 651 652 static GLuint 653 set_sampler_border_colorf(struct gl_context *ctx, 654 struct gl_sampler_object *samp, 655 const GLfloat params[4]) 656 { 657 flush(ctx); 658 samp->BorderColor.f[RCOMP] = params[0]; 659 samp->BorderColor.f[GCOMP] = params[1]; 660 samp->BorderColor.f[BCOMP] = params[2]; 661 samp->BorderColor.f[ACOMP] = params[3]; 662 return GL_TRUE; 663 } 664 665 666 static GLuint 667 set_sampler_border_colori(struct gl_context *ctx, 668 struct gl_sampler_object *samp, 669 const GLint params[4]) 670 { 671 flush(ctx); 672 samp->BorderColor.i[RCOMP] = params[0]; 673 samp->BorderColor.i[GCOMP] = params[1]; 674 samp->BorderColor.i[BCOMP] = params[2]; 675 samp->BorderColor.i[ACOMP] = params[3]; 676 return GL_TRUE; 677 } 678 679 680 static GLuint 681 set_sampler_border_colorui(struct gl_context *ctx, 682 struct gl_sampler_object *samp, 683 const GLuint params[4]) 684 { 685 flush(ctx); 686 samp->BorderColor.ui[RCOMP] = params[0]; 687 samp->BorderColor.ui[GCOMP] = params[1]; 688 samp->BorderColor.ui[BCOMP] = params[2]; 689 samp->BorderColor.ui[ACOMP] = params[3]; 690 return GL_TRUE; 691 } 692 693 694 static GLuint 695 set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp, 696 GLfloat param) 697 { 698 if (samp->MinLod == param) 699 return GL_FALSE; 700 701 flush(ctx); 702 samp->MinLod = param; 703 return GL_TRUE; 704 } 705 706 707 static GLuint 708 set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp, 709 GLfloat param) 710 { 711 if (samp->MaxLod == param) 712 return GL_FALSE; 713 714 flush(ctx); 715 samp->MaxLod = param; 716 return GL_TRUE; 717 } 718 719 720 static GLuint 721 set_sampler_compare_mode(struct gl_context *ctx, 722 struct gl_sampler_object *samp, GLint param) 723 { 724 /* If GL_ARB_shadow is not supported, don't report an error. The 725 * sampler object extension spec isn't clear on this extension interaction. 726 * Silences errors with Wine on older GPUs such as R200. 727 */ 728 if (!ctx->Extensions.ARB_shadow) 729 return GL_FALSE; 730 731 if (samp->CompareMode == param) 732 return GL_FALSE; 733 734 if (param == GL_NONE || 735 param == GL_COMPARE_R_TO_TEXTURE_ARB) { 736 flush(ctx); 737 samp->CompareMode = param; 738 return GL_TRUE; 739 } 740 741 return INVALID_PARAM; 742 } 743 744 745 static GLuint 746 set_sampler_compare_func(struct gl_context *ctx, 747 struct gl_sampler_object *samp, GLint param) 748 { 749 /* If GL_ARB_shadow is not supported, don't report an error. The 750 * sampler object extension spec isn't clear on this extension interaction. 751 * Silences errors with Wine on older GPUs such as R200. 752 */ 753 if (!ctx->Extensions.ARB_shadow) 754 return GL_FALSE; 755 756 if (samp->CompareFunc == param) 757 return GL_FALSE; 758 759 switch (param) { 760 case GL_LEQUAL: 761 case GL_GEQUAL: 762 case GL_EQUAL: 763 case GL_NOTEQUAL: 764 case GL_LESS: 765 case GL_GREATER: 766 case GL_ALWAYS: 767 case GL_NEVER: 768 flush(ctx); 769 samp->CompareFunc = param; 770 return GL_TRUE; 771 default: 772 return INVALID_PARAM; 773 } 774 } 775 776 777 static GLuint 778 set_sampler_max_anisotropy(struct gl_context *ctx, 779 struct gl_sampler_object *samp, GLfloat param) 780 { 781 if (!ctx->Extensions.EXT_texture_filter_anisotropic) 782 return INVALID_PNAME; 783 784 if (samp->MaxAnisotropy == param) 785 return GL_FALSE; 786 787 if (param < 1.0F) 788 return INVALID_VALUE; 789 790 flush(ctx); 791 /* clamp to max, that's what NVIDIA does */ 792 samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy); 793 return GL_TRUE; 794 } 795 796 797 static GLuint 798 set_sampler_cube_map_seamless(struct gl_context *ctx, 799 struct gl_sampler_object *samp, GLboolean param) 800 { 801 if (!_mesa_is_desktop_gl(ctx) 802 || !ctx->Extensions.AMD_seamless_cubemap_per_texture) 803 return INVALID_PNAME; 804 805 if (samp->CubeMapSeamless == param) 806 return GL_FALSE; 807 808 if (param != GL_TRUE && param != GL_FALSE) 809 return INVALID_VALUE; 810 811 flush(ctx); 812 samp->CubeMapSeamless = param; 813 return GL_TRUE; 814 } 815 816 void 817 _mesa_set_sampler_srgb_decode(struct gl_context *ctx, 818 struct gl_sampler_object *samp, GLenum param) 819 { 820 assert(param == GL_DECODE_EXT || param == GL_SKIP_DECODE_EXT); 821 822 flush(ctx); 823 samp->sRGBDecode = param; 824 } 825 826 static GLuint 827 set_sampler_srgb_decode(struct gl_context *ctx, 828 struct gl_sampler_object *samp, GLenum param) 829 { 830 if (!ctx->Extensions.EXT_texture_sRGB_decode) 831 return INVALID_PNAME; 832 833 if (samp->sRGBDecode == param) 834 return GL_FALSE; 835 836 /* The EXT_texture_sRGB_decode spec says: 837 * 838 * "INVALID_ENUM is generated if the <pname> parameter of 839 * TexParameter[i,f,Ii,Iui][v][EXT], 840 * MultiTexParameter[i,f,Ii,Iui][v]EXT, 841 * TextureParameter[i,f,Ii,Iui][v]EXT, SamplerParameter[i,f,Ii,Iui][v] 842 * is TEXTURE_SRGB_DECODE_EXT when the <param> parameter is not one of 843 * DECODE_EXT or SKIP_DECODE_EXT. 844 * 845 * Returning INVALID_PARAM makes that happen. 846 */ 847 if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT) 848 return INVALID_PARAM; 849 850 flush(ctx); 851 samp->sRGBDecode = param; 852 return GL_TRUE; 853 } 854 855 static struct gl_sampler_object * 856 sampler_parameter_error_check(struct gl_context *ctx, GLuint sampler, 857 bool get, const char *name) 858 { 859 struct gl_sampler_object *sampObj; 860 861 sampObj = _mesa_lookup_samplerobj(ctx, sampler); 862 if (!sampObj) { 863 /* OpenGL 4.5 spec, section "8.2 Sampler Objects", page 176 of the PDF 864 * states: 865 * 866 * "An INVALID_OPERATION error is generated if sampler is not the name 867 * of a sampler object previously returned from a call to 868 * GenSamplers." 869 */ 870 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid sampler)", name); 871 return NULL; 872 } 873 874 if (!get && sampObj->HandleAllocated) { 875 /* The ARB_bindless_texture spec says: 876 * 877 * "The error INVALID_OPERATION is generated by SamplerParameter* if 878 * <sampler> identifies a sampler object referenced by one or more 879 * texture handles." 880 */ 881 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable sampler)", name); 882 return NULL; 883 } 884 885 return sampObj; 886 } 887 888 void GLAPIENTRY 889 _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) 890 { 891 struct gl_sampler_object *sampObj; 892 GLuint res; 893 GET_CURRENT_CONTEXT(ctx); 894 895 sampObj = sampler_parameter_error_check(ctx, sampler, false, 896 "glSamplerParameteri"); 897 if (!sampObj) 898 return; 899 900 switch (pname) { 901 case GL_TEXTURE_WRAP_S: 902 res = set_sampler_wrap_s(ctx, sampObj, param); 903 break; 904 case GL_TEXTURE_WRAP_T: 905 res = set_sampler_wrap_t(ctx, sampObj, param); 906 break; 907 case GL_TEXTURE_WRAP_R: 908 res = set_sampler_wrap_r(ctx, sampObj, param); 909 break; 910 case GL_TEXTURE_MIN_FILTER: 911 res = set_sampler_min_filter(ctx, sampObj, param); 912 break; 913 case GL_TEXTURE_MAG_FILTER: 914 res = set_sampler_mag_filter(ctx, sampObj, param); 915 break; 916 case GL_TEXTURE_MIN_LOD: 917 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param); 918 break; 919 case GL_TEXTURE_MAX_LOD: 920 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param); 921 break; 922 case GL_TEXTURE_LOD_BIAS: 923 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param); 924 break; 925 case GL_TEXTURE_COMPARE_MODE: 926 res = set_sampler_compare_mode(ctx, sampObj, param); 927 break; 928 case GL_TEXTURE_COMPARE_FUNC: 929 res = set_sampler_compare_func(ctx, sampObj, param); 930 break; 931 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 932 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param); 933 break; 934 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 935 res = set_sampler_cube_map_seamless(ctx, sampObj, param); 936 break; 937 case GL_TEXTURE_SRGB_DECODE_EXT: 938 res = set_sampler_srgb_decode(ctx, sampObj, param); 939 break; 940 case GL_TEXTURE_BORDER_COLOR: 941 /* fall-through */ 942 default: 943 res = INVALID_PNAME; 944 } 945 946 switch (res) { 947 case GL_FALSE: 948 /* no change */ 949 break; 950 case GL_TRUE: 951 /* state change - we do nothing special at this time */ 952 break; 953 case INVALID_PNAME: 954 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n", 955 _mesa_enum_to_string(pname)); 956 break; 957 case INVALID_PARAM: 958 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n", 959 param); 960 break; 961 case INVALID_VALUE: 962 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n", 963 param); 964 break; 965 default: 966 ; 967 } 968 } 969 970 971 void GLAPIENTRY 972 _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) 973 { 974 struct gl_sampler_object *sampObj; 975 GLuint res; 976 GET_CURRENT_CONTEXT(ctx); 977 978 sampObj = sampler_parameter_error_check(ctx, sampler, false, 979 "glSamplerParameterf"); 980 if (!sampObj) 981 return; 982 983 switch (pname) { 984 case GL_TEXTURE_WRAP_S: 985 res = set_sampler_wrap_s(ctx, sampObj, (GLint) param); 986 break; 987 case GL_TEXTURE_WRAP_T: 988 res = set_sampler_wrap_t(ctx, sampObj, (GLint) param); 989 break; 990 case GL_TEXTURE_WRAP_R: 991 res = set_sampler_wrap_r(ctx, sampObj, (GLint) param); 992 break; 993 case GL_TEXTURE_MIN_FILTER: 994 res = set_sampler_min_filter(ctx, sampObj, (GLint) param); 995 break; 996 case GL_TEXTURE_MAG_FILTER: 997 res = set_sampler_mag_filter(ctx, sampObj, (GLint) param); 998 break; 999 case GL_TEXTURE_MIN_LOD: 1000 res = set_sampler_min_lod(ctx, sampObj, param); 1001 break; 1002 case GL_TEXTURE_MAX_LOD: 1003 res = set_sampler_max_lod(ctx, sampObj, param); 1004 break; 1005 case GL_TEXTURE_LOD_BIAS: 1006 res = set_sampler_lod_bias(ctx, sampObj, param); 1007 break; 1008 case GL_TEXTURE_COMPARE_MODE: 1009 res = set_sampler_compare_mode(ctx, sampObj, (GLint) param); 1010 break; 1011 case GL_TEXTURE_COMPARE_FUNC: 1012 res = set_sampler_compare_func(ctx, sampObj, (GLint) param); 1013 break; 1014 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1015 res = set_sampler_max_anisotropy(ctx, sampObj, param); 1016 break; 1017 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1018 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) param); 1019 break; 1020 case GL_TEXTURE_SRGB_DECODE_EXT: 1021 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) param); 1022 break; 1023 case GL_TEXTURE_BORDER_COLOR: 1024 /* fall-through */ 1025 default: 1026 res = INVALID_PNAME; 1027 } 1028 1029 switch (res) { 1030 case GL_FALSE: 1031 /* no change */ 1032 break; 1033 case GL_TRUE: 1034 /* state change - we do nothing special at this time */ 1035 break; 1036 case INVALID_PNAME: 1037 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n", 1038 _mesa_enum_to_string(pname)); 1039 break; 1040 case INVALID_PARAM: 1041 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n", 1042 param); 1043 break; 1044 case INVALID_VALUE: 1045 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n", 1046 param); 1047 break; 1048 default: 1049 ; 1050 } 1051 } 1052 1053 void GLAPIENTRY 1054 _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params) 1055 { 1056 struct gl_sampler_object *sampObj; 1057 GLuint res; 1058 GET_CURRENT_CONTEXT(ctx); 1059 1060 sampObj = sampler_parameter_error_check(ctx, sampler, false, 1061 "glSamplerParameteriv"); 1062 if (!sampObj) 1063 return; 1064 1065 switch (pname) { 1066 case GL_TEXTURE_WRAP_S: 1067 res = set_sampler_wrap_s(ctx, sampObj, params[0]); 1068 break; 1069 case GL_TEXTURE_WRAP_T: 1070 res = set_sampler_wrap_t(ctx, sampObj, params[0]); 1071 break; 1072 case GL_TEXTURE_WRAP_R: 1073 res = set_sampler_wrap_r(ctx, sampObj, params[0]); 1074 break; 1075 case GL_TEXTURE_MIN_FILTER: 1076 res = set_sampler_min_filter(ctx, sampObj, params[0]); 1077 break; 1078 case GL_TEXTURE_MAG_FILTER: 1079 res = set_sampler_mag_filter(ctx, sampObj, params[0]); 1080 break; 1081 case GL_TEXTURE_MIN_LOD: 1082 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]); 1083 break; 1084 case GL_TEXTURE_MAX_LOD: 1085 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]); 1086 break; 1087 case GL_TEXTURE_LOD_BIAS: 1088 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]); 1089 break; 1090 case GL_TEXTURE_COMPARE_MODE: 1091 res = set_sampler_compare_mode(ctx, sampObj, params[0]); 1092 break; 1093 case GL_TEXTURE_COMPARE_FUNC: 1094 res = set_sampler_compare_func(ctx, sampObj, params[0]); 1095 break; 1096 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1097 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]); 1098 break; 1099 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1100 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]); 1101 break; 1102 case GL_TEXTURE_SRGB_DECODE_EXT: 1103 res = set_sampler_srgb_decode(ctx, sampObj, params[0]); 1104 break; 1105 case GL_TEXTURE_BORDER_COLOR: 1106 { 1107 GLfloat c[4]; 1108 c[0] = INT_TO_FLOAT(params[0]); 1109 c[1] = INT_TO_FLOAT(params[1]); 1110 c[2] = INT_TO_FLOAT(params[2]); 1111 c[3] = INT_TO_FLOAT(params[3]); 1112 res = set_sampler_border_colorf(ctx, sampObj, c); 1113 } 1114 break; 1115 default: 1116 res = INVALID_PNAME; 1117 } 1118 1119 switch (res) { 1120 case GL_FALSE: 1121 /* no change */ 1122 break; 1123 case GL_TRUE: 1124 /* state change - we do nothing special at this time */ 1125 break; 1126 case INVALID_PNAME: 1127 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n", 1128 _mesa_enum_to_string(pname)); 1129 break; 1130 case INVALID_PARAM: 1131 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n", 1132 params[0]); 1133 break; 1134 case INVALID_VALUE: 1135 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n", 1136 params[0]); 1137 break; 1138 default: 1139 ; 1140 } 1141 } 1142 1143 void GLAPIENTRY 1144 _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params) 1145 { 1146 struct gl_sampler_object *sampObj; 1147 GLuint res; 1148 GET_CURRENT_CONTEXT(ctx); 1149 1150 sampObj = sampler_parameter_error_check(ctx, sampler, false, 1151 "glSamplerParameterfv"); 1152 if (!sampObj) 1153 return; 1154 1155 switch (pname) { 1156 case GL_TEXTURE_WRAP_S: 1157 res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]); 1158 break; 1159 case GL_TEXTURE_WRAP_T: 1160 res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]); 1161 break; 1162 case GL_TEXTURE_WRAP_R: 1163 res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]); 1164 break; 1165 case GL_TEXTURE_MIN_FILTER: 1166 res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]); 1167 break; 1168 case GL_TEXTURE_MAG_FILTER: 1169 res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]); 1170 break; 1171 case GL_TEXTURE_MIN_LOD: 1172 res = set_sampler_min_lod(ctx, sampObj, params[0]); 1173 break; 1174 case GL_TEXTURE_MAX_LOD: 1175 res = set_sampler_max_lod(ctx, sampObj, params[0]); 1176 break; 1177 case GL_TEXTURE_LOD_BIAS: 1178 res = set_sampler_lod_bias(ctx, sampObj, params[0]); 1179 break; 1180 case GL_TEXTURE_COMPARE_MODE: 1181 res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]); 1182 break; 1183 case GL_TEXTURE_COMPARE_FUNC: 1184 res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]); 1185 break; 1186 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1187 res = set_sampler_max_anisotropy(ctx, sampObj, params[0]); 1188 break; 1189 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1190 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]); 1191 break; 1192 case GL_TEXTURE_SRGB_DECODE_EXT: 1193 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]); 1194 break; 1195 case GL_TEXTURE_BORDER_COLOR: 1196 res = set_sampler_border_colorf(ctx, sampObj, params); 1197 break; 1198 default: 1199 res = INVALID_PNAME; 1200 } 1201 1202 switch (res) { 1203 case GL_FALSE: 1204 /* no change */ 1205 break; 1206 case GL_TRUE: 1207 /* state change - we do nothing special at this time */ 1208 break; 1209 case INVALID_PNAME: 1210 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n", 1211 _mesa_enum_to_string(pname)); 1212 break; 1213 case INVALID_PARAM: 1214 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n", 1215 params[0]); 1216 break; 1217 case INVALID_VALUE: 1218 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n", 1219 params[0]); 1220 break; 1221 default: 1222 ; 1223 } 1224 } 1225 1226 void GLAPIENTRY 1227 _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params) 1228 { 1229 struct gl_sampler_object *sampObj; 1230 GLuint res; 1231 GET_CURRENT_CONTEXT(ctx); 1232 1233 sampObj = sampler_parameter_error_check(ctx, sampler, false, 1234 "glSamplerParameterIiv"); 1235 if (!sampObj) 1236 return; 1237 1238 switch (pname) { 1239 case GL_TEXTURE_WRAP_S: 1240 res = set_sampler_wrap_s(ctx, sampObj, params[0]); 1241 break; 1242 case GL_TEXTURE_WRAP_T: 1243 res = set_sampler_wrap_t(ctx, sampObj, params[0]); 1244 break; 1245 case GL_TEXTURE_WRAP_R: 1246 res = set_sampler_wrap_r(ctx, sampObj, params[0]); 1247 break; 1248 case GL_TEXTURE_MIN_FILTER: 1249 res = set_sampler_min_filter(ctx, sampObj, params[0]); 1250 break; 1251 case GL_TEXTURE_MAG_FILTER: 1252 res = set_sampler_mag_filter(ctx, sampObj, params[0]); 1253 break; 1254 case GL_TEXTURE_MIN_LOD: 1255 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]); 1256 break; 1257 case GL_TEXTURE_MAX_LOD: 1258 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]); 1259 break; 1260 case GL_TEXTURE_LOD_BIAS: 1261 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]); 1262 break; 1263 case GL_TEXTURE_COMPARE_MODE: 1264 res = set_sampler_compare_mode(ctx, sampObj, params[0]); 1265 break; 1266 case GL_TEXTURE_COMPARE_FUNC: 1267 res = set_sampler_compare_func(ctx, sampObj, params[0]); 1268 break; 1269 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1270 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]); 1271 break; 1272 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1273 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]); 1274 break; 1275 case GL_TEXTURE_SRGB_DECODE_EXT: 1276 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]); 1277 break; 1278 case GL_TEXTURE_BORDER_COLOR: 1279 res = set_sampler_border_colori(ctx, sampObj, params); 1280 break; 1281 default: 1282 res = INVALID_PNAME; 1283 } 1284 1285 switch (res) { 1286 case GL_FALSE: 1287 /* no change */ 1288 break; 1289 case GL_TRUE: 1290 /* state change - we do nothing special at this time */ 1291 break; 1292 case INVALID_PNAME: 1293 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n", 1294 _mesa_enum_to_string(pname)); 1295 break; 1296 case INVALID_PARAM: 1297 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n", 1298 params[0]); 1299 break; 1300 case INVALID_VALUE: 1301 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n", 1302 params[0]); 1303 break; 1304 default: 1305 ; 1306 } 1307 } 1308 1309 1310 void GLAPIENTRY 1311 _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params) 1312 { 1313 struct gl_sampler_object *sampObj; 1314 GLuint res; 1315 GET_CURRENT_CONTEXT(ctx); 1316 1317 sampObj = sampler_parameter_error_check(ctx, sampler, false, 1318 "glSamplerParameterIuiv"); 1319 if (!sampObj) 1320 return; 1321 1322 switch (pname) { 1323 case GL_TEXTURE_WRAP_S: 1324 res = set_sampler_wrap_s(ctx, sampObj, params[0]); 1325 break; 1326 case GL_TEXTURE_WRAP_T: 1327 res = set_sampler_wrap_t(ctx, sampObj, params[0]); 1328 break; 1329 case GL_TEXTURE_WRAP_R: 1330 res = set_sampler_wrap_r(ctx, sampObj, params[0]); 1331 break; 1332 case GL_TEXTURE_MIN_FILTER: 1333 res = set_sampler_min_filter(ctx, sampObj, params[0]); 1334 break; 1335 case GL_TEXTURE_MAG_FILTER: 1336 res = set_sampler_mag_filter(ctx, sampObj, params[0]); 1337 break; 1338 case GL_TEXTURE_MIN_LOD: 1339 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]); 1340 break; 1341 case GL_TEXTURE_MAX_LOD: 1342 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]); 1343 break; 1344 case GL_TEXTURE_LOD_BIAS: 1345 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]); 1346 break; 1347 case GL_TEXTURE_COMPARE_MODE: 1348 res = set_sampler_compare_mode(ctx, sampObj, params[0]); 1349 break; 1350 case GL_TEXTURE_COMPARE_FUNC: 1351 res = set_sampler_compare_func(ctx, sampObj, params[0]); 1352 break; 1353 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1354 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]); 1355 break; 1356 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1357 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]); 1358 break; 1359 case GL_TEXTURE_SRGB_DECODE_EXT: 1360 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]); 1361 break; 1362 case GL_TEXTURE_BORDER_COLOR: 1363 res = set_sampler_border_colorui(ctx, sampObj, params); 1364 break; 1365 default: 1366 res = INVALID_PNAME; 1367 } 1368 1369 switch (res) { 1370 case GL_FALSE: 1371 /* no change */ 1372 break; 1373 case GL_TRUE: 1374 /* state change - we do nothing special at this time */ 1375 break; 1376 case INVALID_PNAME: 1377 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n", 1378 _mesa_enum_to_string(pname)); 1379 break; 1380 case INVALID_PARAM: 1381 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n", 1382 params[0]); 1383 break; 1384 case INVALID_VALUE: 1385 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n", 1386 params[0]); 1387 break; 1388 default: 1389 ; 1390 } 1391 } 1392 1393 1394 void GLAPIENTRY 1395 _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) 1396 { 1397 struct gl_sampler_object *sampObj; 1398 GET_CURRENT_CONTEXT(ctx); 1399 1400 sampObj = sampler_parameter_error_check(ctx, sampler, true, 1401 "glGetSamplerParameteriv"); 1402 if (!sampObj) 1403 return; 1404 1405 switch (pname) { 1406 case GL_TEXTURE_WRAP_S: 1407 *params = sampObj->WrapS; 1408 break; 1409 case GL_TEXTURE_WRAP_T: 1410 *params = sampObj->WrapT; 1411 break; 1412 case GL_TEXTURE_WRAP_R: 1413 *params = sampObj->WrapR; 1414 break; 1415 case GL_TEXTURE_MIN_FILTER: 1416 *params = sampObj->MinFilter; 1417 break; 1418 case GL_TEXTURE_MAG_FILTER: 1419 *params = sampObj->MagFilter; 1420 break; 1421 case GL_TEXTURE_MIN_LOD: 1422 /* GL spec 'Data Conversions' section specifies that floating-point 1423 * value in integer Get function is rounded to nearest integer 1424 */ 1425 *params = IROUND(sampObj->MinLod); 1426 break; 1427 case GL_TEXTURE_MAX_LOD: 1428 /* GL spec 'Data Conversions' section specifies that floating-point 1429 * value in integer Get function is rounded to nearest integer 1430 */ 1431 *params = IROUND(sampObj->MaxLod); 1432 break; 1433 case GL_TEXTURE_LOD_BIAS: 1434 /* GL spec 'Data Conversions' section specifies that floating-point 1435 * value in integer Get function is rounded to nearest integer 1436 */ 1437 *params = IROUND(sampObj->LodBias); 1438 break; 1439 case GL_TEXTURE_COMPARE_MODE: 1440 *params = sampObj->CompareMode; 1441 break; 1442 case GL_TEXTURE_COMPARE_FUNC: 1443 *params = sampObj->CompareFunc; 1444 break; 1445 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1446 /* GL spec 'Data Conversions' section specifies that floating-point 1447 * value in integer Get function is rounded to nearest integer 1448 */ 1449 *params = IROUND(sampObj->MaxAnisotropy); 1450 break; 1451 case GL_TEXTURE_BORDER_COLOR: 1452 params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]); 1453 params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]); 1454 params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]); 1455 params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]); 1456 break; 1457 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1458 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture) 1459 goto invalid_pname; 1460 *params = sampObj->CubeMapSeamless; 1461 break; 1462 case GL_TEXTURE_SRGB_DECODE_EXT: 1463 if (!ctx->Extensions.EXT_texture_sRGB_decode) 1464 goto invalid_pname; 1465 *params = (GLenum) sampObj->sRGBDecode; 1466 break; 1467 default: 1468 goto invalid_pname; 1469 } 1470 return; 1471 1472 invalid_pname: 1473 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)", 1474 _mesa_enum_to_string(pname)); 1475 } 1476 1477 1478 void GLAPIENTRY 1479 _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) 1480 { 1481 struct gl_sampler_object *sampObj; 1482 GET_CURRENT_CONTEXT(ctx); 1483 1484 sampObj = sampler_parameter_error_check(ctx, sampler, true, 1485 "glGetSamplerParameterfv"); 1486 if (!sampObj) 1487 return; 1488 1489 switch (pname) { 1490 case GL_TEXTURE_WRAP_S: 1491 *params = (GLfloat) sampObj->WrapS; 1492 break; 1493 case GL_TEXTURE_WRAP_T: 1494 *params = (GLfloat) sampObj->WrapT; 1495 break; 1496 case GL_TEXTURE_WRAP_R: 1497 *params = (GLfloat) sampObj->WrapR; 1498 break; 1499 case GL_TEXTURE_MIN_FILTER: 1500 *params = (GLfloat) sampObj->MinFilter; 1501 break; 1502 case GL_TEXTURE_MAG_FILTER: 1503 *params = (GLfloat) sampObj->MagFilter; 1504 break; 1505 case GL_TEXTURE_MIN_LOD: 1506 *params = sampObj->MinLod; 1507 break; 1508 case GL_TEXTURE_MAX_LOD: 1509 *params = sampObj->MaxLod; 1510 break; 1511 case GL_TEXTURE_LOD_BIAS: 1512 *params = sampObj->LodBias; 1513 break; 1514 case GL_TEXTURE_COMPARE_MODE: 1515 *params = (GLfloat) sampObj->CompareMode; 1516 break; 1517 case GL_TEXTURE_COMPARE_FUNC: 1518 *params = (GLfloat) sampObj->CompareFunc; 1519 break; 1520 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1521 *params = sampObj->MaxAnisotropy; 1522 break; 1523 case GL_TEXTURE_BORDER_COLOR: 1524 params[0] = sampObj->BorderColor.f[0]; 1525 params[1] = sampObj->BorderColor.f[1]; 1526 params[2] = sampObj->BorderColor.f[2]; 1527 params[3] = sampObj->BorderColor.f[3]; 1528 break; 1529 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1530 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture) 1531 goto invalid_pname; 1532 *params = (GLfloat) sampObj->CubeMapSeamless; 1533 break; 1534 case GL_TEXTURE_SRGB_DECODE_EXT: 1535 if (!ctx->Extensions.EXT_texture_sRGB_decode) 1536 goto invalid_pname; 1537 *params = (GLfloat) sampObj->sRGBDecode; 1538 break; 1539 default: 1540 goto invalid_pname; 1541 } 1542 return; 1543 1544 invalid_pname: 1545 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)", 1546 _mesa_enum_to_string(pname)); 1547 } 1548 1549 1550 void GLAPIENTRY 1551 _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params) 1552 { 1553 struct gl_sampler_object *sampObj; 1554 GET_CURRENT_CONTEXT(ctx); 1555 1556 sampObj = sampler_parameter_error_check(ctx, sampler, true, 1557 "glGetSamplerParameterIiv"); 1558 if (!sampObj) 1559 return; 1560 1561 switch (pname) { 1562 case GL_TEXTURE_WRAP_S: 1563 *params = sampObj->WrapS; 1564 break; 1565 case GL_TEXTURE_WRAP_T: 1566 *params = sampObj->WrapT; 1567 break; 1568 case GL_TEXTURE_WRAP_R: 1569 *params = sampObj->WrapR; 1570 break; 1571 case GL_TEXTURE_MIN_FILTER: 1572 *params = sampObj->MinFilter; 1573 break; 1574 case GL_TEXTURE_MAG_FILTER: 1575 *params = sampObj->MagFilter; 1576 break; 1577 case GL_TEXTURE_MIN_LOD: 1578 *params = (GLint) sampObj->MinLod; 1579 break; 1580 case GL_TEXTURE_MAX_LOD: 1581 *params = (GLint) sampObj->MaxLod; 1582 break; 1583 case GL_TEXTURE_LOD_BIAS: 1584 *params = (GLint) sampObj->LodBias; 1585 break; 1586 case GL_TEXTURE_COMPARE_MODE: 1587 *params = sampObj->CompareMode; 1588 break; 1589 case GL_TEXTURE_COMPARE_FUNC: 1590 *params = sampObj->CompareFunc; 1591 break; 1592 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1593 *params = (GLint) sampObj->MaxAnisotropy; 1594 break; 1595 case GL_TEXTURE_BORDER_COLOR: 1596 params[0] = sampObj->BorderColor.i[0]; 1597 params[1] = sampObj->BorderColor.i[1]; 1598 params[2] = sampObj->BorderColor.i[2]; 1599 params[3] = sampObj->BorderColor.i[3]; 1600 break; 1601 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1602 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture) 1603 goto invalid_pname; 1604 *params = sampObj->CubeMapSeamless; 1605 break; 1606 case GL_TEXTURE_SRGB_DECODE_EXT: 1607 if (!ctx->Extensions.EXT_texture_sRGB_decode) 1608 goto invalid_pname; 1609 *params = (GLenum) sampObj->sRGBDecode; 1610 break; 1611 default: 1612 goto invalid_pname; 1613 } 1614 return; 1615 1616 invalid_pname: 1617 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)", 1618 _mesa_enum_to_string(pname)); 1619 } 1620 1621 1622 void GLAPIENTRY 1623 _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params) 1624 { 1625 struct gl_sampler_object *sampObj; 1626 GET_CURRENT_CONTEXT(ctx); 1627 1628 sampObj = sampler_parameter_error_check(ctx, sampler, true, 1629 "glGetSamplerParameterIuiv"); 1630 if (!sampObj) 1631 return; 1632 1633 switch (pname) { 1634 case GL_TEXTURE_WRAP_S: 1635 *params = sampObj->WrapS; 1636 break; 1637 case GL_TEXTURE_WRAP_T: 1638 *params = sampObj->WrapT; 1639 break; 1640 case GL_TEXTURE_WRAP_R: 1641 *params = sampObj->WrapR; 1642 break; 1643 case GL_TEXTURE_MIN_FILTER: 1644 *params = sampObj->MinFilter; 1645 break; 1646 case GL_TEXTURE_MAG_FILTER: 1647 *params = sampObj->MagFilter; 1648 break; 1649 case GL_TEXTURE_MIN_LOD: 1650 *params = (GLuint) sampObj->MinLod; 1651 break; 1652 case GL_TEXTURE_MAX_LOD: 1653 *params = (GLuint) sampObj->MaxLod; 1654 break; 1655 case GL_TEXTURE_LOD_BIAS: 1656 *params = (GLuint) sampObj->LodBias; 1657 break; 1658 case GL_TEXTURE_COMPARE_MODE: 1659 *params = sampObj->CompareMode; 1660 break; 1661 case GL_TEXTURE_COMPARE_FUNC: 1662 *params = sampObj->CompareFunc; 1663 break; 1664 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 1665 *params = (GLuint) sampObj->MaxAnisotropy; 1666 break; 1667 case GL_TEXTURE_BORDER_COLOR: 1668 params[0] = sampObj->BorderColor.ui[0]; 1669 params[1] = sampObj->BorderColor.ui[1]; 1670 params[2] = sampObj->BorderColor.ui[2]; 1671 params[3] = sampObj->BorderColor.ui[3]; 1672 break; 1673 case GL_TEXTURE_CUBE_MAP_SEAMLESS: 1674 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture) 1675 goto invalid_pname; 1676 *params = sampObj->CubeMapSeamless; 1677 break; 1678 case GL_TEXTURE_SRGB_DECODE_EXT: 1679 if (!ctx->Extensions.EXT_texture_sRGB_decode) 1680 goto invalid_pname; 1681 *params = (GLenum) sampObj->sRGBDecode; 1682 break; 1683 default: 1684 goto invalid_pname; 1685 } 1686 return; 1687 1688 invalid_pname: 1689 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)", 1690 _mesa_enum_to_string(pname)); 1691 } 1692 1693 1694 void 1695 _mesa_init_sampler_object_functions(struct dd_function_table *driver) 1696 { 1697 driver->NewSamplerObject = _mesa_new_sampler_object; 1698 } 1699