samplerobj.c revision 848b8605
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
75
76/**
77 * Handle reference counting.
78 */
79void
80_mesa_reference_sampler_object_(struct gl_context *ctx,
81                                struct gl_sampler_object **ptr,
82                                struct gl_sampler_object *samp)
83{
84   assert(*ptr != samp); /* The inline wrapper should prevent no-op calls */
85
86   if (*ptr) {
87      /* Unreference the old sampler */
88      GLboolean deleteFlag = GL_FALSE;
89      struct gl_sampler_object *oldSamp = *ptr;
90
91      /*mtx_lock(&oldSamp->Mutex);*/
92      ASSERT(oldSamp->RefCount > 0);
93      oldSamp->RefCount--;
94#if 0
95      printf("SamplerObj %p %d DECR to %d\n",
96             (void *) oldSamp, oldSamp->Name, oldSamp->RefCount);
97#endif
98      deleteFlag = (oldSamp->RefCount == 0);
99      /*mtx_unlock(&oldSamp->Mutex);*/
100
101      if (deleteFlag) {
102	 ASSERT(ctx->Driver.DeleteSamplerObject);
103         ctx->Driver.DeleteSamplerObject(ctx, oldSamp);
104      }
105
106      *ptr = NULL;
107   }
108   ASSERT(!*ptr);
109
110   if (samp) {
111      /* reference new sampler */
112      /*mtx_lock(&samp->Mutex);*/
113      if (samp->RefCount == 0) {
114         /* this sampler's being deleted (look just above) */
115         /* Not sure this can every really happen.  Warn if it does. */
116         _mesa_problem(NULL, "referencing deleted sampler object");
117         *ptr = NULL;
118      }
119      else {
120         samp->RefCount++;
121#if 0
122         printf("SamplerObj %p %d INCR to %d\n",
123                (void *) samp, samp->Name, samp->RefCount);
124#endif
125         *ptr = samp;
126      }
127      /*mtx_unlock(&samp->Mutex);*/
128   }
129}
130
131
132/**
133 * Initialize the fields of the given sampler object.
134 */
135static void
136_mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
137{
138   sampObj->Name = name;
139   sampObj->RefCount = 1;
140   sampObj->WrapS = GL_REPEAT;
141   sampObj->WrapT = GL_REPEAT;
142   sampObj->WrapR = GL_REPEAT;
143   sampObj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
144   sampObj->MagFilter = GL_LINEAR;
145   sampObj->BorderColor.f[0] = 0.0;
146   sampObj->BorderColor.f[1] = 0.0;
147   sampObj->BorderColor.f[2] = 0.0;
148   sampObj->BorderColor.f[3] = 0.0;
149   sampObj->MinLod = -1000.0F;
150   sampObj->MaxLod = 1000.0F;
151   sampObj->LodBias = 0.0F;
152   sampObj->MaxAnisotropy = 1.0F;
153   sampObj->CompareMode = GL_NONE;
154   sampObj->CompareFunc = GL_LEQUAL;
155   sampObj->sRGBDecode = GL_DECODE_EXT;
156   sampObj->CubeMapSeamless = GL_FALSE;
157}
158
159/**
160 * Fallback for ctx->Driver.NewSamplerObject();
161 */
162struct gl_sampler_object *
163_mesa_new_sampler_object(struct gl_context *ctx, GLuint name)
164{
165   struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object);
166   if (sampObj) {
167      _mesa_init_sampler_object(sampObj, name);
168   }
169   return sampObj;
170}
171
172
173/**
174 * Fallback for ctx->Driver.DeleteSamplerObject();
175 */
176static void
177_mesa_delete_sampler_object(struct gl_context *ctx,
178                            struct gl_sampler_object *sampObj)
179{
180   free(sampObj->Label);
181   free(sampObj);
182}
183
184
185void GLAPIENTRY
186_mesa_GenSamplers(GLsizei count, GLuint *samplers)
187{
188   GET_CURRENT_CONTEXT(ctx);
189   GLuint first;
190   GLint i;
191
192   if (MESA_VERBOSE & VERBOSE_API)
193      _mesa_debug(ctx, "glGenSamplers(%d)\n", count);
194
195   if (count < 0) {
196      _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers");
197      return;
198   }
199
200   if (!samplers)
201      return;
202
203   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count);
204
205   /* Insert the ID and pointer to new sampler object into hash table */
206   for (i = 0; i < count; i++) {
207      struct gl_sampler_object *sampObj =
208         ctx->Driver.NewSamplerObject(ctx, first + i);
209      _mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj);
210      samplers[i] = first + i;
211   }
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
447
448#define INVALID_PARAM 0x100
449#define INVALID_PNAME 0x101
450#define INVALID_VALUE 0x102
451
452static GLuint
453set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
454                   GLint param)
455{
456   if (samp->WrapS == param)
457      return GL_FALSE;
458   if (validate_texture_wrap_mode(ctx, param)) {
459      flush(ctx);
460      samp->WrapS = param;
461      return GL_TRUE;
462   }
463   return INVALID_PARAM;
464}
465
466
467static GLuint
468set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
469                   GLint param)
470{
471   if (samp->WrapT == param)
472      return GL_FALSE;
473   if (validate_texture_wrap_mode(ctx, param)) {
474      flush(ctx);
475      samp->WrapT = param;
476      return GL_TRUE;
477   }
478   return INVALID_PARAM;
479}
480
481
482static GLuint
483set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
484                   GLint param)
485{
486   if (samp->WrapR == param)
487      return GL_FALSE;
488   if (validate_texture_wrap_mode(ctx, param)) {
489      flush(ctx);
490      samp->WrapR = param;
491      return GL_TRUE;
492   }
493   return INVALID_PARAM;
494}
495
496
497static GLuint
498set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
499                       GLint param)
500{
501   if (samp->MinFilter == param)
502      return GL_FALSE;
503
504   switch (param) {
505   case GL_NEAREST:
506   case GL_LINEAR:
507   case GL_NEAREST_MIPMAP_NEAREST:
508   case GL_LINEAR_MIPMAP_NEAREST:
509   case GL_NEAREST_MIPMAP_LINEAR:
510   case GL_LINEAR_MIPMAP_LINEAR:
511      flush(ctx);
512      samp->MinFilter = param;
513      return GL_TRUE;
514   default:
515      return INVALID_PARAM;
516   }
517}
518
519
520static GLuint
521set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
522                       GLint param)
523{
524   if (samp->MagFilter == param)
525      return GL_FALSE;
526
527   switch (param) {
528   case GL_NEAREST:
529   case GL_LINEAR:
530      flush(ctx);
531      samp->MagFilter = param;
532      return GL_TRUE;
533   default:
534      return INVALID_PARAM;
535   }
536}
537
538
539static GLuint
540set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
541                     GLfloat param)
542{
543   if (samp->LodBias == param)
544      return GL_FALSE;
545
546   flush(ctx);
547   samp->LodBias = param;
548   return GL_TRUE;
549}
550
551
552static GLuint
553set_sampler_border_colorf(struct gl_context *ctx,
554                          struct gl_sampler_object *samp,
555                          const GLfloat params[4])
556{
557   flush(ctx);
558   samp->BorderColor.f[RCOMP] = params[0];
559   samp->BorderColor.f[GCOMP] = params[1];
560   samp->BorderColor.f[BCOMP] = params[2];
561   samp->BorderColor.f[ACOMP] = params[3];
562   return GL_TRUE;
563}
564
565
566static GLuint
567set_sampler_border_colori(struct gl_context *ctx,
568                          struct gl_sampler_object *samp,
569                          const GLint params[4])
570{
571   flush(ctx);
572   samp->BorderColor.i[RCOMP] = params[0];
573   samp->BorderColor.i[GCOMP] = params[1];
574   samp->BorderColor.i[BCOMP] = params[2];
575   samp->BorderColor.i[ACOMP] = params[3];
576   return GL_TRUE;
577}
578
579
580static GLuint
581set_sampler_border_colorui(struct gl_context *ctx,
582                           struct gl_sampler_object *samp,
583                           const GLuint params[4])
584{
585   flush(ctx);
586   samp->BorderColor.ui[RCOMP] = params[0];
587   samp->BorderColor.ui[GCOMP] = params[1];
588   samp->BorderColor.ui[BCOMP] = params[2];
589   samp->BorderColor.ui[ACOMP] = params[3];
590   return GL_TRUE;
591}
592
593
594static GLuint
595set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
596                    GLfloat param)
597{
598   if (samp->MinLod == param)
599      return GL_FALSE;
600
601   flush(ctx);
602   samp->MinLod = param;
603   return GL_TRUE;
604}
605
606
607static GLuint
608set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
609                    GLfloat param)
610{
611   if (samp->MaxLod == param)
612      return GL_FALSE;
613
614   flush(ctx);
615   samp->MaxLod = param;
616   return GL_TRUE;
617}
618
619
620static GLuint
621set_sampler_compare_mode(struct gl_context *ctx,
622                         struct gl_sampler_object *samp, GLint param)
623{
624   if (!ctx->Extensions.ARB_shadow)
625      return INVALID_PNAME;
626
627   if (samp->CompareMode == param)
628      return GL_FALSE;
629
630   if (param == GL_NONE ||
631       param == GL_COMPARE_R_TO_TEXTURE_ARB) {
632      flush(ctx);
633      samp->CompareMode = param;
634      return GL_TRUE;
635   }
636
637   return INVALID_PARAM;
638}
639
640
641static GLuint
642set_sampler_compare_func(struct gl_context *ctx,
643                         struct gl_sampler_object *samp, GLint param)
644{
645   if (!ctx->Extensions.ARB_shadow)
646      return INVALID_PNAME;
647
648   if (samp->CompareFunc == param)
649      return GL_FALSE;
650
651   switch (param) {
652   case GL_LEQUAL:
653   case GL_GEQUAL:
654   case GL_EQUAL:
655   case GL_NOTEQUAL:
656   case GL_LESS:
657   case GL_GREATER:
658   case GL_ALWAYS:
659   case GL_NEVER:
660      flush(ctx);
661      samp->CompareFunc = param;
662      return GL_TRUE;
663   default:
664      return INVALID_PARAM;
665   }
666}
667
668
669static GLuint
670set_sampler_max_anisotropy(struct gl_context *ctx,
671                           struct gl_sampler_object *samp, GLfloat param)
672{
673   if (!ctx->Extensions.EXT_texture_filter_anisotropic)
674      return INVALID_PNAME;
675
676   if (samp->MaxAnisotropy == param)
677      return GL_FALSE;
678
679   if (param < 1.0)
680      return INVALID_VALUE;
681
682   flush(ctx);
683   /* clamp to max, that's what NVIDIA does */
684   samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
685   return GL_TRUE;
686}
687
688
689static GLuint
690set_sampler_cube_map_seamless(struct gl_context *ctx,
691                              struct gl_sampler_object *samp, GLboolean param)
692{
693   if (!_mesa_is_desktop_gl(ctx)
694       || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
695      return INVALID_PNAME;
696
697   if (samp->CubeMapSeamless == param)
698      return GL_FALSE;
699
700   if (param != GL_TRUE && param != GL_FALSE)
701      return INVALID_VALUE;
702
703   flush(ctx);
704   samp->CubeMapSeamless = param;
705   return GL_TRUE;
706}
707
708static GLuint
709set_sampler_srgb_decode(struct gl_context *ctx,
710                              struct gl_sampler_object *samp, GLenum param)
711{
712   if (!ctx->Extensions.EXT_texture_sRGB_decode)
713      return INVALID_PNAME;
714
715   if (samp->sRGBDecode == param)
716      return GL_FALSE;
717
718   if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
719      return INVALID_VALUE;
720
721   flush(ctx);
722   samp->sRGBDecode = param;
723   return GL_TRUE;
724}
725
726void GLAPIENTRY
727_mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
728{
729   struct gl_sampler_object *sampObj;
730   GLuint res;
731   GET_CURRENT_CONTEXT(ctx);
732
733   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
734   if (!sampObj) {
735      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)",
736                  sampler);
737      return;
738   }
739
740   switch (pname) {
741   case GL_TEXTURE_WRAP_S:
742      res = set_sampler_wrap_s(ctx, sampObj, param);
743      break;
744   case GL_TEXTURE_WRAP_T:
745      res = set_sampler_wrap_t(ctx, sampObj, param);
746      break;
747   case GL_TEXTURE_WRAP_R:
748      res = set_sampler_wrap_r(ctx, sampObj, param);
749      break;
750   case GL_TEXTURE_MIN_FILTER:
751      res = set_sampler_min_filter(ctx, sampObj, param);
752      break;
753   case GL_TEXTURE_MAG_FILTER:
754      res = set_sampler_mag_filter(ctx, sampObj, param);
755      break;
756   case GL_TEXTURE_MIN_LOD:
757      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
758      break;
759   case GL_TEXTURE_MAX_LOD:
760      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
761      break;
762   case GL_TEXTURE_LOD_BIAS:
763      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
764      break;
765   case GL_TEXTURE_COMPARE_MODE:
766      res = set_sampler_compare_mode(ctx, sampObj, param);
767      break;
768   case GL_TEXTURE_COMPARE_FUNC:
769      res = set_sampler_compare_func(ctx, sampObj, param);
770      break;
771   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
772      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
773      break;
774   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
775      res = set_sampler_cube_map_seamless(ctx, sampObj, param);
776      break;
777   case GL_TEXTURE_SRGB_DECODE_EXT:
778      res = set_sampler_srgb_decode(ctx, sampObj, param);
779      break;
780   case GL_TEXTURE_BORDER_COLOR:
781      /* fall-through */
782   default:
783      res = INVALID_PNAME;
784   }
785
786   switch (res) {
787   case GL_FALSE:
788      /* no change */
789      break;
790   case GL_TRUE:
791      /* state change - we do nothing special at this time */
792      break;
793   case INVALID_PNAME:
794      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
795                  _mesa_lookup_enum_by_nr(pname));
796      break;
797   case INVALID_PARAM:
798      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
799                  param);
800      break;
801   case INVALID_VALUE:
802      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
803                  param);
804      break;
805   default:
806      ;
807   }
808}
809
810
811void GLAPIENTRY
812_mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
813{
814   struct gl_sampler_object *sampObj;
815   GLuint res;
816   GET_CURRENT_CONTEXT(ctx);
817
818   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
819   if (!sampObj) {
820      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(sampler %u)",
821                  sampler);
822      return;
823   }
824
825   switch (pname) {
826   case GL_TEXTURE_WRAP_S:
827      res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
828      break;
829   case GL_TEXTURE_WRAP_T:
830      res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
831      break;
832   case GL_TEXTURE_WRAP_R:
833      res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
834      break;
835   case GL_TEXTURE_MIN_FILTER:
836      res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
837      break;
838   case GL_TEXTURE_MAG_FILTER:
839      res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
840      break;
841   case GL_TEXTURE_MIN_LOD:
842      res = set_sampler_min_lod(ctx, sampObj, param);
843      break;
844   case GL_TEXTURE_MAX_LOD:
845      res = set_sampler_max_lod(ctx, sampObj, param);
846      break;
847   case GL_TEXTURE_LOD_BIAS:
848      res = set_sampler_lod_bias(ctx, sampObj, param);
849      break;
850   case GL_TEXTURE_COMPARE_MODE:
851      res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
852      break;
853   case GL_TEXTURE_COMPARE_FUNC:
854      res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
855      break;
856   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
857      res = set_sampler_max_anisotropy(ctx, sampObj, param);
858      break;
859   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
860      res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) param);
861      break;
862   case GL_TEXTURE_SRGB_DECODE_EXT:
863      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) param);
864      break;
865   case GL_TEXTURE_BORDER_COLOR:
866      /* fall-through */
867   default:
868      res = INVALID_PNAME;
869   }
870
871   switch (res) {
872   case GL_FALSE:
873      /* no change */
874      break;
875   case GL_TRUE:
876      /* state change - we do nothing special at this time */
877      break;
878   case INVALID_PNAME:
879      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
880                  _mesa_lookup_enum_by_nr(pname));
881      break;
882   case INVALID_PARAM:
883      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
884                  param);
885      break;
886   case INVALID_VALUE:
887      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
888                  param);
889      break;
890   default:
891      ;
892   }
893}
894
895void GLAPIENTRY
896_mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
897{
898   struct gl_sampler_object *sampObj;
899   GLuint res;
900   GET_CURRENT_CONTEXT(ctx);
901
902   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
903   if (!sampObj) {
904      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(sampler %u)",
905                  sampler);
906      return;
907   }
908
909   switch (pname) {
910   case GL_TEXTURE_WRAP_S:
911      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
912      break;
913   case GL_TEXTURE_WRAP_T:
914      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
915      break;
916   case GL_TEXTURE_WRAP_R:
917      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
918      break;
919   case GL_TEXTURE_MIN_FILTER:
920      res = set_sampler_min_filter(ctx, sampObj, params[0]);
921      break;
922   case GL_TEXTURE_MAG_FILTER:
923      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
924      break;
925   case GL_TEXTURE_MIN_LOD:
926      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
927      break;
928   case GL_TEXTURE_MAX_LOD:
929      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
930      break;
931   case GL_TEXTURE_LOD_BIAS:
932      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
933      break;
934   case GL_TEXTURE_COMPARE_MODE:
935      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
936      break;
937   case GL_TEXTURE_COMPARE_FUNC:
938      res = set_sampler_compare_func(ctx, sampObj, params[0]);
939      break;
940   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
941      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
942      break;
943   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
944      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
945      break;
946   case GL_TEXTURE_SRGB_DECODE_EXT:
947      res = set_sampler_srgb_decode(ctx, sampObj, params[0]);
948      break;
949   case GL_TEXTURE_BORDER_COLOR:
950      {
951         GLfloat c[4];
952         c[0] = INT_TO_FLOAT(params[0]);
953         c[1] = INT_TO_FLOAT(params[1]);
954         c[2] = INT_TO_FLOAT(params[2]);
955         c[3] = INT_TO_FLOAT(params[3]);
956         res = set_sampler_border_colorf(ctx, sampObj, c);
957      }
958      break;
959   default:
960      res = INVALID_PNAME;
961   }
962
963   switch (res) {
964   case GL_FALSE:
965      /* no change */
966      break;
967   case GL_TRUE:
968      /* state change - we do nothing special at this time */
969      break;
970   case INVALID_PNAME:
971      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
972                  _mesa_lookup_enum_by_nr(pname));
973      break;
974   case INVALID_PARAM:
975      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
976                  params[0]);
977      break;
978   case INVALID_VALUE:
979      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
980                  params[0]);
981      break;
982   default:
983      ;
984   }
985}
986
987void GLAPIENTRY
988_mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
989{
990   struct gl_sampler_object *sampObj;
991   GLuint res;
992   GET_CURRENT_CONTEXT(ctx);
993
994   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
995   if (!sampObj) {
996      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(sampler %u)",
997                  sampler);
998      return;
999   }
1000
1001   switch (pname) {
1002   case GL_TEXTURE_WRAP_S:
1003      res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
1004      break;
1005   case GL_TEXTURE_WRAP_T:
1006      res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
1007      break;
1008   case GL_TEXTURE_WRAP_R:
1009      res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
1010      break;
1011   case GL_TEXTURE_MIN_FILTER:
1012      res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
1013      break;
1014   case GL_TEXTURE_MAG_FILTER:
1015      res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
1016      break;
1017   case GL_TEXTURE_MIN_LOD:
1018      res = set_sampler_min_lod(ctx, sampObj, params[0]);
1019      break;
1020   case GL_TEXTURE_MAX_LOD:
1021      res = set_sampler_max_lod(ctx, sampObj, params[0]);
1022      break;
1023   case GL_TEXTURE_LOD_BIAS:
1024      res = set_sampler_lod_bias(ctx, sampObj, params[0]);
1025      break;
1026   case GL_TEXTURE_COMPARE_MODE:
1027      res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
1028      break;
1029   case GL_TEXTURE_COMPARE_FUNC:
1030      res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
1031      break;
1032   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1033      res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
1034      break;
1035   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1036      res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]);
1037      break;
1038   case GL_TEXTURE_SRGB_DECODE_EXT:
1039      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1040      break;
1041   case GL_TEXTURE_BORDER_COLOR:
1042      res = set_sampler_border_colorf(ctx, sampObj, params);
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, "glSamplerParameterfv(pname=%s)\n",
1057                  _mesa_lookup_enum_by_nr(pname));
1058      break;
1059   case INVALID_PARAM:
1060      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
1061                  params[0]);
1062      break;
1063   case INVALID_VALUE:
1064      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
1065                  params[0]);
1066      break;
1067   default:
1068      ;
1069   }
1070}
1071
1072void GLAPIENTRY
1073_mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *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      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(sampler %u)",
1082                  sampler);
1083      return;
1084   }
1085
1086   switch (pname) {
1087   case GL_TEXTURE_WRAP_S:
1088      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1089      break;
1090   case GL_TEXTURE_WRAP_T:
1091      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1092      break;
1093   case GL_TEXTURE_WRAP_R:
1094      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1095      break;
1096   case GL_TEXTURE_MIN_FILTER:
1097      res = set_sampler_min_filter(ctx, sampObj, params[0]);
1098      break;
1099   case GL_TEXTURE_MAG_FILTER:
1100      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1101      break;
1102   case GL_TEXTURE_MIN_LOD:
1103      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1104      break;
1105   case GL_TEXTURE_MAX_LOD:
1106      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1107      break;
1108   case GL_TEXTURE_LOD_BIAS:
1109      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1110      break;
1111   case GL_TEXTURE_COMPARE_MODE:
1112      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1113      break;
1114   case GL_TEXTURE_COMPARE_FUNC:
1115      res = set_sampler_compare_func(ctx, sampObj, params[0]);
1116      break;
1117   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1118      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1119      break;
1120   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1121      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1122      break;
1123   case GL_TEXTURE_SRGB_DECODE_EXT:
1124      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1125      break;
1126   case GL_TEXTURE_BORDER_COLOR:
1127      res = set_sampler_border_colori(ctx, sampObj, params);
1128      break;
1129   default:
1130      res = INVALID_PNAME;
1131   }
1132
1133   switch (res) {
1134   case GL_FALSE:
1135      /* no change */
1136      break;
1137   case GL_TRUE:
1138      /* state change - we do nothing special at this time */
1139      break;
1140   case INVALID_PNAME:
1141      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
1142                  _mesa_lookup_enum_by_nr(pname));
1143      break;
1144   case INVALID_PARAM:
1145      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
1146                  params[0]);
1147      break;
1148   case INVALID_VALUE:
1149      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
1150                  params[0]);
1151      break;
1152   default:
1153      ;
1154   }
1155}
1156
1157
1158void GLAPIENTRY
1159_mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
1160{
1161   struct gl_sampler_object *sampObj;
1162   GLuint res;
1163   GET_CURRENT_CONTEXT(ctx);
1164
1165   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1166   if (!sampObj) {
1167      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(sampler %u)",
1168                  sampler);
1169      return;
1170   }
1171
1172   switch (pname) {
1173   case GL_TEXTURE_WRAP_S:
1174      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1175      break;
1176   case GL_TEXTURE_WRAP_T:
1177      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1178      break;
1179   case GL_TEXTURE_WRAP_R:
1180      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1181      break;
1182   case GL_TEXTURE_MIN_FILTER:
1183      res = set_sampler_min_filter(ctx, sampObj, params[0]);
1184      break;
1185   case GL_TEXTURE_MAG_FILTER:
1186      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1187      break;
1188   case GL_TEXTURE_MIN_LOD:
1189      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1190      break;
1191   case GL_TEXTURE_MAX_LOD:
1192      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1193      break;
1194   case GL_TEXTURE_LOD_BIAS:
1195      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1196      break;
1197   case GL_TEXTURE_COMPARE_MODE:
1198      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1199      break;
1200   case GL_TEXTURE_COMPARE_FUNC:
1201      res = set_sampler_compare_func(ctx, sampObj, params[0]);
1202      break;
1203   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1204      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1205      break;
1206   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1207      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1208      break;
1209   case GL_TEXTURE_SRGB_DECODE_EXT:
1210      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1211      break;
1212   case GL_TEXTURE_BORDER_COLOR:
1213      res = set_sampler_border_colorui(ctx, sampObj, params);
1214      break;
1215   default:
1216      res = INVALID_PNAME;
1217   }
1218
1219   switch (res) {
1220   case GL_FALSE:
1221      /* no change */
1222      break;
1223   case GL_TRUE:
1224      /* state change - we do nothing special at this time */
1225      break;
1226   case INVALID_PNAME:
1227      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
1228                  _mesa_lookup_enum_by_nr(pname));
1229      break;
1230   case INVALID_PARAM:
1231      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
1232                  params[0]);
1233      break;
1234   case INVALID_VALUE:
1235      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
1236                  params[0]);
1237      break;
1238   default:
1239      ;
1240   }
1241}
1242
1243
1244void GLAPIENTRY
1245_mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
1246{
1247   struct gl_sampler_object *sampObj;
1248   GET_CURRENT_CONTEXT(ctx);
1249
1250   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1251   if (!sampObj) {
1252      _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameteriv(sampler %u)",
1253                  sampler);
1254      return;
1255   }
1256
1257   switch (pname) {
1258   case GL_TEXTURE_WRAP_S:
1259      *params = sampObj->WrapS;
1260      break;
1261   case GL_TEXTURE_WRAP_T:
1262      *params = sampObj->WrapT;
1263      break;
1264   case GL_TEXTURE_WRAP_R:
1265      *params = sampObj->WrapR;
1266      break;
1267   case GL_TEXTURE_MIN_FILTER:
1268      *params = sampObj->MinFilter;
1269      break;
1270   case GL_TEXTURE_MAG_FILTER:
1271      *params = sampObj->MagFilter;
1272      break;
1273   case GL_TEXTURE_MIN_LOD:
1274      *params = (GLint) sampObj->MinLod;
1275      break;
1276   case GL_TEXTURE_MAX_LOD:
1277      *params = (GLint) sampObj->MaxLod;
1278      break;
1279   case GL_TEXTURE_LOD_BIAS:
1280      *params = (GLint) sampObj->LodBias;
1281      break;
1282   case GL_TEXTURE_COMPARE_MODE:
1283      if (!ctx->Extensions.ARB_shadow)
1284         goto invalid_pname;
1285      *params = sampObj->CompareMode;
1286      break;
1287   case GL_TEXTURE_COMPARE_FUNC:
1288      if (!ctx->Extensions.ARB_shadow)
1289         goto invalid_pname;
1290      *params = sampObj->CompareFunc;
1291      break;
1292   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1293      *params = (GLint) sampObj->MaxAnisotropy;
1294      break;
1295   case GL_TEXTURE_BORDER_COLOR:
1296      params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
1297      params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
1298      params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
1299      params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
1300      break;
1301   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1302      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1303         goto invalid_pname;
1304      *params = sampObj->CubeMapSeamless;
1305      break;
1306   case GL_TEXTURE_SRGB_DECODE_EXT:
1307      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1308         goto invalid_pname;
1309      *params = (GLenum) sampObj->sRGBDecode;
1310      break;
1311   default:
1312      goto invalid_pname;
1313   }
1314   return;
1315
1316invalid_pname:
1317   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
1318               _mesa_lookup_enum_by_nr(pname));
1319}
1320
1321
1322void GLAPIENTRY
1323_mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
1324{
1325   struct gl_sampler_object *sampObj;
1326   GET_CURRENT_CONTEXT(ctx);
1327
1328   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1329   if (!sampObj) {
1330      _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameterfv(sampler %u)",
1331                  sampler);
1332      return;
1333   }
1334
1335   switch (pname) {
1336   case GL_TEXTURE_WRAP_S:
1337      *params = (GLfloat) sampObj->WrapS;
1338      break;
1339   case GL_TEXTURE_WRAP_T:
1340      *params = (GLfloat) sampObj->WrapT;
1341      break;
1342   case GL_TEXTURE_WRAP_R:
1343      *params = (GLfloat) sampObj->WrapR;
1344      break;
1345   case GL_TEXTURE_MIN_FILTER:
1346      *params = (GLfloat) sampObj->MinFilter;
1347      break;
1348   case GL_TEXTURE_MAG_FILTER:
1349      *params = (GLfloat) sampObj->MagFilter;
1350      break;
1351   case GL_TEXTURE_MIN_LOD:
1352      *params = sampObj->MinLod;
1353      break;
1354   case GL_TEXTURE_MAX_LOD:
1355      *params = sampObj->MaxLod;
1356      break;
1357   case GL_TEXTURE_LOD_BIAS:
1358      *params = sampObj->LodBias;
1359      break;
1360   case GL_TEXTURE_COMPARE_MODE:
1361      if (!ctx->Extensions.ARB_shadow)
1362         goto invalid_pname;
1363      *params = (GLfloat) sampObj->CompareMode;
1364      break;
1365   case GL_TEXTURE_COMPARE_FUNC:
1366      if (!ctx->Extensions.ARB_shadow)
1367         goto invalid_pname;
1368      *params = (GLfloat) sampObj->CompareFunc;
1369      break;
1370   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1371      *params = sampObj->MaxAnisotropy;
1372      break;
1373   case GL_TEXTURE_BORDER_COLOR:
1374      params[0] = sampObj->BorderColor.f[0];
1375      params[1] = sampObj->BorderColor.f[1];
1376      params[2] = sampObj->BorderColor.f[2];
1377      params[3] = sampObj->BorderColor.f[3];
1378      break;
1379   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1380      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1381         goto invalid_pname;
1382      *params = (GLfloat) sampObj->CubeMapSeamless;
1383      break;
1384   case GL_TEXTURE_SRGB_DECODE_EXT:
1385      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1386         goto invalid_pname;
1387      *params = (GLfloat) sampObj->sRGBDecode;
1388      break;
1389   default:
1390      goto invalid_pname;
1391   }
1392   return;
1393
1394invalid_pname:
1395   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
1396               _mesa_lookup_enum_by_nr(pname));
1397}
1398
1399
1400void GLAPIENTRY
1401_mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
1402{
1403   struct gl_sampler_object *sampObj;
1404   GET_CURRENT_CONTEXT(ctx);
1405
1406   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1407   if (!sampObj) {
1408      _mesa_error(ctx, GL_INVALID_VALUE,
1409                  "glGetSamplerParameterIiv(sampler %u)",
1410                  sampler);
1411      return;
1412   }
1413
1414   switch (pname) {
1415   case GL_TEXTURE_WRAP_S:
1416      *params = sampObj->WrapS;
1417      break;
1418   case GL_TEXTURE_WRAP_T:
1419      *params = sampObj->WrapT;
1420      break;
1421   case GL_TEXTURE_WRAP_R:
1422      *params = sampObj->WrapR;
1423      break;
1424   case GL_TEXTURE_MIN_FILTER:
1425      *params = sampObj->MinFilter;
1426      break;
1427   case GL_TEXTURE_MAG_FILTER:
1428      *params = sampObj->MagFilter;
1429      break;
1430   case GL_TEXTURE_MIN_LOD:
1431      *params = (GLint) sampObj->MinLod;
1432      break;
1433   case GL_TEXTURE_MAX_LOD:
1434      *params = (GLint) sampObj->MaxLod;
1435      break;
1436   case GL_TEXTURE_LOD_BIAS:
1437      *params = (GLint) sampObj->LodBias;
1438      break;
1439   case GL_TEXTURE_COMPARE_MODE:
1440      if (!ctx->Extensions.ARB_shadow)
1441         goto invalid_pname;
1442      *params = sampObj->CompareMode;
1443      break;
1444   case GL_TEXTURE_COMPARE_FUNC:
1445      if (!ctx->Extensions.ARB_shadow)
1446         goto invalid_pname;
1447      *params = sampObj->CompareFunc;
1448      break;
1449   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1450      *params = (GLint) sampObj->MaxAnisotropy;
1451      break;
1452   case GL_TEXTURE_BORDER_COLOR:
1453      params[0] = sampObj->BorderColor.i[0];
1454      params[1] = sampObj->BorderColor.i[1];
1455      params[2] = sampObj->BorderColor.i[2];
1456      params[3] = sampObj->BorderColor.i[3];
1457      break;
1458   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1459      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1460         goto invalid_pname;
1461      *params = sampObj->CubeMapSeamless;
1462      break;
1463   case GL_TEXTURE_SRGB_DECODE_EXT:
1464      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1465         goto invalid_pname;
1466      *params = (GLenum) sampObj->sRGBDecode;
1467      break;
1468   default:
1469      goto invalid_pname;
1470   }
1471   return;
1472
1473invalid_pname:
1474   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
1475               _mesa_lookup_enum_by_nr(pname));
1476}
1477
1478
1479void GLAPIENTRY
1480_mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
1481{
1482   struct gl_sampler_object *sampObj;
1483   GET_CURRENT_CONTEXT(ctx);
1484
1485   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1486   if (!sampObj) {
1487      _mesa_error(ctx, GL_INVALID_VALUE,
1488                  "glGetSamplerParameterIuiv(sampler %u)",
1489                  sampler);
1490      return;
1491   }
1492
1493   switch (pname) {
1494   case GL_TEXTURE_WRAP_S:
1495      *params = sampObj->WrapS;
1496      break;
1497   case GL_TEXTURE_WRAP_T:
1498      *params = sampObj->WrapT;
1499      break;
1500   case GL_TEXTURE_WRAP_R:
1501      *params = sampObj->WrapR;
1502      break;
1503   case GL_TEXTURE_MIN_FILTER:
1504      *params = sampObj->MinFilter;
1505      break;
1506   case GL_TEXTURE_MAG_FILTER:
1507      *params = sampObj->MagFilter;
1508      break;
1509   case GL_TEXTURE_MIN_LOD:
1510      *params = (GLuint) sampObj->MinLod;
1511      break;
1512   case GL_TEXTURE_MAX_LOD:
1513      *params = (GLuint) sampObj->MaxLod;
1514      break;
1515   case GL_TEXTURE_LOD_BIAS:
1516      *params = (GLuint) sampObj->LodBias;
1517      break;
1518   case GL_TEXTURE_COMPARE_MODE:
1519      if (!ctx->Extensions.ARB_shadow)
1520         goto invalid_pname;
1521      *params = sampObj->CompareMode;
1522      break;
1523   case GL_TEXTURE_COMPARE_FUNC:
1524      if (!ctx->Extensions.ARB_shadow)
1525         goto invalid_pname;
1526      *params = sampObj->CompareFunc;
1527      break;
1528   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1529      *params = (GLuint) sampObj->MaxAnisotropy;
1530      break;
1531   case GL_TEXTURE_BORDER_COLOR:
1532      params[0] = sampObj->BorderColor.ui[0];
1533      params[1] = sampObj->BorderColor.ui[1];
1534      params[2] = sampObj->BorderColor.ui[2];
1535      params[3] = sampObj->BorderColor.ui[3];
1536      break;
1537   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1538      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1539         goto invalid_pname;
1540      *params = sampObj->CubeMapSeamless;
1541      break;
1542   case GL_TEXTURE_SRGB_DECODE_EXT:
1543      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1544         goto invalid_pname;
1545      *params = (GLenum) sampObj->sRGBDecode;
1546      break;
1547   default:
1548      goto invalid_pname;
1549   }
1550   return;
1551
1552invalid_pname:
1553   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
1554               _mesa_lookup_enum_by_nr(pname));
1555}
1556
1557
1558void
1559_mesa_init_sampler_object_functions(struct dd_function_table *driver)
1560{
1561   driver->NewSamplerObject = _mesa_new_sampler_object;
1562   driver->DeleteSamplerObject = _mesa_delete_sampler_object;
1563}
1564