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