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