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