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