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