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