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