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