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