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