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