mesa/main: remove useless check in _mesa_IsSampler()
[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 GET_CURRENT_CONTEXT(ctx);
274
275 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
276
277 return _mesa_lookup_samplerobj(ctx, sampler) != NULL;
278 }
279
280 void
281 _mesa_bind_sampler(struct gl_context *ctx, GLuint unit,
282 struct gl_sampler_object *sampObj)
283 {
284 if (ctx->Texture.Unit[unit].Sampler != sampObj) {
285 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
286 }
287
288 _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler,
289 sampObj);
290 }
291
292 void GLAPIENTRY
293 _mesa_BindSampler(GLuint unit, GLuint sampler)
294 {
295 struct gl_sampler_object *sampObj;
296 GET_CURRENT_CONTEXT(ctx);
297
298 if (unit >= ctx->Const.MaxCombinedTextureImageUnits) {
299 _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
300 return;
301 }
302
303 if (sampler == 0) {
304 /* Use the default sampler object, the one contained in the texture
305 * object.
306 */
307 sampObj = NULL;
308 }
309 else {
310 /* user-defined sampler object */
311 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
312 if (!sampObj) {
313 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)");
314 return;
315 }
316 }
317
318 /* bind new sampler */
319 _mesa_bind_sampler(ctx, unit, 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 void
461 _mesa_set_sampler_wrap(struct gl_context *ctx, struct gl_sampler_object *samp,
462 GLenum s, GLenum t, GLenum r)
463 {
464 assert(validate_texture_wrap_mode(ctx, s));
465 assert(validate_texture_wrap_mode(ctx, t));
466 assert(validate_texture_wrap_mode(ctx, r));
467
468 if (samp->WrapS == s && samp->WrapT == t && samp->WrapR == r)
469 return;
470
471 flush(ctx);
472 samp->WrapS = s;
473 samp->WrapT = t;
474 samp->WrapR = r;
475 }
476
477 #define INVALID_PARAM 0x100
478 #define INVALID_PNAME 0x101
479 #define INVALID_VALUE 0x102
480
481 static GLuint
482 set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
483 GLint param)
484 {
485 if (samp->WrapS == param)
486 return GL_FALSE;
487 if (validate_texture_wrap_mode(ctx, param)) {
488 flush(ctx);
489 samp->WrapS = param;
490 return GL_TRUE;
491 }
492 return INVALID_PARAM;
493 }
494
495
496 static GLuint
497 set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
498 GLint param)
499 {
500 if (samp->WrapT == param)
501 return GL_FALSE;
502 if (validate_texture_wrap_mode(ctx, param)) {
503 flush(ctx);
504 samp->WrapT = param;
505 return GL_TRUE;
506 }
507 return INVALID_PARAM;
508 }
509
510
511 static GLuint
512 set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
513 GLint param)
514 {
515 if (samp->WrapR == param)
516 return GL_FALSE;
517 if (validate_texture_wrap_mode(ctx, param)) {
518 flush(ctx);
519 samp->WrapR = param;
520 return GL_TRUE;
521 }
522 return INVALID_PARAM;
523 }
524
525 void
526 _mesa_set_sampler_filters(struct gl_context *ctx,
527 struct gl_sampler_object *samp,
528 GLenum min_filter, GLenum mag_filter)
529 {
530 assert(min_filter == GL_NEAREST ||
531 min_filter == GL_LINEAR ||
532 min_filter == GL_NEAREST_MIPMAP_NEAREST ||
533 min_filter == GL_LINEAR_MIPMAP_NEAREST ||
534 min_filter == GL_NEAREST_MIPMAP_LINEAR ||
535 min_filter == GL_LINEAR_MIPMAP_LINEAR);
536 assert(mag_filter == GL_NEAREST ||
537 mag_filter == GL_LINEAR);
538
539 if (samp->MinFilter == min_filter && samp->MagFilter == mag_filter)
540 return;
541
542 flush(ctx);
543 samp->MinFilter = min_filter;
544 samp->MagFilter = mag_filter;
545 }
546
547 static GLuint
548 set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
549 GLint param)
550 {
551 if (samp->MinFilter == param)
552 return GL_FALSE;
553
554 switch (param) {
555 case GL_NEAREST:
556 case GL_LINEAR:
557 case GL_NEAREST_MIPMAP_NEAREST:
558 case GL_LINEAR_MIPMAP_NEAREST:
559 case GL_NEAREST_MIPMAP_LINEAR:
560 case GL_LINEAR_MIPMAP_LINEAR:
561 flush(ctx);
562 samp->MinFilter = param;
563 return GL_TRUE;
564 default:
565 return INVALID_PARAM;
566 }
567 }
568
569
570 static GLuint
571 set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
572 GLint param)
573 {
574 if (samp->MagFilter == param)
575 return GL_FALSE;
576
577 switch (param) {
578 case GL_NEAREST:
579 case GL_LINEAR:
580 flush(ctx);
581 samp->MagFilter = param;
582 return GL_TRUE;
583 default:
584 return INVALID_PARAM;
585 }
586 }
587
588
589 static GLuint
590 set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
591 GLfloat param)
592 {
593 if (samp->LodBias == param)
594 return GL_FALSE;
595
596 flush(ctx);
597 samp->LodBias = param;
598 return GL_TRUE;
599 }
600
601
602 static GLuint
603 set_sampler_border_colorf(struct gl_context *ctx,
604 struct gl_sampler_object *samp,
605 const GLfloat params[4])
606 {
607 flush(ctx);
608 samp->BorderColor.f[RCOMP] = params[0];
609 samp->BorderColor.f[GCOMP] = params[1];
610 samp->BorderColor.f[BCOMP] = params[2];
611 samp->BorderColor.f[ACOMP] = params[3];
612 return GL_TRUE;
613 }
614
615
616 static GLuint
617 set_sampler_border_colori(struct gl_context *ctx,
618 struct gl_sampler_object *samp,
619 const GLint params[4])
620 {
621 flush(ctx);
622 samp->BorderColor.i[RCOMP] = params[0];
623 samp->BorderColor.i[GCOMP] = params[1];
624 samp->BorderColor.i[BCOMP] = params[2];
625 samp->BorderColor.i[ACOMP] = params[3];
626 return GL_TRUE;
627 }
628
629
630 static GLuint
631 set_sampler_border_colorui(struct gl_context *ctx,
632 struct gl_sampler_object *samp,
633 const GLuint params[4])
634 {
635 flush(ctx);
636 samp->BorderColor.ui[RCOMP] = params[0];
637 samp->BorderColor.ui[GCOMP] = params[1];
638 samp->BorderColor.ui[BCOMP] = params[2];
639 samp->BorderColor.ui[ACOMP] = params[3];
640 return GL_TRUE;
641 }
642
643
644 static GLuint
645 set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
646 GLfloat param)
647 {
648 if (samp->MinLod == param)
649 return GL_FALSE;
650
651 flush(ctx);
652 samp->MinLod = param;
653 return GL_TRUE;
654 }
655
656
657 static GLuint
658 set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
659 GLfloat param)
660 {
661 if (samp->MaxLod == param)
662 return GL_FALSE;
663
664 flush(ctx);
665 samp->MaxLod = param;
666 return GL_TRUE;
667 }
668
669
670 static GLuint
671 set_sampler_compare_mode(struct gl_context *ctx,
672 struct gl_sampler_object *samp, GLint param)
673 {
674 /* If GL_ARB_shadow is not supported, don't report an error. The
675 * sampler object extension spec isn't clear on this extension interaction.
676 * Silences errors with Wine on older GPUs such as R200.
677 */
678 if (!ctx->Extensions.ARB_shadow)
679 return GL_FALSE;
680
681 if (samp->CompareMode == param)
682 return GL_FALSE;
683
684 if (param == GL_NONE ||
685 param == GL_COMPARE_R_TO_TEXTURE_ARB) {
686 flush(ctx);
687 samp->CompareMode = param;
688 return GL_TRUE;
689 }
690
691 return INVALID_PARAM;
692 }
693
694
695 static GLuint
696 set_sampler_compare_func(struct gl_context *ctx,
697 struct gl_sampler_object *samp, GLint param)
698 {
699 /* If GL_ARB_shadow is not supported, don't report an error. The
700 * sampler object extension spec isn't clear on this extension interaction.
701 * Silences errors with Wine on older GPUs such as R200.
702 */
703 if (!ctx->Extensions.ARB_shadow)
704 return GL_FALSE;
705
706 if (samp->CompareFunc == param)
707 return GL_FALSE;
708
709 switch (param) {
710 case GL_LEQUAL:
711 case GL_GEQUAL:
712 case GL_EQUAL:
713 case GL_NOTEQUAL:
714 case GL_LESS:
715 case GL_GREATER:
716 case GL_ALWAYS:
717 case GL_NEVER:
718 flush(ctx);
719 samp->CompareFunc = param;
720 return GL_TRUE;
721 default:
722 return INVALID_PARAM;
723 }
724 }
725
726
727 static GLuint
728 set_sampler_max_anisotropy(struct gl_context *ctx,
729 struct gl_sampler_object *samp, GLfloat param)
730 {
731 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
732 return INVALID_PNAME;
733
734 if (samp->MaxAnisotropy == param)
735 return GL_FALSE;
736
737 if (param < 1.0F)
738 return INVALID_VALUE;
739
740 flush(ctx);
741 /* clamp to max, that's what NVIDIA does */
742 samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
743 return GL_TRUE;
744 }
745
746
747 static GLuint
748 set_sampler_cube_map_seamless(struct gl_context *ctx,
749 struct gl_sampler_object *samp, GLboolean param)
750 {
751 if (!_mesa_is_desktop_gl(ctx)
752 || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
753 return INVALID_PNAME;
754
755 if (samp->CubeMapSeamless == param)
756 return GL_FALSE;
757
758 if (param != GL_TRUE && param != GL_FALSE)
759 return INVALID_VALUE;
760
761 flush(ctx);
762 samp->CubeMapSeamless = param;
763 return GL_TRUE;
764 }
765
766 void
767 _mesa_set_sampler_srgb_decode(struct gl_context *ctx,
768 struct gl_sampler_object *samp, GLenum param)
769 {
770 assert(param == GL_DECODE_EXT || param == GL_SKIP_DECODE_EXT);
771
772 flush(ctx);
773 samp->sRGBDecode = param;
774 }
775
776 static GLuint
777 set_sampler_srgb_decode(struct gl_context *ctx,
778 struct gl_sampler_object *samp, GLenum param)
779 {
780 if (!ctx->Extensions.EXT_texture_sRGB_decode)
781 return INVALID_PNAME;
782
783 if (samp->sRGBDecode == param)
784 return GL_FALSE;
785
786 if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
787 return INVALID_VALUE;
788
789 flush(ctx);
790 samp->sRGBDecode = param;
791 return GL_TRUE;
792 }
793
794 static struct gl_sampler_object *
795 sampler_parameter_error_check(struct gl_context *ctx, GLuint sampler,
796 const char *name)
797 {
798 struct gl_sampler_object *sampObj;
799
800 sampObj = _mesa_lookup_samplerobj(ctx, sampler);
801 if (!sampObj) {
802 /* OpenGL 4.5 spec, section "8.2 Sampler Objects", page 176 of the PDF
803 * states:
804 *
805 * "An INVALID_OPERATION error is generated if sampler is not the name
806 * of a sampler object previously returned from a call to
807 * GenSamplers."
808 */
809 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid sampler)", name);
810 return NULL;
811 }
812
813 return sampObj;
814 }
815
816 void GLAPIENTRY
817 _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
818 {
819 struct gl_sampler_object *sampObj;
820 GLuint res;
821 GET_CURRENT_CONTEXT(ctx);
822
823 sampObj = sampler_parameter_error_check(ctx, sampler,
824 "glSamplerParameteri");
825 if (!sampObj)
826 return;
827
828 switch (pname) {
829 case GL_TEXTURE_WRAP_S:
830 res = set_sampler_wrap_s(ctx, sampObj, param);
831 break;
832 case GL_TEXTURE_WRAP_T:
833 res = set_sampler_wrap_t(ctx, sampObj, param);
834 break;
835 case GL_TEXTURE_WRAP_R:
836 res = set_sampler_wrap_r(ctx, sampObj, param);
837 break;
838 case GL_TEXTURE_MIN_FILTER:
839 res = set_sampler_min_filter(ctx, sampObj, param);
840 break;
841 case GL_TEXTURE_MAG_FILTER:
842 res = set_sampler_mag_filter(ctx, sampObj, param);
843 break;
844 case GL_TEXTURE_MIN_LOD:
845 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
846 break;
847 case GL_TEXTURE_MAX_LOD:
848 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
849 break;
850 case GL_TEXTURE_LOD_BIAS:
851 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
852 break;
853 case GL_TEXTURE_COMPARE_MODE:
854 res = set_sampler_compare_mode(ctx, sampObj, param);
855 break;
856 case GL_TEXTURE_COMPARE_FUNC:
857 res = set_sampler_compare_func(ctx, sampObj, param);
858 break;
859 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
860 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
861 break;
862 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
863 res = set_sampler_cube_map_seamless(ctx, sampObj, param);
864 break;
865 case GL_TEXTURE_SRGB_DECODE_EXT:
866 res = set_sampler_srgb_decode(ctx, sampObj, param);
867 break;
868 case GL_TEXTURE_BORDER_COLOR:
869 /* fall-through */
870 default:
871 res = INVALID_PNAME;
872 }
873
874 switch (res) {
875 case GL_FALSE:
876 /* no change */
877 break;
878 case GL_TRUE:
879 /* state change - we do nothing special at this time */
880 break;
881 case INVALID_PNAME:
882 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
883 _mesa_enum_to_string(pname));
884 break;
885 case INVALID_PARAM:
886 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
887 param);
888 break;
889 case INVALID_VALUE:
890 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
891 param);
892 break;
893 default:
894 ;
895 }
896 }
897
898
899 void GLAPIENTRY
900 _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
901 {
902 struct gl_sampler_object *sampObj;
903 GLuint res;
904 GET_CURRENT_CONTEXT(ctx);
905
906 sampObj = sampler_parameter_error_check(ctx, sampler,
907 "glSamplerParameterf");
908 if (!sampObj)
909 return;
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 = sampler_parameter_error_check(ctx, sampler,
989 "glSamplerParameteriv");
990 if (!sampObj)
991 return;
992
993 switch (pname) {
994 case GL_TEXTURE_WRAP_S:
995 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
996 break;
997 case GL_TEXTURE_WRAP_T:
998 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
999 break;
1000 case GL_TEXTURE_WRAP_R:
1001 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1002 break;
1003 case GL_TEXTURE_MIN_FILTER:
1004 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1005 break;
1006 case GL_TEXTURE_MAG_FILTER:
1007 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1008 break;
1009 case GL_TEXTURE_MIN_LOD:
1010 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1011 break;
1012 case GL_TEXTURE_MAX_LOD:
1013 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1014 break;
1015 case GL_TEXTURE_LOD_BIAS:
1016 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1017 break;
1018 case GL_TEXTURE_COMPARE_MODE:
1019 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1020 break;
1021 case GL_TEXTURE_COMPARE_FUNC:
1022 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1023 break;
1024 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1025 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1026 break;
1027 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1028 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1029 break;
1030 case GL_TEXTURE_SRGB_DECODE_EXT:
1031 res = set_sampler_srgb_decode(ctx, sampObj, params[0]);
1032 break;
1033 case GL_TEXTURE_BORDER_COLOR:
1034 {
1035 GLfloat c[4];
1036 c[0] = INT_TO_FLOAT(params[0]);
1037 c[1] = INT_TO_FLOAT(params[1]);
1038 c[2] = INT_TO_FLOAT(params[2]);
1039 c[3] = INT_TO_FLOAT(params[3]);
1040 res = set_sampler_border_colorf(ctx, sampObj, c);
1041 }
1042 break;
1043 default:
1044 res = INVALID_PNAME;
1045 }
1046
1047 switch (res) {
1048 case GL_FALSE:
1049 /* no change */
1050 break;
1051 case GL_TRUE:
1052 /* state change - we do nothing special at this time */
1053 break;
1054 case INVALID_PNAME:
1055 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
1056 _mesa_enum_to_string(pname));
1057 break;
1058 case INVALID_PARAM:
1059 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
1060 params[0]);
1061 break;
1062 case INVALID_VALUE:
1063 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
1064 params[0]);
1065 break;
1066 default:
1067 ;
1068 }
1069 }
1070
1071 void GLAPIENTRY
1072 _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
1073 {
1074 struct gl_sampler_object *sampObj;
1075 GLuint res;
1076 GET_CURRENT_CONTEXT(ctx);
1077
1078 sampObj = sampler_parameter_error_check(ctx, sampler,
1079 "glSamplerParameterfv");
1080 if (!sampObj)
1081 return;
1082
1083 switch (pname) {
1084 case GL_TEXTURE_WRAP_S:
1085 res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
1086 break;
1087 case GL_TEXTURE_WRAP_T:
1088 res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
1089 break;
1090 case GL_TEXTURE_WRAP_R:
1091 res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
1092 break;
1093 case GL_TEXTURE_MIN_FILTER:
1094 res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
1095 break;
1096 case GL_TEXTURE_MAG_FILTER:
1097 res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
1098 break;
1099 case GL_TEXTURE_MIN_LOD:
1100 res = set_sampler_min_lod(ctx, sampObj, params[0]);
1101 break;
1102 case GL_TEXTURE_MAX_LOD:
1103 res = set_sampler_max_lod(ctx, sampObj, params[0]);
1104 break;
1105 case GL_TEXTURE_LOD_BIAS:
1106 res = set_sampler_lod_bias(ctx, sampObj, params[0]);
1107 break;
1108 case GL_TEXTURE_COMPARE_MODE:
1109 res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
1110 break;
1111 case GL_TEXTURE_COMPARE_FUNC:
1112 res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
1113 break;
1114 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1115 res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
1116 break;
1117 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1118 res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]);
1119 break;
1120 case GL_TEXTURE_SRGB_DECODE_EXT:
1121 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1122 break;
1123 case GL_TEXTURE_BORDER_COLOR:
1124 res = set_sampler_border_colorf(ctx, sampObj, params);
1125 break;
1126 default:
1127 res = INVALID_PNAME;
1128 }
1129
1130 switch (res) {
1131 case GL_FALSE:
1132 /* no change */
1133 break;
1134 case GL_TRUE:
1135 /* state change - we do nothing special at this time */
1136 break;
1137 case INVALID_PNAME:
1138 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
1139 _mesa_enum_to_string(pname));
1140 break;
1141 case INVALID_PARAM:
1142 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
1143 params[0]);
1144 break;
1145 case INVALID_VALUE:
1146 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
1147 params[0]);
1148 break;
1149 default:
1150 ;
1151 }
1152 }
1153
1154 void GLAPIENTRY
1155 _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
1156 {
1157 struct gl_sampler_object *sampObj;
1158 GLuint res;
1159 GET_CURRENT_CONTEXT(ctx);
1160
1161 sampObj = sampler_parameter_error_check(ctx, sampler,
1162 "glSamplerParameterIiv");
1163 if (!sampObj)
1164 return;
1165
1166 switch (pname) {
1167 case GL_TEXTURE_WRAP_S:
1168 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1169 break;
1170 case GL_TEXTURE_WRAP_T:
1171 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1172 break;
1173 case GL_TEXTURE_WRAP_R:
1174 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1175 break;
1176 case GL_TEXTURE_MIN_FILTER:
1177 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1178 break;
1179 case GL_TEXTURE_MAG_FILTER:
1180 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1181 break;
1182 case GL_TEXTURE_MIN_LOD:
1183 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1184 break;
1185 case GL_TEXTURE_MAX_LOD:
1186 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1187 break;
1188 case GL_TEXTURE_LOD_BIAS:
1189 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1190 break;
1191 case GL_TEXTURE_COMPARE_MODE:
1192 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1193 break;
1194 case GL_TEXTURE_COMPARE_FUNC:
1195 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1196 break;
1197 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1198 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1199 break;
1200 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1201 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1202 break;
1203 case GL_TEXTURE_SRGB_DECODE_EXT:
1204 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1205 break;
1206 case GL_TEXTURE_BORDER_COLOR:
1207 res = set_sampler_border_colori(ctx, sampObj, params);
1208 break;
1209 default:
1210 res = INVALID_PNAME;
1211 }
1212
1213 switch (res) {
1214 case GL_FALSE:
1215 /* no change */
1216 break;
1217 case GL_TRUE:
1218 /* state change - we do nothing special at this time */
1219 break;
1220 case INVALID_PNAME:
1221 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
1222 _mesa_enum_to_string(pname));
1223 break;
1224 case INVALID_PARAM:
1225 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
1226 params[0]);
1227 break;
1228 case INVALID_VALUE:
1229 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
1230 params[0]);
1231 break;
1232 default:
1233 ;
1234 }
1235 }
1236
1237
1238 void GLAPIENTRY
1239 _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
1240 {
1241 struct gl_sampler_object *sampObj;
1242 GLuint res;
1243 GET_CURRENT_CONTEXT(ctx);
1244
1245 sampObj = sampler_parameter_error_check(ctx, sampler,
1246 "glSamplerParameterIuiv");
1247 if (!sampObj)
1248 return;
1249
1250 switch (pname) {
1251 case GL_TEXTURE_WRAP_S:
1252 res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1253 break;
1254 case GL_TEXTURE_WRAP_T:
1255 res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1256 break;
1257 case GL_TEXTURE_WRAP_R:
1258 res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1259 break;
1260 case GL_TEXTURE_MIN_FILTER:
1261 res = set_sampler_min_filter(ctx, sampObj, params[0]);
1262 break;
1263 case GL_TEXTURE_MAG_FILTER:
1264 res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1265 break;
1266 case GL_TEXTURE_MIN_LOD:
1267 res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1268 break;
1269 case GL_TEXTURE_MAX_LOD:
1270 res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1271 break;
1272 case GL_TEXTURE_LOD_BIAS:
1273 res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1274 break;
1275 case GL_TEXTURE_COMPARE_MODE:
1276 res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1277 break;
1278 case GL_TEXTURE_COMPARE_FUNC:
1279 res = set_sampler_compare_func(ctx, sampObj, params[0]);
1280 break;
1281 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1282 res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1283 break;
1284 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1285 res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1286 break;
1287 case GL_TEXTURE_SRGB_DECODE_EXT:
1288 res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1289 break;
1290 case GL_TEXTURE_BORDER_COLOR:
1291 res = set_sampler_border_colorui(ctx, sampObj, params);
1292 break;
1293 default:
1294 res = INVALID_PNAME;
1295 }
1296
1297 switch (res) {
1298 case GL_FALSE:
1299 /* no change */
1300 break;
1301 case GL_TRUE:
1302 /* state change - we do nothing special at this time */
1303 break;
1304 case INVALID_PNAME:
1305 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
1306 _mesa_enum_to_string(pname));
1307 break;
1308 case INVALID_PARAM:
1309 _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
1310 params[0]);
1311 break;
1312 case INVALID_VALUE:
1313 _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
1314 params[0]);
1315 break;
1316 default:
1317 ;
1318 }
1319 }
1320
1321
1322 void GLAPIENTRY
1323 _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
1324 {
1325 struct gl_sampler_object *sampObj;
1326 GET_CURRENT_CONTEXT(ctx);
1327
1328 sampObj = sampler_parameter_error_check(ctx, sampler,
1329 "glGetSamplerParameteriv");
1330 if (!sampObj)
1331 return;
1332
1333 switch (pname) {
1334 case GL_TEXTURE_WRAP_S:
1335 *params = sampObj->WrapS;
1336 break;
1337 case GL_TEXTURE_WRAP_T:
1338 *params = sampObj->WrapT;
1339 break;
1340 case GL_TEXTURE_WRAP_R:
1341 *params = sampObj->WrapR;
1342 break;
1343 case GL_TEXTURE_MIN_FILTER:
1344 *params = sampObj->MinFilter;
1345 break;
1346 case GL_TEXTURE_MAG_FILTER:
1347 *params = sampObj->MagFilter;
1348 break;
1349 case GL_TEXTURE_MIN_LOD:
1350 /* GL spec 'Data Conversions' section specifies that floating-point
1351 * value in integer Get function is rounded to nearest integer
1352 */
1353 *params = IROUND(sampObj->MinLod);
1354 break;
1355 case GL_TEXTURE_MAX_LOD:
1356 /* GL spec 'Data Conversions' section specifies that floating-point
1357 * value in integer Get function is rounded to nearest integer
1358 */
1359 *params = IROUND(sampObj->MaxLod);
1360 break;
1361 case GL_TEXTURE_LOD_BIAS:
1362 /* GL spec 'Data Conversions' section specifies that floating-point
1363 * value in integer Get function is rounded to nearest integer
1364 */
1365 *params = IROUND(sampObj->LodBias);
1366 break;
1367 case GL_TEXTURE_COMPARE_MODE:
1368 *params = sampObj->CompareMode;
1369 break;
1370 case GL_TEXTURE_COMPARE_FUNC:
1371 *params = sampObj->CompareFunc;
1372 break;
1373 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1374 /* GL spec 'Data Conversions' section specifies that floating-point
1375 * value in integer Get function is rounded to nearest integer
1376 */
1377 *params = IROUND(sampObj->MaxAnisotropy);
1378 break;
1379 case GL_TEXTURE_BORDER_COLOR:
1380 params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
1381 params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
1382 params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
1383 params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
1384 break;
1385 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1386 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1387 goto invalid_pname;
1388 *params = sampObj->CubeMapSeamless;
1389 break;
1390 case GL_TEXTURE_SRGB_DECODE_EXT:
1391 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1392 goto invalid_pname;
1393 *params = (GLenum) sampObj->sRGBDecode;
1394 break;
1395 default:
1396 goto invalid_pname;
1397 }
1398 return;
1399
1400 invalid_pname:
1401 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
1402 _mesa_enum_to_string(pname));
1403 }
1404
1405
1406 void GLAPIENTRY
1407 _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
1408 {
1409 struct gl_sampler_object *sampObj;
1410 GET_CURRENT_CONTEXT(ctx);
1411
1412 sampObj = sampler_parameter_error_check(ctx, sampler,
1413 "glGetSamplerParameterfv");
1414 if (!sampObj)
1415 return;
1416
1417 switch (pname) {
1418 case GL_TEXTURE_WRAP_S:
1419 *params = (GLfloat) sampObj->WrapS;
1420 break;
1421 case GL_TEXTURE_WRAP_T:
1422 *params = (GLfloat) sampObj->WrapT;
1423 break;
1424 case GL_TEXTURE_WRAP_R:
1425 *params = (GLfloat) sampObj->WrapR;
1426 break;
1427 case GL_TEXTURE_MIN_FILTER:
1428 *params = (GLfloat) sampObj->MinFilter;
1429 break;
1430 case GL_TEXTURE_MAG_FILTER:
1431 *params = (GLfloat) sampObj->MagFilter;
1432 break;
1433 case GL_TEXTURE_MIN_LOD:
1434 *params = sampObj->MinLod;
1435 break;
1436 case GL_TEXTURE_MAX_LOD:
1437 *params = sampObj->MaxLod;
1438 break;
1439 case GL_TEXTURE_LOD_BIAS:
1440 *params = sampObj->LodBias;
1441 break;
1442 case GL_TEXTURE_COMPARE_MODE:
1443 *params = (GLfloat) sampObj->CompareMode;
1444 break;
1445 case GL_TEXTURE_COMPARE_FUNC:
1446 *params = (GLfloat) sampObj->CompareFunc;
1447 break;
1448 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1449 *params = sampObj->MaxAnisotropy;
1450 break;
1451 case GL_TEXTURE_BORDER_COLOR:
1452 params[0] = sampObj->BorderColor.f[0];
1453 params[1] = sampObj->BorderColor.f[1];
1454 params[2] = sampObj->BorderColor.f[2];
1455 params[3] = sampObj->BorderColor.f[3];
1456 break;
1457 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1458 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1459 goto invalid_pname;
1460 *params = (GLfloat) sampObj->CubeMapSeamless;
1461 break;
1462 case GL_TEXTURE_SRGB_DECODE_EXT:
1463 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1464 goto invalid_pname;
1465 *params = (GLfloat) sampObj->sRGBDecode;
1466 break;
1467 default:
1468 goto invalid_pname;
1469 }
1470 return;
1471
1472 invalid_pname:
1473 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
1474 _mesa_enum_to_string(pname));
1475 }
1476
1477
1478 void GLAPIENTRY
1479 _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
1480 {
1481 struct gl_sampler_object *sampObj;
1482 GET_CURRENT_CONTEXT(ctx);
1483
1484 sampObj = sampler_parameter_error_check(ctx, sampler,
1485 "glGetSamplerParameterIiv");
1486 if (!sampObj)
1487 return;
1488
1489 switch (pname) {
1490 case GL_TEXTURE_WRAP_S:
1491 *params = sampObj->WrapS;
1492 break;
1493 case GL_TEXTURE_WRAP_T:
1494 *params = sampObj->WrapT;
1495 break;
1496 case GL_TEXTURE_WRAP_R:
1497 *params = sampObj->WrapR;
1498 break;
1499 case GL_TEXTURE_MIN_FILTER:
1500 *params = sampObj->MinFilter;
1501 break;
1502 case GL_TEXTURE_MAG_FILTER:
1503 *params = sampObj->MagFilter;
1504 break;
1505 case GL_TEXTURE_MIN_LOD:
1506 *params = (GLint) sampObj->MinLod;
1507 break;
1508 case GL_TEXTURE_MAX_LOD:
1509 *params = (GLint) sampObj->MaxLod;
1510 break;
1511 case GL_TEXTURE_LOD_BIAS:
1512 *params = (GLint) sampObj->LodBias;
1513 break;
1514 case GL_TEXTURE_COMPARE_MODE:
1515 *params = sampObj->CompareMode;
1516 break;
1517 case GL_TEXTURE_COMPARE_FUNC:
1518 *params = sampObj->CompareFunc;
1519 break;
1520 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1521 *params = (GLint) sampObj->MaxAnisotropy;
1522 break;
1523 case GL_TEXTURE_BORDER_COLOR:
1524 params[0] = sampObj->BorderColor.i[0];
1525 params[1] = sampObj->BorderColor.i[1];
1526 params[2] = sampObj->BorderColor.i[2];
1527 params[3] = sampObj->BorderColor.i[3];
1528 break;
1529 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1530 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1531 goto invalid_pname;
1532 *params = sampObj->CubeMapSeamless;
1533 break;
1534 case GL_TEXTURE_SRGB_DECODE_EXT:
1535 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1536 goto invalid_pname;
1537 *params = (GLenum) sampObj->sRGBDecode;
1538 break;
1539 default:
1540 goto invalid_pname;
1541 }
1542 return;
1543
1544 invalid_pname:
1545 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
1546 _mesa_enum_to_string(pname));
1547 }
1548
1549
1550 void GLAPIENTRY
1551 _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
1552 {
1553 struct gl_sampler_object *sampObj;
1554 GET_CURRENT_CONTEXT(ctx);
1555
1556 sampObj = sampler_parameter_error_check(ctx, sampler,
1557 "glGetSamplerParameterIuiv");
1558 if (!sampObj)
1559 return;
1560
1561 switch (pname) {
1562 case GL_TEXTURE_WRAP_S:
1563 *params = sampObj->WrapS;
1564 break;
1565 case GL_TEXTURE_WRAP_T:
1566 *params = sampObj->WrapT;
1567 break;
1568 case GL_TEXTURE_WRAP_R:
1569 *params = sampObj->WrapR;
1570 break;
1571 case GL_TEXTURE_MIN_FILTER:
1572 *params = sampObj->MinFilter;
1573 break;
1574 case GL_TEXTURE_MAG_FILTER:
1575 *params = sampObj->MagFilter;
1576 break;
1577 case GL_TEXTURE_MIN_LOD:
1578 *params = (GLuint) sampObj->MinLod;
1579 break;
1580 case GL_TEXTURE_MAX_LOD:
1581 *params = (GLuint) sampObj->MaxLod;
1582 break;
1583 case GL_TEXTURE_LOD_BIAS:
1584 *params = (GLuint) sampObj->LodBias;
1585 break;
1586 case GL_TEXTURE_COMPARE_MODE:
1587 *params = sampObj->CompareMode;
1588 break;
1589 case GL_TEXTURE_COMPARE_FUNC:
1590 *params = sampObj->CompareFunc;
1591 break;
1592 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1593 *params = (GLuint) sampObj->MaxAnisotropy;
1594 break;
1595 case GL_TEXTURE_BORDER_COLOR:
1596 params[0] = sampObj->BorderColor.ui[0];
1597 params[1] = sampObj->BorderColor.ui[1];
1598 params[2] = sampObj->BorderColor.ui[2];
1599 params[3] = sampObj->BorderColor.ui[3];
1600 break;
1601 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1602 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1603 goto invalid_pname;
1604 *params = sampObj->CubeMapSeamless;
1605 break;
1606 case GL_TEXTURE_SRGB_DECODE_EXT:
1607 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1608 goto invalid_pname;
1609 *params = (GLenum) sampObj->sRGBDecode;
1610 break;
1611 default:
1612 goto invalid_pname;
1613 }
1614 return;
1615
1616 invalid_pname:
1617 _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
1618 _mesa_enum_to_string(pname));
1619 }
1620
1621
1622 void
1623 _mesa_init_sampler_object_functions(struct dd_function_table *driver)
1624 {
1625 driver->NewSamplerObject = _mesa_new_sampler_object;
1626 }