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