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