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