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