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