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