main/base_tex_format: Properly handle STENCIL_INDEX1/4/16
[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 #if 0
95 printf("SamplerObj %p %d DECR to %d\n",
96 (void *) oldSamp, oldSamp->Name, oldSamp->RefCount);
97 #endif
98 deleteFlag = (oldSamp->RefCount == 0);
99 /*mtx_unlock(&oldSamp->Mutex);*/
100
101 if (deleteFlag) {
102 assert(ctx->Driver.DeleteSamplerObject);
103 ctx->Driver.DeleteSamplerObject(ctx, oldSamp);
104 }
105
106 *ptr = NULL;
107 }
108 assert(!*ptr);
109
110 if (samp) {
111 /* reference new sampler */
112 /*mtx_lock(&samp->Mutex);*/
113 if (samp->RefCount == 0) {
114 /* this sampler's being deleted (look just above) */
115 /* Not sure this can every really happen. Warn if it does. */
116 _mesa_problem(NULL, "referencing deleted sampler object");
117 *ptr = NULL;
118 }
119 else {
120 samp->RefCount++;
121 #if 0
122 printf("SamplerObj %p %d INCR to %d\n",
123 (void *) samp, samp->Name, samp->RefCount);
124 #endif
125 *ptr = samp;
126 }
127 /*mtx_unlock(&samp->Mutex);*/
128 }
129 }
130
131
132 /**
133 * Initialize the fields of the given sampler object.
134 */
135 static void
136 _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
137 {
138 sampObj->Name = name;
139 sampObj->RefCount = 1;
140 sampObj->WrapS = GL_REPEAT;
141 sampObj->WrapT = GL_REPEAT;
142 sampObj->WrapR = GL_REPEAT;
143 sampObj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
144 sampObj->MagFilter = GL_LINEAR;
145 sampObj->BorderColor.f[0] = 0.0;
146 sampObj->BorderColor.f[1] = 0.0;
147 sampObj->BorderColor.f[2] = 0.0;
148 sampObj->BorderColor.f[3] = 0.0;
149 sampObj->MinLod = -1000.0F;
150 sampObj->MaxLod = 1000.0F;
151 sampObj->LodBias = 0.0F;
152 sampObj->MaxAnisotropy = 1.0F;
153 sampObj->CompareMode = GL_NONE;
154 sampObj->CompareFunc = GL_LEQUAL;
155 sampObj->sRGBDecode = GL_DECODE_EXT;
156 sampObj->CubeMapSeamless = GL_FALSE;
157 }
158
159 /**
160 * Fallback for ctx->Driver.NewSamplerObject();
161 */
162 struct gl_sampler_object *
163 _mesa_new_sampler_object(struct gl_context *ctx, GLuint name)
164 {
165 struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object);
166 if (sampObj) {
167 _mesa_init_sampler_object(sampObj, name);
168 }
169 return sampObj;
170 }
171
172
173 /**
174 * Fallback for ctx->Driver.DeleteSamplerObject();
175 */
176 static void
177 _mesa_delete_sampler_object(struct gl_context *ctx,
178 struct gl_sampler_object *sampObj)
179 {
180 free(sampObj->Label);
181 free(sampObj);
182 }
183
184
185 void GLAPIENTRY
186 _mesa_GenSamplers(GLsizei count, GLuint *samplers)
187 {
188 GET_CURRENT_CONTEXT(ctx);
189 GLuint first;
190 GLint i;
191
192 if (MESA_VERBOSE & VERBOSE_API)
193 _mesa_debug(ctx, "glGenSamplers(%d)\n", count);
194
195 if (count < 0) {
196 _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers");
197 return;
198 }
199
200 if (!samplers)
201 return;
202
203 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count);
204
205 /* Insert the ID and pointer to new sampler object into hash table */
206 for (i = 0; i < count; i++) {
207 struct gl_sampler_object *sampObj =
208 ctx->Driver.NewSamplerObject(ctx, first + i);
209 _mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj);
210 samplers[i] = first + i;
211 }
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
448 #define INVALID_PARAM 0x100
449 #define INVALID_PNAME 0x101
450 #define INVALID_VALUE 0x102
451
452 static GLuint
453 set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
454 GLint param)
455 {
456 if (samp->WrapS == param)
457 return GL_FALSE;
458 if (validate_texture_wrap_mode(ctx, param)) {
459 flush(ctx);
460 samp->WrapS = param;
461 return GL_TRUE;
462 }
463 return INVALID_PARAM;
464 }
465
466
467 static GLuint
468 set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
469 GLint param)
470 {
471 if (samp->WrapT == param)
472 return GL_FALSE;
473 if (validate_texture_wrap_mode(ctx, param)) {
474 flush(ctx);
475 samp->WrapT = param;
476 return GL_TRUE;
477 }
478 return INVALID_PARAM;
479 }
480
481
482 static GLuint
483 set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
484 GLint param)
485 {
486 if (samp->WrapR == param)
487 return GL_FALSE;
488 if (validate_texture_wrap_mode(ctx, param)) {
489 flush(ctx);
490 samp->WrapR = param;
491 return GL_TRUE;
492 }
493 return INVALID_PARAM;
494 }
495
496
497 static GLuint
498 set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
499 GLint param)
500 {
501 if (samp->MinFilter == param)
502 return GL_FALSE;
503
504 switch (param) {
505 case GL_NEAREST:
506 case GL_LINEAR:
507 case GL_NEAREST_MIPMAP_NEAREST:
508 case GL_LINEAR_MIPMAP_NEAREST:
509 case GL_NEAREST_MIPMAP_LINEAR:
510 case GL_LINEAR_MIPMAP_LINEAR:
511 flush(ctx);
512 samp->MinFilter = param;
513 return GL_TRUE;
514 default:
515 return INVALID_PARAM;
516 }
517 }
518
519
520 static GLuint
521 set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
522 GLint param)
523 {
524 if (samp->MagFilter == param)
525 return GL_FALSE;
526
527 switch (param) {
528 case GL_NEAREST:
529 case GL_LINEAR:
530 flush(ctx);
531 samp->MagFilter = param;
532 return GL_TRUE;
533 default:
534 return INVALID_PARAM;
535 }
536 }
537
538
539 static GLuint
540 set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
541 GLfloat param)
542 {
543 if (samp->LodBias == param)
544 return GL_FALSE;
545
546 flush(ctx);
547 samp->LodBias = param;
548 return GL_TRUE;
549 }
550
551
552 static GLuint
553 set_sampler_border_colorf(struct gl_context *ctx,
554 struct gl_sampler_object *samp,
555 const GLfloat params[4])
556 {
557 flush(ctx);
558 samp->BorderColor.f[RCOMP] = params[0];
559 samp->BorderColor.f[GCOMP] = params[1];
560 samp->BorderColor.f[BCOMP] = params[2];
561 samp->BorderColor.f[ACOMP] = params[3];
562 return GL_TRUE;
563 }
564
565
566 static GLuint
567 set_sampler_border_colori(struct gl_context *ctx,
568 struct gl_sampler_object *samp,
569 const GLint params[4])
570 {
571 flush(ctx);
572 samp->BorderColor.i[RCOMP] = params[0];
573 samp->BorderColor.i[GCOMP] = params[1];
574 samp->BorderColor.i[BCOMP] = params[2];
575 samp->BorderColor.i[ACOMP] = params[3];
576 return GL_TRUE;
577 }
578
579
580 static GLuint
581 set_sampler_border_colorui(struct gl_context *ctx,
582 struct gl_sampler_object *samp,
583 const GLuint params[4])
584 {
585 flush(ctx);
586 samp->BorderColor.ui[RCOMP] = params[0];
587 samp->BorderColor.ui[GCOMP] = params[1];
588 samp->BorderColor.ui[BCOMP] = params[2];
589 samp->BorderColor.ui[ACOMP] = params[3];
590 return GL_TRUE;
591 }
592
593
594 static GLuint
595 set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
596 GLfloat param)
597 {
598 if (samp->MinLod == param)
599 return GL_FALSE;
600
601 flush(ctx);
602 samp->MinLod = param;
603 return GL_TRUE;
604 }
605
606
607 static GLuint
608 set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
609 GLfloat param)
610 {
611 if (samp->MaxLod == param)
612 return GL_FALSE;
613
614 flush(ctx);
615 samp->MaxLod = param;
616 return GL_TRUE;
617 }
618
619
620 static GLuint
621 set_sampler_compare_mode(struct gl_context *ctx,
622 struct gl_sampler_object *samp, GLint param)
623 {
624 if (!ctx->Extensions.ARB_shadow)
625 return INVALID_PNAME;
626
627 if (samp->CompareMode == param)
628 return GL_FALSE;
629
630 if (param == GL_NONE ||
631 param == GL_COMPARE_R_TO_TEXTURE_ARB) {
632 flush(ctx);
633 samp->CompareMode = param;
634 return GL_TRUE;
635 }
636
637 return INVALID_PARAM;
638 }
639
640
641 static GLuint
642 set_sampler_compare_func(struct gl_context *ctx,
643 struct gl_sampler_object *samp, GLint param)
644 {
645 if (!ctx->Extensions.ARB_shadow)
646 return INVALID_PNAME;
647
648 if (samp->CompareFunc == param)
649 return GL_FALSE;
650
651 switch (param) {
652 case GL_LEQUAL:
653 case GL_GEQUAL:
654 case GL_EQUAL:
655 case GL_NOTEQUAL:
656 case GL_LESS:
657 case GL_GREATER:
658 case GL_ALWAYS:
659 case GL_NEVER:
660 flush(ctx);
661 samp->CompareFunc = param;
662 return GL_TRUE;
663 default:
664 return INVALID_PARAM;
665 }
666 }
667
668
669 static GLuint
670 set_sampler_max_anisotropy(struct gl_context *ctx,
671 struct gl_sampler_object *samp, GLfloat param)
672 {
673 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
674 return INVALID_PNAME;
675
676 if (samp->MaxAnisotropy == param)
677 return GL_FALSE;
678
679 if (param < 1.0)
680 return INVALID_VALUE;
681
682 flush(ctx);
683 /* clamp to max, that's what NVIDIA does */
684 samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
685 return GL_TRUE;
686 }
687
688
689 static GLuint
690 set_sampler_cube_map_seamless(struct gl_context *ctx,
691 struct gl_sampler_object *samp, GLboolean param)
692 {
693 if (!_mesa_is_desktop_gl(ctx)
694 || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
695 return INVALID_PNAME;
696
697 if (samp->CubeMapSeamless == param)
698 return GL_FALSE;
699
700 if (param != GL_TRUE && param != GL_FALSE)
701 return INVALID_VALUE;
702
703 flush(ctx);
704 samp->CubeMapSeamless = param;
705 return GL_TRUE;
706 }
707
708 static GLuint
709 set_sampler_srgb_decode(struct gl_context *ctx,
710 struct gl_sampler_object *samp, GLenum param)
711 {
712 if (!ctx->Extensions.EXT_texture_sRGB_decode)
713 return INVALID_PNAME;
714
715 if (samp->sRGBDecode == param)
716 return GL_FALSE;
717
718 if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
719 return INVALID_VALUE;
720
721 flush(ctx);
722 samp->sRGBDecode = param;
723 return GL_TRUE;
724 }
725
726 void GLAPIENTRY
727 _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
728 {
729 struct gl_sampler_object *sampObj;
730 GLuint res;
731 GET_CURRENT_CONTEXT(ctx);
732
733 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
734 if (!sampObj) {
735 /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
736 *
737 * "An INVALID_OPERATION error is generated if sampler is not the name
738 * of a sampler object previously returned from a call to GenSamplers."
739 *
740 * In desktop GL, an GL_INVALID_VALUE is returned instead.
741 */
742 _mesa_error(ctx, (_mesa_is_gles(ctx) ?
743 GL_INVALID_OPERATION : GL_INVALID_VALUE),
744 "glSamplerParameteri(sampler %u)", sampler);
745 return;
746 }
747
748 switch (pname) {
749 case GL_TEXTURE_WRAP_S:
750 res = set_sampler_wrap_s(ctx, sampObj, param);
751 break;
752 case GL_TEXTURE_WRAP_T:
753 res = set_sampler_wrap_t(ctx, sampObj, param);
754 break;
755 case GL_TEXTURE_WRAP_R:
756 res = set_sampler_wrap_r(ctx, sampObj, param);
757 break;
758 case GL_TEXTURE_MIN_FILTER:
759 res = set_sampler_min_filter(ctx, sampObj, param);
760 break;
761 case GL_TEXTURE_MAG_FILTER:
762 res = set_sampler_mag_filter(ctx, sampObj, param);
763 break;
764 case GL_TEXTURE_MIN_LOD:
765 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
766 break;
767 case GL_TEXTURE_MAX_LOD:
768 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
769 break;
770 case GL_TEXTURE_LOD_BIAS:
771 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
772 break;
773 case GL_TEXTURE_COMPARE_MODE:
774 res = set_sampler_compare_mode(ctx, sampObj, param);
775 break;
776 case GL_TEXTURE_COMPARE_FUNC:
777 res = set_sampler_compare_func(ctx, sampObj, param);
778 break;
779 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
780 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
781 break;
782 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
783 res = set_sampler_cube_map_seamless(ctx, sampObj, param);
784 break;
785 case GL_TEXTURE_SRGB_DECODE_EXT:
786 res = set_sampler_srgb_decode(ctx, sampObj, param);
787 break;
788 case GL_TEXTURE_BORDER_COLOR:
789 /* fall-through */
790 default:
791 res = INVALID_PNAME;
792 }
793
794 switch (res) {
795 case GL_FALSE:
796 /* no change */
797 break;
798 case GL_TRUE:
799 /* state change - we do nothing special at this time */
800 break;
801 case INVALID_PNAME:
802 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
803 _mesa_lookup_enum_by_nr(pname));
804 break;
805 case INVALID_PARAM:
806 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
807 param);
808 break;
809 case INVALID_VALUE:
810 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
811 param);
812 break;
813 default:
814 ;
815 }
816 }
817
818
819 void GLAPIENTRY
820 _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
821 {
822 struct gl_sampler_object *sampObj;
823 GLuint res;
824 GET_CURRENT_CONTEXT(ctx);
825
826 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
827 if (!sampObj) {
828 /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
829 *
830 * "An INVALID_OPERATION error is generated if sampler is not the name
831 * of a sampler object previously returned from a call to GenSamplers."
832 *
833 * In desktop GL, an GL_INVALID_VALUE is returned instead.
834 */
835 _mesa_error(ctx, (_mesa_is_gles(ctx) ?
836 GL_INVALID_OPERATION : GL_INVALID_VALUE),
837 "glSamplerParameterf(sampler %u)", sampler);
838 return;
839 }
840
841 switch (pname) {
842 case GL_TEXTURE_WRAP_S:
843 res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
844 break;
845 case GL_TEXTURE_WRAP_T:
846 res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
847 break;
848 case GL_TEXTURE_WRAP_R:
849 res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
850 break;
851 case GL_TEXTURE_MIN_FILTER:
852 res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
853 break;
854 case GL_TEXTURE_MAG_FILTER:
855 res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
856 break;
857 case GL_TEXTURE_MIN_LOD:
858 res = set_sampler_min_lod(ctx, sampObj, param);
859 break;
860 case GL_TEXTURE_MAX_LOD:
861 res = set_sampler_max_lod(ctx, sampObj, param);
862 break;
863 case GL_TEXTURE_LOD_BIAS:
864 res = set_sampler_lod_bias(ctx, sampObj, param);
865 break;
866 case GL_TEXTURE_COMPARE_MODE:
867 res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
868 break;
869 case GL_TEXTURE_COMPARE_FUNC:
870 res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
871 break;
872 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
873 res = set_sampler_max_anisotropy(ctx, sampObj, param);
874 break;
875 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
876 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) param);
877 break;
878 case GL_TEXTURE_SRGB_DECODE_EXT:
879 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) param);
880 break;
881 case GL_TEXTURE_BORDER_COLOR:
882 /* fall-through */
883 default:
884 res = INVALID_PNAME;
885 }
886
887 switch (res) {
888 case GL_FALSE:
889 /* no change */
890 break;
891 case GL_TRUE:
892 /* state change - we do nothing special at this time */
893 break;
894 case INVALID_PNAME:
895 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
896 _mesa_lookup_enum_by_nr(pname));
897 break;
898 case INVALID_PARAM:
899 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
900 param);
901 break;
902 case INVALID_VALUE:
903 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
904 param);
905 break;
906 default:
907 ;
908 }
909 }
910
911 void GLAPIENTRY
912 _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
913 {
914 struct gl_sampler_object *sampObj;
915 GLuint res;
916 GET_CURRENT_CONTEXT(ctx);
917
918 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
919 if (!sampObj) {
920 /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
921 *
922 * "An INVALID_OPERATION error is generated if sampler is not the name
923 * of a sampler object previously returned from a call to GenSamplers."
924 *
925 * In desktop GL, an GL_INVALID_VALUE is returned instead.
926 */
927 _mesa_error(ctx, (_mesa_is_gles(ctx) ?
928 GL_INVALID_OPERATION : GL_INVALID_VALUE),
929 "glSamplerParameteriv(sampler %u)", sampler);
930 return;
931 }
932
933 switch (pname) {
934 case GL_TEXTURE_WRAP_S:
935 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
936 break;
937 case GL_TEXTURE_WRAP_T:
938 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
939 break;
940 case GL_TEXTURE_WRAP_R:
941 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
942 break;
943 case GL_TEXTURE_MIN_FILTER:
944 res = set_sampler_min_filter(ctx, sampObj, params[0]);
945 break;
946 case GL_TEXTURE_MAG_FILTER:
947 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
948 break;
949 case GL_TEXTURE_MIN_LOD:
950 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
951 break;
952 case GL_TEXTURE_MAX_LOD:
953 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
954 break;
955 case GL_TEXTURE_LOD_BIAS:
956 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
957 break;
958 case GL_TEXTURE_COMPARE_MODE:
959 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
960 break;
961 case GL_TEXTURE_COMPARE_FUNC:
962 res = set_sampler_compare_func(ctx, sampObj, params[0]);
963 break;
964 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
965 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
966 break;
967 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
968 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
969 break;
970 case GL_TEXTURE_SRGB_DECODE_EXT:
971 res = set_sampler_srgb_decode(ctx, sampObj, params[0]);
972 break;
973 case GL_TEXTURE_BORDER_COLOR:
974 {
975 GLfloat c[4];
976 c[0] = INT_TO_FLOAT(params[0]);
977 c[1] = INT_TO_FLOAT(params[1]);
978 c[2] = INT_TO_FLOAT(params[2]);
979 c[3] = INT_TO_FLOAT(params[3]);
980 res = set_sampler_border_colorf(ctx, sampObj, c);
981 }
982 break;
983 default:
984 res = INVALID_PNAME;
985 }
986
987 switch (res) {
988 case GL_FALSE:
989 /* no change */
990 break;
991 case GL_TRUE:
992 /* state change - we do nothing special at this time */
993 break;
994 case INVALID_PNAME:
995 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
996 _mesa_lookup_enum_by_nr(pname));
997 break;
998 case INVALID_PARAM:
999 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
1000 params[0]);
1001 break;
1002 case INVALID_VALUE:
1003 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
1004 params[0]);
1005 break;
1006 default:
1007 ;
1008 }
1009 }
1010
1011 void GLAPIENTRY
1012 _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
1013 {
1014 struct gl_sampler_object *sampObj;
1015 GLuint res;
1016 GET_CURRENT_CONTEXT(ctx);
1017
1018 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1019 if (!sampObj) {
1020 /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
1021 *
1022 * "An INVALID_OPERATION error is generated if sampler is not the name
1023 * of a sampler object previously returned from a call to GenSamplers."
1024 *
1025 * In desktop GL, an GL_INVALID_VALUE is returned instead.
1026 */
1027 _mesa_error(ctx, (_mesa_is_gles(ctx) ?
1028 GL_INVALID_OPERATION : GL_INVALID_VALUE),
1029 "glSamplerParameterfv(sampler %u)", sampler);
1030 return;
1031 }
1032
1033 switch (pname) {
1034 case GL_TEXTURE_WRAP_S:
1035 res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
1036 break;
1037 case GL_TEXTURE_WRAP_T:
1038 res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
1039 break;
1040 case GL_TEXTURE_WRAP_R:
1041 res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
1042 break;
1043 case GL_TEXTURE_MIN_FILTER:
1044 res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
1045 break;
1046 case GL_TEXTURE_MAG_FILTER:
1047 res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
1048 break;
1049 case GL_TEXTURE_MIN_LOD:
1050 res = set_sampler_min_lod(ctx, sampObj, params[0]);
1051 break;
1052 case GL_TEXTURE_MAX_LOD:
1053 res = set_sampler_max_lod(ctx, sampObj, params[0]);
1054 break;
1055 case GL_TEXTURE_LOD_BIAS:
1056 res = set_sampler_lod_bias(ctx, sampObj, params[0]);
1057 break;
1058 case GL_TEXTURE_COMPARE_MODE:
1059 res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
1060 break;
1061 case GL_TEXTURE_COMPARE_FUNC:
1062 res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
1063 break;
1064 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1065 res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
1066 break;
1067 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1068 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]);
1069 break;
1070 case GL_TEXTURE_SRGB_DECODE_EXT:
1071 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1072 break;
1073 case GL_TEXTURE_BORDER_COLOR:
1074 res = set_sampler_border_colorf(ctx, sampObj, params);
1075 break;
1076 default:
1077 res = INVALID_PNAME;
1078 }
1079
1080 switch (res) {
1081 case GL_FALSE:
1082 /* no change */
1083 break;
1084 case GL_TRUE:
1085 /* state change - we do nothing special at this time */
1086 break;
1087 case INVALID_PNAME:
1088 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
1089 _mesa_lookup_enum_by_nr(pname));
1090 break;
1091 case INVALID_PARAM:
1092 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
1093 params[0]);
1094 break;
1095 case INVALID_VALUE:
1096 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
1097 params[0]);
1098 break;
1099 default:
1100 ;
1101 }
1102 }
1103
1104 void GLAPIENTRY
1105 _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
1106 {
1107 struct gl_sampler_object *sampObj;
1108 GLuint res;
1109 GET_CURRENT_CONTEXT(ctx);
1110
1111 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1112 if (!sampObj) {
1113 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(sampler %u)",
1114 sampler);
1115 return;
1116 }
1117
1118 switch (pname) {
1119 case GL_TEXTURE_WRAP_S:
1120 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1121 break;
1122 case GL_TEXTURE_WRAP_T:
1123 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1124 break;
1125 case GL_TEXTURE_WRAP_R:
1126 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1127 break;
1128 case GL_TEXTURE_MIN_FILTER:
1129 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1130 break;
1131 case GL_TEXTURE_MAG_FILTER:
1132 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1133 break;
1134 case GL_TEXTURE_MIN_LOD:
1135 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1136 break;
1137 case GL_TEXTURE_MAX_LOD:
1138 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1139 break;
1140 case GL_TEXTURE_LOD_BIAS:
1141 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1142 break;
1143 case GL_TEXTURE_COMPARE_MODE:
1144 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1145 break;
1146 case GL_TEXTURE_COMPARE_FUNC:
1147 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1148 break;
1149 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1150 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1151 break;
1152 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1153 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1154 break;
1155 case GL_TEXTURE_SRGB_DECODE_EXT:
1156 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1157 break;
1158 case GL_TEXTURE_BORDER_COLOR:
1159 res = set_sampler_border_colori(ctx, sampObj, params);
1160 break;
1161 default:
1162 res = INVALID_PNAME;
1163 }
1164
1165 switch (res) {
1166 case GL_FALSE:
1167 /* no change */
1168 break;
1169 case GL_TRUE:
1170 /* state change - we do nothing special at this time */
1171 break;
1172 case INVALID_PNAME:
1173 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
1174 _mesa_lookup_enum_by_nr(pname));
1175 break;
1176 case INVALID_PARAM:
1177 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
1178 params[0]);
1179 break;
1180 case INVALID_VALUE:
1181 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
1182 params[0]);
1183 break;
1184 default:
1185 ;
1186 }
1187 }
1188
1189
1190 void GLAPIENTRY
1191 _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
1192 {
1193 struct gl_sampler_object *sampObj;
1194 GLuint res;
1195 GET_CURRENT_CONTEXT(ctx);
1196
1197 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1198 if (!sampObj) {
1199 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(sampler %u)",
1200 sampler);
1201 return;
1202 }
1203
1204 switch (pname) {
1205 case GL_TEXTURE_WRAP_S:
1206 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1207 break;
1208 case GL_TEXTURE_WRAP_T:
1209 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1210 break;
1211 case GL_TEXTURE_WRAP_R:
1212 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1213 break;
1214 case GL_TEXTURE_MIN_FILTER:
1215 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1216 break;
1217 case GL_TEXTURE_MAG_FILTER:
1218 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1219 break;
1220 case GL_TEXTURE_MIN_LOD:
1221 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1222 break;
1223 case GL_TEXTURE_MAX_LOD:
1224 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1225 break;
1226 case GL_TEXTURE_LOD_BIAS:
1227 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1228 break;
1229 case GL_TEXTURE_COMPARE_MODE:
1230 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1231 break;
1232 case GL_TEXTURE_COMPARE_FUNC:
1233 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1234 break;
1235 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1236 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1237 break;
1238 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1239 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1240 break;
1241 case GL_TEXTURE_SRGB_DECODE_EXT:
1242 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1243 break;
1244 case GL_TEXTURE_BORDER_COLOR:
1245 res = set_sampler_border_colorui(ctx, sampObj, params);
1246 break;
1247 default:
1248 res = INVALID_PNAME;
1249 }
1250
1251 switch (res) {
1252 case GL_FALSE:
1253 /* no change */
1254 break;
1255 case GL_TRUE:
1256 /* state change - we do nothing special at this time */
1257 break;
1258 case INVALID_PNAME:
1259 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
1260 _mesa_lookup_enum_by_nr(pname));
1261 break;
1262 case INVALID_PARAM:
1263 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
1264 params[0]);
1265 break;
1266 case INVALID_VALUE:
1267 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
1268 params[0]);
1269 break;
1270 default:
1271 ;
1272 }
1273 }
1274
1275
1276 void GLAPIENTRY
1277 _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
1278 {
1279 struct gl_sampler_object *sampObj;
1280 GET_CURRENT_CONTEXT(ctx);
1281
1282 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1283 if (!sampObj) {
1284 /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
1285 *
1286 * "An INVALID_OPERATION error is generated if sampler is not the name
1287 * of a sampler object previously returned from a call to GenSamplers."
1288 *
1289 * In desktop GL, an GL_INVALID_VALUE is returned instead.
1290 */
1291 _mesa_error(ctx, (_mesa_is_gles(ctx) ?
1292 GL_INVALID_OPERATION : GL_INVALID_VALUE),
1293 "glGetSamplerParameteriv(sampler %u)", sampler);
1294 return;
1295 }
1296
1297 switch (pname) {
1298 case GL_TEXTURE_WRAP_S:
1299 *params = sampObj->WrapS;
1300 break;
1301 case GL_TEXTURE_WRAP_T:
1302 *params = sampObj->WrapT;
1303 break;
1304 case GL_TEXTURE_WRAP_R:
1305 *params = sampObj->WrapR;
1306 break;
1307 case GL_TEXTURE_MIN_FILTER:
1308 *params = sampObj->MinFilter;
1309 break;
1310 case GL_TEXTURE_MAG_FILTER:
1311 *params = sampObj->MagFilter;
1312 break;
1313 case GL_TEXTURE_MIN_LOD:
1314 /* GL spec 'Data Conversions' section specifies that floating-point
1315 * value in integer Get function is rounded to nearest integer
1316 */
1317 *params = IROUND(sampObj->MinLod);
1318 break;
1319 case GL_TEXTURE_MAX_LOD:
1320 /* GL spec 'Data Conversions' section specifies that floating-point
1321 * value in integer Get function is rounded to nearest integer
1322 */
1323 *params = IROUND(sampObj->MaxLod);
1324 break;
1325 case GL_TEXTURE_LOD_BIAS:
1326 /* GL spec 'Data Conversions' section specifies that floating-point
1327 * value in integer Get function is rounded to nearest integer
1328 */
1329 *params = IROUND(sampObj->LodBias);
1330 break;
1331 case GL_TEXTURE_COMPARE_MODE:
1332 if (!ctx->Extensions.ARB_shadow)
1333 goto invalid_pname;
1334 *params = sampObj->CompareMode;
1335 break;
1336 case GL_TEXTURE_COMPARE_FUNC:
1337 if (!ctx->Extensions.ARB_shadow)
1338 goto invalid_pname;
1339 *params = sampObj->CompareFunc;
1340 break;
1341 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1342 /* GL spec 'Data Conversions' section specifies that floating-point
1343 * value in integer Get function is rounded to nearest integer
1344 */
1345 *params = IROUND(sampObj->MaxAnisotropy);
1346 break;
1347 case GL_TEXTURE_BORDER_COLOR:
1348 params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
1349 params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
1350 params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
1351 params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
1352 break;
1353 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1354 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1355 goto invalid_pname;
1356 *params = sampObj->CubeMapSeamless;
1357 break;
1358 case GL_TEXTURE_SRGB_DECODE_EXT:
1359 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1360 goto invalid_pname;
1361 *params = (GLenum) sampObj->sRGBDecode;
1362 break;
1363 default:
1364 goto invalid_pname;
1365 }
1366 return;
1367
1368 invalid_pname:
1369 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
1370 _mesa_lookup_enum_by_nr(pname));
1371 }
1372
1373
1374 void GLAPIENTRY
1375 _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
1376 {
1377 struct gl_sampler_object *sampObj;
1378 GET_CURRENT_CONTEXT(ctx);
1379
1380 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1381 if (!sampObj) {
1382 /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
1383 *
1384 * "An INVALID_OPERATION error is generated if sampler is not the name
1385 * of a sampler object previously returned from a call to GenSamplers."
1386 *
1387 * In desktop GL, an GL_INVALID_VALUE is returned instead.
1388 */
1389 _mesa_error(ctx, (_mesa_is_gles(ctx) ?
1390 GL_INVALID_OPERATION : GL_INVALID_VALUE),
1391 "glGetSamplerParameterfv(sampler %u)", sampler);
1392 return;
1393 }
1394
1395 switch (pname) {
1396 case GL_TEXTURE_WRAP_S:
1397 *params = (GLfloat) sampObj->WrapS;
1398 break;
1399 case GL_TEXTURE_WRAP_T:
1400 *params = (GLfloat) sampObj->WrapT;
1401 break;
1402 case GL_TEXTURE_WRAP_R:
1403 *params = (GLfloat) sampObj->WrapR;
1404 break;
1405 case GL_TEXTURE_MIN_FILTER:
1406 *params = (GLfloat) sampObj->MinFilter;
1407 break;
1408 case GL_TEXTURE_MAG_FILTER:
1409 *params = (GLfloat) sampObj->MagFilter;
1410 break;
1411 case GL_TEXTURE_MIN_LOD:
1412 *params = sampObj->MinLod;
1413 break;
1414 case GL_TEXTURE_MAX_LOD:
1415 *params = sampObj->MaxLod;
1416 break;
1417 case GL_TEXTURE_LOD_BIAS:
1418 *params = sampObj->LodBias;
1419 break;
1420 case GL_TEXTURE_COMPARE_MODE:
1421 if (!ctx->Extensions.ARB_shadow)
1422 goto invalid_pname;
1423 *params = (GLfloat) sampObj->CompareMode;
1424 break;
1425 case GL_TEXTURE_COMPARE_FUNC:
1426 if (!ctx->Extensions.ARB_shadow)
1427 goto invalid_pname;
1428 *params = (GLfloat) sampObj->CompareFunc;
1429 break;
1430 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1431 *params = sampObj->MaxAnisotropy;
1432 break;
1433 case GL_TEXTURE_BORDER_COLOR:
1434 params[0] = sampObj->BorderColor.f[0];
1435 params[1] = sampObj->BorderColor.f[1];
1436 params[2] = sampObj->BorderColor.f[2];
1437 params[3] = sampObj->BorderColor.f[3];
1438 break;
1439 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1440 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1441 goto invalid_pname;
1442 *params = (GLfloat) sampObj->CubeMapSeamless;
1443 break;
1444 case GL_TEXTURE_SRGB_DECODE_EXT:
1445 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1446 goto invalid_pname;
1447 *params = (GLfloat) sampObj->sRGBDecode;
1448 break;
1449 default:
1450 goto invalid_pname;
1451 }
1452 return;
1453
1454 invalid_pname:
1455 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
1456 _mesa_lookup_enum_by_nr(pname));
1457 }
1458
1459
1460 void GLAPIENTRY
1461 _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
1462 {
1463 struct gl_sampler_object *sampObj;
1464 GET_CURRENT_CONTEXT(ctx);
1465
1466 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1467 if (!sampObj) {
1468 _mesa_error(ctx, GL_INVALID_VALUE,
1469 "glGetSamplerParameterIiv(sampler %u)",
1470 sampler);
1471 return;
1472 }
1473
1474 switch (pname) {
1475 case GL_TEXTURE_WRAP_S:
1476 *params = sampObj->WrapS;
1477 break;
1478 case GL_TEXTURE_WRAP_T:
1479 *params = sampObj->WrapT;
1480 break;
1481 case GL_TEXTURE_WRAP_R:
1482 *params = sampObj->WrapR;
1483 break;
1484 case GL_TEXTURE_MIN_FILTER:
1485 *params = sampObj->MinFilter;
1486 break;
1487 case GL_TEXTURE_MAG_FILTER:
1488 *params = sampObj->MagFilter;
1489 break;
1490 case GL_TEXTURE_MIN_LOD:
1491 *params = (GLint) sampObj->MinLod;
1492 break;
1493 case GL_TEXTURE_MAX_LOD:
1494 *params = (GLint) sampObj->MaxLod;
1495 break;
1496 case GL_TEXTURE_LOD_BIAS:
1497 *params = (GLint) sampObj->LodBias;
1498 break;
1499 case GL_TEXTURE_COMPARE_MODE:
1500 if (!ctx->Extensions.ARB_shadow)
1501 goto invalid_pname;
1502 *params = sampObj->CompareMode;
1503 break;
1504 case GL_TEXTURE_COMPARE_FUNC:
1505 if (!ctx->Extensions.ARB_shadow)
1506 goto invalid_pname;
1507 *params = sampObj->CompareFunc;
1508 break;
1509 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1510 *params = (GLint) sampObj->MaxAnisotropy;
1511 break;
1512 case GL_TEXTURE_BORDER_COLOR:
1513 params[0] = sampObj->BorderColor.i[0];
1514 params[1] = sampObj->BorderColor.i[1];
1515 params[2] = sampObj->BorderColor.i[2];
1516 params[3] = sampObj->BorderColor.i[3];
1517 break;
1518 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1519 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1520 goto invalid_pname;
1521 *params = sampObj->CubeMapSeamless;
1522 break;
1523 case GL_TEXTURE_SRGB_DECODE_EXT:
1524 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1525 goto invalid_pname;
1526 *params = (GLenum) sampObj->sRGBDecode;
1527 break;
1528 default:
1529 goto invalid_pname;
1530 }
1531 return;
1532
1533 invalid_pname:
1534 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
1535 _mesa_lookup_enum_by_nr(pname));
1536 }
1537
1538
1539 void GLAPIENTRY
1540 _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
1541 {
1542 struct gl_sampler_object *sampObj;
1543 GET_CURRENT_CONTEXT(ctx);
1544
1545 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1546 if (!sampObj) {
1547 _mesa_error(ctx, GL_INVALID_VALUE,
1548 "glGetSamplerParameterIuiv(sampler %u)",
1549 sampler);
1550 return;
1551 }
1552
1553 switch (pname) {
1554 case GL_TEXTURE_WRAP_S:
1555 *params = sampObj->WrapS;
1556 break;
1557 case GL_TEXTURE_WRAP_T:
1558 *params = sampObj->WrapT;
1559 break;
1560 case GL_TEXTURE_WRAP_R:
1561 *params = sampObj->WrapR;
1562 break;
1563 case GL_TEXTURE_MIN_FILTER:
1564 *params = sampObj->MinFilter;
1565 break;
1566 case GL_TEXTURE_MAG_FILTER:
1567 *params = sampObj->MagFilter;
1568 break;
1569 case GL_TEXTURE_MIN_LOD:
1570 *params = (GLuint) sampObj->MinLod;
1571 break;
1572 case GL_TEXTURE_MAX_LOD:
1573 *params = (GLuint) sampObj->MaxLod;
1574 break;
1575 case GL_TEXTURE_LOD_BIAS:
1576 *params = (GLuint) sampObj->LodBias;
1577 break;
1578 case GL_TEXTURE_COMPARE_MODE:
1579 if (!ctx->Extensions.ARB_shadow)
1580 goto invalid_pname;
1581 *params = sampObj->CompareMode;
1582 break;
1583 case GL_TEXTURE_COMPARE_FUNC:
1584 if (!ctx->Extensions.ARB_shadow)
1585 goto invalid_pname;
1586 *params = sampObj->CompareFunc;
1587 break;
1588 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1589 *params = (GLuint) sampObj->MaxAnisotropy;
1590 break;
1591 case GL_TEXTURE_BORDER_COLOR:
1592 params[0] = sampObj->BorderColor.ui[0];
1593 params[1] = sampObj->BorderColor.ui[1];
1594 params[2] = sampObj->BorderColor.ui[2];
1595 params[3] = sampObj->BorderColor.ui[3];
1596 break;
1597 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1598 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1599 goto invalid_pname;
1600 *params = sampObj->CubeMapSeamless;
1601 break;
1602 case GL_TEXTURE_SRGB_DECODE_EXT:
1603 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1604 goto invalid_pname;
1605 *params = (GLenum) sampObj->sRGBDecode;
1606 break;
1607 default:
1608 goto invalid_pname;
1609 }
1610 return;
1611
1612 invalid_pname:
1613 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
1614 _mesa_lookup_enum_by_nr(pname));
1615 }
1616
1617
1618 void
1619 _mesa_init_sampler_object_functions(struct dd_function_table *driver)
1620 {
1621 driver->NewSamplerObject = _mesa_new_sampler_object;
1622 driver->DeleteSamplerObject = _mesa_delete_sampler_object;
1623 }