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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24
25/**
26 * \file samplerobj.c
27 * \brief Functions for the GL_ARB_sampler_objects extension.
28 * \author Brian Paul
29 */
30
31
32#include "main/glheader.h"
33#include "main/context.h"
34#include "main/dispatch.h"
35#include "main/enums.h"
36#include "main/hash.h"
37#include "main/macros.h"
38#include "main/mfeatures.h"
39#include "main/mtypes.h"
40#include "main/samplerobj.h"
41
42
43static struct gl_sampler_object *
44_mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name)
45{
46   if (name == 0)
47      return NULL;
48   else
49      return (struct gl_sampler_object *)
50         _mesa_HashLookup(ctx->Shared->SamplerObjects, name);
51}
52
53
54/**
55 * Handle reference counting.
56 */
57void
58_mesa_reference_sampler_object_(struct gl_context *ctx,
59                                struct gl_sampler_object **ptr,
60                                struct gl_sampler_object *samp)
61{
62   assert(*ptr != samp); /* The inline wrapper should prevent no-op calls */
63
64   if (*ptr) {
65      /* Unreference the old sampler */
66      GLboolean deleteFlag = GL_FALSE;
67      struct gl_sampler_object *oldSamp = *ptr;
68
69      /*_glthread_LOCK_MUTEX(oldSamp->Mutex);*/
70      ASSERT(oldSamp->RefCount > 0);
71      oldSamp->RefCount--;
72#if 0
73      printf("SamplerObj %p %d DECR to %d\n",
74             (void *) oldSamp, oldSamp->Name, oldSamp->RefCount);
75#endif
76      deleteFlag = (oldSamp->RefCount == 0);
77      /*_glthread_UNLOCK_MUTEX(oldSamp->Mutex);*/
78
79      if (deleteFlag) {
80	 ASSERT(ctx->Driver.DeleteSamplerObject);
81         ctx->Driver.DeleteSamplerObject(ctx, oldSamp);
82      }
83
84      *ptr = NULL;
85   }
86   ASSERT(!*ptr);
87
88   if (samp) {
89      /* reference new sampler */
90      /*_glthread_LOCK_MUTEX(samp->Mutex);*/
91      if (samp->RefCount == 0) {
92         /* this sampler's being deleted (look just above) */
93         /* Not sure this can every really happen.  Warn if it does. */
94         _mesa_problem(NULL, "referencing deleted sampler object");
95         *ptr = NULL;
96      }
97      else {
98         samp->RefCount++;
99#if 0
100         printf("SamplerObj %p %d INCR to %d\n",
101                (void *) samp, samp->Name, samp->RefCount);
102#endif
103         *ptr = samp;
104      }
105      /*_glthread_UNLOCK_MUTEX(samp->Mutex);*/
106   }
107}
108
109
110/**
111 * Initialize the fields of the given sampler object.
112 */
113void
114_mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
115{
116   sampObj->Name = name;
117   sampObj->RefCount = 1;
118   sampObj->WrapS = GL_REPEAT;
119   sampObj->WrapT = GL_REPEAT;
120   sampObj->WrapR = GL_REPEAT;
121   sampObj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
122   sampObj->MagFilter = GL_LINEAR;
123   sampObj->BorderColor.f[0] = 0.0;
124   sampObj->BorderColor.f[1] = 0.0;
125   sampObj->BorderColor.f[2] = 0.0;
126   sampObj->BorderColor.f[3] = 0.0;
127   sampObj->MinLod = -1000.0F;
128   sampObj->MaxLod = 1000.0F;
129   sampObj->LodBias = 0.0F;
130   sampObj->MaxAnisotropy = 1.0F;
131   sampObj->CompareMode = GL_NONE;
132   sampObj->CompareFunc = GL_LEQUAL;
133   sampObj->sRGBDecode = GL_DECODE_EXT;
134   sampObj->CubeMapSeamless = GL_FALSE;
135}
136
137/**
138 * Fallback for ctx->Driver.NewSamplerObject();
139 */
140struct gl_sampler_object *
141_mesa_new_sampler_object(struct gl_context *ctx, GLuint name)
142{
143   struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object);
144   if (sampObj) {
145      _mesa_init_sampler_object(sampObj, name);
146   }
147   return sampObj;
148}
149
150
151/**
152 * Fallback for ctx->Driver.DeleteSamplerObject();
153 */
154void
155_mesa_delete_sampler_object(struct gl_context *ctx,
156                            struct gl_sampler_object *sampObj)
157{
158   FREE(sampObj);
159}
160
161
162void GLAPIENTRY
163_mesa_GenSamplers(GLsizei count, GLuint *samplers)
164{
165   GET_CURRENT_CONTEXT(ctx);
166   GLuint first;
167   GLint i;
168
169   ASSERT_OUTSIDE_BEGIN_END(ctx);
170
171   if (MESA_VERBOSE & VERBOSE_API)
172      _mesa_debug(ctx, "glGenSamplers(%d)\n", count);
173
174   if (count < 0) {
175      _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers");
176      return;
177   }
178
179   if (!samplers)
180      return;
181
182   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count);
183
184   /* Insert the ID and pointer to new sampler object into hash table */
185   for (i = 0; i < count; i++) {
186      struct gl_sampler_object *sampObj =
187         ctx->Driver.NewSamplerObject(ctx, first + i);
188      _mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj);
189      samplers[i] = first + i;
190   }
191}
192
193
194void GLAPIENTRY
195_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
196{
197   GET_CURRENT_CONTEXT(ctx);
198   GLsizei i;
199
200   ASSERT_OUTSIDE_BEGIN_END(ctx);
201   FLUSH_VERTICES(ctx, 0);
202
203   if (count < 0) {
204      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
205      return;
206   }
207
208   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
209
210   for (i = 0; i < count; i++) {
211      if (samplers[i]) {
212         struct gl_sampler_object *sampObj =
213            _mesa_lookup_samplerobj(ctx, samplers[i]);
214         if (sampObj) {
215            /* The ID is immediately freed for re-use */
216            _mesa_HashRemove(ctx->Shared->SamplerObjects, samplers[i]);
217            /* But the object exists until its reference count goes to zero */
218            _mesa_reference_sampler_object(ctx, &sampObj, NULL);
219         }
220      }
221   }
222
223   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
224}
225
226
227static GLboolean GLAPIENTRY
228_mesa_IsSampler(GLuint sampler)
229{
230   struct gl_sampler_object *sampObj;
231   GET_CURRENT_CONTEXT(ctx);
232
233   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
234
235   if (sampler == 0)
236      return GL_FALSE;
237
238   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
239
240   return sampObj != NULL;
241}
242
243
244void GLAPIENTRY
245_mesa_BindSampler(GLuint unit, GLuint sampler)
246{
247   struct gl_sampler_object *sampObj;
248   GET_CURRENT_CONTEXT(ctx);
249
250   if (unit >= ctx->Const.MaxCombinedTextureImageUnits) {
251      _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
252      return;
253   }
254
255   if (sampler == 0) {
256      /* Use the default sampler object, the one contained in the texture
257       * object.
258       */
259      sampObj = NULL;
260   }
261   else {
262      /* user-defined sampler object */
263      sampObj = _mesa_lookup_samplerobj(ctx, sampler);
264      if (!sampObj) {
265         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)");
266         return;
267      }
268   }
269
270   if (ctx->Texture.Unit[unit].Sampler != sampObj) {
271      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
272   }
273
274   /* bind new sampler */
275   _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler,
276                                  sampObj);
277}
278
279
280/**
281 * Check if a coordinate wrap mode is legal.
282 * \return GL_TRUE if legal, GL_FALSE otherwise
283 */
284static GLboolean
285validate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap)
286{
287   const struct gl_extensions * const e = &ctx->Extensions;
288
289   switch (wrap) {
290   case GL_CLAMP:
291   case GL_CLAMP_TO_EDGE:
292   case GL_REPEAT:
293   case GL_MIRRORED_REPEAT:
294      return GL_TRUE;
295   case GL_CLAMP_TO_BORDER:
296      return e->ARB_texture_border_clamp;
297   case GL_MIRROR_CLAMP_EXT:
298      return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
299   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
300      return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
301   case GL_MIRROR_CLAMP_TO_BORDER_EXT:
302      return e->EXT_texture_mirror_clamp;
303   default:
304      return GL_FALSE;
305   }
306}
307
308
309/**
310 * This is called just prior to changing any sampler object state.
311 */
312static inline void
313flush(struct gl_context *ctx)
314{
315   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
316}
317
318
319#define INVALID_PARAM 0x100
320#define INVALID_PNAME 0x101
321#define INVALID_VALUE 0x102
322
323static GLuint
324set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
325                   GLint param)
326{
327   if (samp->WrapS == param)
328      return GL_FALSE;
329   if (validate_texture_wrap_mode(ctx, param)) {
330      flush(ctx);
331      samp->WrapS = param;
332      return GL_TRUE;
333   }
334   return INVALID_PARAM;
335}
336
337
338static GLuint
339set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
340                   GLint param)
341{
342   if (samp->WrapT == param)
343      return GL_FALSE;
344   if (validate_texture_wrap_mode(ctx, param)) {
345      flush(ctx);
346      samp->WrapT = param;
347      return GL_TRUE;
348   }
349   return INVALID_PARAM;
350}
351
352
353static GLuint
354set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
355                   GLint param)
356{
357   if (samp->WrapR == param)
358      return GL_FALSE;
359   if (validate_texture_wrap_mode(ctx, param)) {
360      flush(ctx);
361      samp->WrapR = param;
362      return GL_TRUE;
363   }
364   return INVALID_PARAM;
365}
366
367
368static GLuint
369set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
370                       GLint param)
371{
372   if (samp->MinFilter == param)
373      return GL_FALSE;
374
375   switch (param) {
376   case GL_NEAREST:
377   case GL_LINEAR:
378   case GL_NEAREST_MIPMAP_NEAREST:
379   case GL_LINEAR_MIPMAP_NEAREST:
380   case GL_NEAREST_MIPMAP_LINEAR:
381   case GL_LINEAR_MIPMAP_LINEAR:
382      flush(ctx);
383      samp->MinFilter = param;
384      return GL_TRUE;
385   default:
386      return INVALID_PARAM;
387   }
388}
389
390
391static GLuint
392set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
393                       GLint param)
394{
395   if (samp->MagFilter == param)
396      return GL_FALSE;
397
398   switch (param) {
399   case GL_NEAREST:
400   case GL_LINEAR:
401      flush(ctx);
402      samp->MagFilter = param;
403      return GL_TRUE;
404   default:
405      return INVALID_PARAM;
406   }
407}
408
409
410static GLuint
411set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
412                     GLfloat param)
413{
414   if (samp->LodBias == param)
415      return GL_FALSE;
416
417   flush(ctx);
418   samp->LodBias = param;
419   return GL_TRUE;
420}
421
422
423static GLuint
424set_sampler_border_colorf(struct gl_context *ctx,
425                          struct gl_sampler_object *samp,
426                          const GLfloat params[4])
427{
428   flush(ctx);
429   samp->BorderColor.f[RCOMP] = params[0];
430   samp->BorderColor.f[GCOMP] = params[1];
431   samp->BorderColor.f[BCOMP] = params[2];
432   samp->BorderColor.f[ACOMP] = params[3];
433   return GL_TRUE;
434}
435
436
437static GLuint
438set_sampler_border_colori(struct gl_context *ctx,
439                          struct gl_sampler_object *samp,
440                          const GLint params[4])
441{
442   flush(ctx);
443   samp->BorderColor.i[RCOMP] = params[0];
444   samp->BorderColor.i[GCOMP] = params[1];
445   samp->BorderColor.i[BCOMP] = params[2];
446   samp->BorderColor.i[ACOMP] = params[3];
447   return GL_TRUE;
448}
449
450
451static GLuint
452set_sampler_border_colorui(struct gl_context *ctx,
453                           struct gl_sampler_object *samp,
454                           const GLuint params[4])
455{
456   flush(ctx);
457   samp->BorderColor.ui[RCOMP] = params[0];
458   samp->BorderColor.ui[GCOMP] = params[1];
459   samp->BorderColor.ui[BCOMP] = params[2];
460   samp->BorderColor.ui[ACOMP] = params[3];
461   return GL_TRUE;
462}
463
464
465static GLuint
466set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
467                    GLfloat param)
468{
469   if (samp->MinLod == param)
470      return GL_FALSE;
471
472   flush(ctx);
473   samp->MinLod = param;
474   return GL_TRUE;
475}
476
477
478static GLuint
479set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
480                    GLfloat param)
481{
482   if (samp->MaxLod == param)
483      return GL_FALSE;
484
485   flush(ctx);
486   samp->MaxLod = param;
487   return GL_TRUE;
488}
489
490
491static GLuint
492set_sampler_compare_mode(struct gl_context *ctx,
493                         struct gl_sampler_object *samp, GLint param)
494{
495   if (!ctx->Extensions.ARB_shadow)
496      return INVALID_PNAME;
497
498   if (samp->CompareMode == param)
499      return GL_FALSE;
500
501   if (param == GL_NONE ||
502       param == GL_COMPARE_R_TO_TEXTURE_ARB) {
503      flush(ctx);
504      samp->CompareMode = param;
505      return GL_TRUE;
506   }
507
508   return INVALID_PARAM;
509}
510
511
512static GLuint
513set_sampler_compare_func(struct gl_context *ctx,
514                         struct gl_sampler_object *samp, GLint param)
515{
516   if (!ctx->Extensions.ARB_shadow)
517      return INVALID_PNAME;
518
519   if (samp->CompareFunc == param)
520      return GL_FALSE;
521
522   switch (param) {
523   case GL_LEQUAL:
524   case GL_GEQUAL:
525      flush(ctx);
526      samp->CompareFunc = param;
527      return GL_TRUE;
528   case GL_EQUAL:
529   case GL_NOTEQUAL:
530   case GL_LESS:
531   case GL_GREATER:
532   case GL_ALWAYS:
533   case GL_NEVER:
534      if (ctx->Extensions.EXT_shadow_funcs) {
535         flush(ctx);
536         samp->CompareFunc = param;
537         return GL_TRUE;
538      }
539      /* fall-through */
540   default:
541      return INVALID_PARAM;
542   }
543}
544
545
546static GLuint
547set_sampler_max_anisotropy(struct gl_context *ctx,
548                           struct gl_sampler_object *samp, GLfloat param)
549{
550   if (!ctx->Extensions.EXT_texture_filter_anisotropic)
551      return INVALID_PNAME;
552
553   if (samp->MaxAnisotropy == param)
554      return GL_FALSE;
555
556   if (param < 1.0)
557      return INVALID_VALUE;
558
559   flush(ctx);
560   /* clamp to max, that's what NVIDIA does */
561   samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
562   return GL_TRUE;
563}
564
565
566static GLuint
567set_sampler_cube_map_seamless(struct gl_context *ctx,
568                              struct gl_sampler_object *samp, GLboolean param)
569{
570   if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
571      return INVALID_PNAME;
572
573   if (samp->CubeMapSeamless == param)
574      return GL_FALSE;
575
576   if (param != GL_TRUE && param != GL_FALSE)
577      return INVALID_VALUE;
578
579   flush(ctx);
580   samp->CubeMapSeamless = param;
581   return GL_TRUE;
582}
583
584static GLuint
585set_sampler_srgb_decode(struct gl_context *ctx,
586                              struct gl_sampler_object *samp, GLenum param)
587{
588   if (!ctx->Extensions.EXT_texture_sRGB_decode)
589      return INVALID_PNAME;
590
591   if (samp->sRGBDecode == param)
592      return GL_FALSE;
593
594   if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
595      return INVALID_VALUE;
596
597   flush(ctx);
598   samp->sRGBDecode = param;
599   return GL_TRUE;
600}
601
602void GLAPIENTRY
603_mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
604{
605   struct gl_sampler_object *sampObj;
606   GLuint res;
607   GET_CURRENT_CONTEXT(ctx);
608
609   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
610   if (!sampObj) {
611      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)",
612                  sampler);
613      return;
614   }
615
616   switch (pname) {
617   case GL_TEXTURE_WRAP_S:
618      res = set_sampler_wrap_s(ctx, sampObj, param);
619      break;
620   case GL_TEXTURE_WRAP_T:
621      res = set_sampler_wrap_t(ctx, sampObj, param);
622      break;
623   case GL_TEXTURE_WRAP_R:
624      res = set_sampler_wrap_r(ctx, sampObj, param);
625      break;
626   case GL_TEXTURE_MIN_FILTER:
627      res = set_sampler_min_filter(ctx, sampObj, param);
628      break;
629   case GL_TEXTURE_MAG_FILTER:
630      res = set_sampler_mag_filter(ctx, sampObj, param);
631      break;
632   case GL_TEXTURE_MIN_LOD:
633      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
634      break;
635   case GL_TEXTURE_MAX_LOD:
636      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
637      break;
638   case GL_TEXTURE_LOD_BIAS:
639      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
640      break;
641   case GL_TEXTURE_COMPARE_MODE:
642      res = set_sampler_compare_mode(ctx, sampObj, param);
643      break;
644   case GL_TEXTURE_COMPARE_FUNC:
645      res = set_sampler_compare_func(ctx, sampObj, param);
646      break;
647   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
648      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
649      break;
650   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
651      res = set_sampler_cube_map_seamless(ctx, sampObj, param);
652      break;
653   case GL_TEXTURE_SRGB_DECODE_EXT:
654      res = set_sampler_srgb_decode(ctx, sampObj, param);
655      break;
656   case GL_TEXTURE_BORDER_COLOR:
657      /* fall-through */
658   default:
659      res = INVALID_PNAME;
660   }
661
662   switch (res) {
663   case GL_FALSE:
664      /* no change */
665      break;
666   case GL_TRUE:
667      /* state change - we do nothing special at this time */
668      break;
669   case INVALID_PNAME:
670      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
671                  _mesa_lookup_enum_by_nr(pname));
672      break;
673   case INVALID_PARAM:
674      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
675                  param);
676      break;
677   case INVALID_VALUE:
678      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
679                  param);
680      break;
681   default:
682      ;
683   }
684}
685
686
687static void GLAPIENTRY
688_mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
689{
690   struct gl_sampler_object *sampObj;
691   GLuint res;
692   GET_CURRENT_CONTEXT(ctx);
693
694   ASSERT_OUTSIDE_BEGIN_END(ctx);
695
696   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
697   if (!sampObj) {
698      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(sampler %u)",
699                  sampler);
700      return;
701   }
702
703   switch (pname) {
704   case GL_TEXTURE_WRAP_S:
705      res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
706      break;
707   case GL_TEXTURE_WRAP_T:
708      res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
709      break;
710   case GL_TEXTURE_WRAP_R:
711      res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
712      break;
713   case GL_TEXTURE_MIN_FILTER:
714      res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
715      break;
716   case GL_TEXTURE_MAG_FILTER:
717      res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
718      break;
719   case GL_TEXTURE_MIN_LOD:
720      res = set_sampler_min_lod(ctx, sampObj, param);
721      break;
722   case GL_TEXTURE_MAX_LOD:
723      res = set_sampler_max_lod(ctx, sampObj, param);
724      break;
725   case GL_TEXTURE_LOD_BIAS:
726      res = set_sampler_lod_bias(ctx, sampObj, param);
727      break;
728   case GL_TEXTURE_COMPARE_MODE:
729      res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
730      break;
731   case GL_TEXTURE_COMPARE_FUNC:
732      res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
733      break;
734   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
735      res = set_sampler_max_anisotropy(ctx, sampObj, param);
736      break;
737   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
738      res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) param);
739      break;
740   case GL_TEXTURE_SRGB_DECODE_EXT:
741      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) param);
742      break;
743   case GL_TEXTURE_BORDER_COLOR:
744      /* fall-through */
745   default:
746      res = INVALID_PNAME;
747   }
748
749   switch (res) {
750   case GL_FALSE:
751      /* no change */
752      break;
753   case GL_TRUE:
754      /* state change - we do nothing special at this time */
755      break;
756   case INVALID_PNAME:
757      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
758                  _mesa_lookup_enum_by_nr(pname));
759      break;
760   case INVALID_PARAM:
761      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
762                  param);
763      break;
764   case INVALID_VALUE:
765      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
766                  param);
767      break;
768   default:
769      ;
770   }
771}
772
773static void GLAPIENTRY
774_mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
775{
776   struct gl_sampler_object *sampObj;
777   GLuint res;
778   GET_CURRENT_CONTEXT(ctx);
779
780   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
781   if (!sampObj) {
782      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(sampler %u)",
783                  sampler);
784      return;
785   }
786
787   switch (pname) {
788   case GL_TEXTURE_WRAP_S:
789      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
790      break;
791   case GL_TEXTURE_WRAP_T:
792      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
793      break;
794   case GL_TEXTURE_WRAP_R:
795      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
796      break;
797   case GL_TEXTURE_MIN_FILTER:
798      res = set_sampler_min_filter(ctx, sampObj, params[0]);
799      break;
800   case GL_TEXTURE_MAG_FILTER:
801      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
802      break;
803   case GL_TEXTURE_MIN_LOD:
804      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
805      break;
806   case GL_TEXTURE_MAX_LOD:
807      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
808      break;
809   case GL_TEXTURE_LOD_BIAS:
810      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
811      break;
812   case GL_TEXTURE_COMPARE_MODE:
813      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
814      break;
815   case GL_TEXTURE_COMPARE_FUNC:
816      res = set_sampler_compare_func(ctx, sampObj, params[0]);
817      break;
818   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
819      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
820      break;
821   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
822      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
823      break;
824   case GL_TEXTURE_SRGB_DECODE_EXT:
825      res = set_sampler_srgb_decode(ctx, sampObj, params[0]);
826      break;
827   case GL_TEXTURE_BORDER_COLOR:
828      {
829         GLfloat c[4];
830         c[0] = INT_TO_FLOAT(params[0]);
831         c[1] = INT_TO_FLOAT(params[1]);
832         c[2] = INT_TO_FLOAT(params[2]);
833         c[3] = INT_TO_FLOAT(params[3]);
834         res = set_sampler_border_colorf(ctx, sampObj, c);
835      }
836      break;
837   default:
838      res = INVALID_PNAME;
839   }
840
841   switch (res) {
842   case GL_FALSE:
843      /* no change */
844      break;
845   case GL_TRUE:
846      /* state change - we do nothing special at this time */
847      break;
848   case INVALID_PNAME:
849      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
850                  _mesa_lookup_enum_by_nr(pname));
851      break;
852   case INVALID_PARAM:
853      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
854                  params[0]);
855      break;
856   case INVALID_VALUE:
857      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
858                  params[0]);
859      break;
860   default:
861      ;
862   }
863}
864
865static void GLAPIENTRY
866_mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
867{
868   struct gl_sampler_object *sampObj;
869   GLuint res;
870   GET_CURRENT_CONTEXT(ctx);
871
872   ASSERT_OUTSIDE_BEGIN_END(ctx);
873
874   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
875   if (!sampObj) {
876      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(sampler %u)",
877                  sampler);
878      return;
879   }
880
881   switch (pname) {
882   case GL_TEXTURE_WRAP_S:
883      res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
884      break;
885   case GL_TEXTURE_WRAP_T:
886      res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
887      break;
888   case GL_TEXTURE_WRAP_R:
889      res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
890      break;
891   case GL_TEXTURE_MIN_FILTER:
892      res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
893      break;
894   case GL_TEXTURE_MAG_FILTER:
895      res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
896      break;
897   case GL_TEXTURE_MIN_LOD:
898      res = set_sampler_min_lod(ctx, sampObj, params[0]);
899      break;
900   case GL_TEXTURE_MAX_LOD:
901      res = set_sampler_max_lod(ctx, sampObj, params[0]);
902      break;
903   case GL_TEXTURE_LOD_BIAS:
904      res = set_sampler_lod_bias(ctx, sampObj, params[0]);
905      break;
906   case GL_TEXTURE_COMPARE_MODE:
907      res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
908      break;
909   case GL_TEXTURE_COMPARE_FUNC:
910      res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
911      break;
912   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
913      res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
914      break;
915   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
916      res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]);
917      break;
918   case GL_TEXTURE_SRGB_DECODE_EXT:
919      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
920      break;
921   case GL_TEXTURE_BORDER_COLOR:
922      res = set_sampler_border_colorf(ctx, sampObj, params);
923      break;
924   default:
925      res = INVALID_PNAME;
926   }
927
928   switch (res) {
929   case GL_FALSE:
930      /* no change */
931      break;
932   case GL_TRUE:
933      /* state change - we do nothing special at this time */
934      break;
935   case INVALID_PNAME:
936      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
937                  _mesa_lookup_enum_by_nr(pname));
938      break;
939   case INVALID_PARAM:
940      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
941                  params[0]);
942      break;
943   case INVALID_VALUE:
944      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
945                  params[0]);
946      break;
947   default:
948      ;
949   }
950}
951
952static void GLAPIENTRY
953_mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
954{
955   struct gl_sampler_object *sampObj;
956   GLuint res;
957   GET_CURRENT_CONTEXT(ctx);
958
959   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
960   if (!sampObj) {
961      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(sampler %u)",
962                  sampler);
963      return;
964   }
965
966   switch (pname) {
967   case GL_TEXTURE_WRAP_S:
968      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
969      break;
970   case GL_TEXTURE_WRAP_T:
971      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
972      break;
973   case GL_TEXTURE_WRAP_R:
974      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
975      break;
976   case GL_TEXTURE_MIN_FILTER:
977      res = set_sampler_min_filter(ctx, sampObj, params[0]);
978      break;
979   case GL_TEXTURE_MAG_FILTER:
980      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
981      break;
982   case GL_TEXTURE_MIN_LOD:
983      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
984      break;
985   case GL_TEXTURE_MAX_LOD:
986      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
987      break;
988   case GL_TEXTURE_LOD_BIAS:
989      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
990      break;
991   case GL_TEXTURE_COMPARE_MODE:
992      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
993      break;
994   case GL_TEXTURE_COMPARE_FUNC:
995      res = set_sampler_compare_func(ctx, sampObj, params[0]);
996      break;
997   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
998      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
999      break;
1000   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1001      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1002      break;
1003   case GL_TEXTURE_SRGB_DECODE_EXT:
1004      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1005      break;
1006   case GL_TEXTURE_BORDER_COLOR:
1007      res = set_sampler_border_colori(ctx, sampObj, params);
1008      break;
1009   default:
1010      res = INVALID_PNAME;
1011   }
1012
1013   switch (res) {
1014   case GL_FALSE:
1015      /* no change */
1016      break;
1017   case GL_TRUE:
1018      /* state change - we do nothing special at this time */
1019      break;
1020   case INVALID_PNAME:
1021      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
1022                  _mesa_lookup_enum_by_nr(pname));
1023      break;
1024   case INVALID_PARAM:
1025      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
1026                  params[0]);
1027      break;
1028   case INVALID_VALUE:
1029      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
1030                  params[0]);
1031      break;
1032   default:
1033      ;
1034   }
1035}
1036
1037
1038static void GLAPIENTRY
1039_mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
1040{
1041   struct gl_sampler_object *sampObj;
1042   GLuint res;
1043   GET_CURRENT_CONTEXT(ctx);
1044
1045   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1046   if (!sampObj) {
1047      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(sampler %u)",
1048                  sampler);
1049      return;
1050   }
1051
1052   switch (pname) {
1053   case GL_TEXTURE_WRAP_S:
1054      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1055      break;
1056   case GL_TEXTURE_WRAP_T:
1057      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1058      break;
1059   case GL_TEXTURE_WRAP_R:
1060      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1061      break;
1062   case GL_TEXTURE_MIN_FILTER:
1063      res = set_sampler_min_filter(ctx, sampObj, params[0]);
1064      break;
1065   case GL_TEXTURE_MAG_FILTER:
1066      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1067      break;
1068   case GL_TEXTURE_MIN_LOD:
1069      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1070      break;
1071   case GL_TEXTURE_MAX_LOD:
1072      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1073      break;
1074   case GL_TEXTURE_LOD_BIAS:
1075      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1076      break;
1077   case GL_TEXTURE_COMPARE_MODE:
1078      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1079      break;
1080   case GL_TEXTURE_COMPARE_FUNC:
1081      res = set_sampler_compare_func(ctx, sampObj, params[0]);
1082      break;
1083   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1084      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1085      break;
1086   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1087      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1088      break;
1089   case GL_TEXTURE_SRGB_DECODE_EXT:
1090      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1091      break;
1092   case GL_TEXTURE_BORDER_COLOR:
1093      res = set_sampler_border_colorui(ctx, sampObj, params);
1094      break;
1095   default:
1096      res = INVALID_PNAME;
1097   }
1098
1099   switch (res) {
1100   case GL_FALSE:
1101      /* no change */
1102      break;
1103   case GL_TRUE:
1104      /* state change - we do nothing special at this time */
1105      break;
1106   case INVALID_PNAME:
1107      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
1108                  _mesa_lookup_enum_by_nr(pname));
1109      break;
1110   case INVALID_PARAM:
1111      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
1112                  params[0]);
1113      break;
1114   case INVALID_VALUE:
1115      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
1116                  params[0]);
1117      break;
1118   default:
1119      ;
1120   }
1121}
1122
1123
1124static void GLAPIENTRY
1125_mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
1126{
1127   struct gl_sampler_object *sampObj;
1128   GET_CURRENT_CONTEXT(ctx);
1129
1130   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1131   if (!sampObj) {
1132      _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameteriv(sampler %u)",
1133                  sampler);
1134      return;
1135   }
1136
1137   switch (pname) {
1138   case GL_TEXTURE_WRAP_S:
1139      *params = sampObj->WrapS;
1140      break;
1141   case GL_TEXTURE_WRAP_T:
1142      *params = sampObj->WrapT;
1143      break;
1144   case GL_TEXTURE_WRAP_R:
1145      *params = sampObj->WrapR;
1146      break;
1147   case GL_TEXTURE_MIN_FILTER:
1148      *params = sampObj->MinFilter;
1149      break;
1150   case GL_TEXTURE_MAG_FILTER:
1151      *params = sampObj->MagFilter;
1152      break;
1153   case GL_TEXTURE_MIN_LOD:
1154      *params = (GLint) sampObj->MinLod;
1155      break;
1156   case GL_TEXTURE_MAX_LOD:
1157      *params = (GLint) sampObj->MaxLod;
1158      break;
1159   case GL_TEXTURE_LOD_BIAS:
1160      *params = (GLint) sampObj->LodBias;
1161      break;
1162   case GL_TEXTURE_COMPARE_MODE:
1163      if (!ctx->Extensions.ARB_shadow)
1164         goto invalid_pname;
1165      *params = sampObj->CompareMode;
1166      break;
1167   case GL_TEXTURE_COMPARE_FUNC:
1168      if (!ctx->Extensions.ARB_shadow)
1169         goto invalid_pname;
1170      *params = sampObj->CompareFunc;
1171      break;
1172   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1173      *params = (GLint) sampObj->MaxAnisotropy;
1174      break;
1175   case GL_TEXTURE_BORDER_COLOR:
1176      params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
1177      params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
1178      params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
1179      params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
1180      break;
1181   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1182      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1183         goto invalid_pname;
1184      *params = sampObj->CubeMapSeamless;
1185      break;
1186   case GL_TEXTURE_SRGB_DECODE_EXT:
1187      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1188         goto invalid_pname;
1189      *params = (GLenum) sampObj->sRGBDecode;
1190      break;
1191   default:
1192      goto invalid_pname;
1193   }
1194   return;
1195
1196invalid_pname:
1197   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
1198               _mesa_lookup_enum_by_nr(pname));
1199}
1200
1201
1202static void GLAPIENTRY
1203_mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
1204{
1205   struct gl_sampler_object *sampObj;
1206   GET_CURRENT_CONTEXT(ctx);
1207
1208   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1209   if (!sampObj) {
1210      _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameterfv(sampler %u)",
1211                  sampler);
1212      return;
1213   }
1214
1215   switch (pname) {
1216   case GL_TEXTURE_WRAP_S:
1217      *params = (GLfloat) sampObj->WrapS;
1218      break;
1219   case GL_TEXTURE_WRAP_T:
1220      *params = (GLfloat) sampObj->WrapT;
1221      break;
1222   case GL_TEXTURE_WRAP_R:
1223      *params = (GLfloat) sampObj->WrapR;
1224      break;
1225   case GL_TEXTURE_MIN_FILTER:
1226      *params = (GLfloat) sampObj->MinFilter;
1227      break;
1228   case GL_TEXTURE_MAG_FILTER:
1229      *params = (GLfloat) sampObj->MagFilter;
1230      break;
1231   case GL_TEXTURE_MIN_LOD:
1232      *params = sampObj->MinLod;
1233      break;
1234   case GL_TEXTURE_MAX_LOD:
1235      *params = sampObj->MaxLod;
1236      break;
1237   case GL_TEXTURE_LOD_BIAS:
1238      *params = sampObj->LodBias;
1239      break;
1240   case GL_TEXTURE_COMPARE_MODE:
1241      if (!ctx->Extensions.ARB_shadow)
1242         goto invalid_pname;
1243      *params = (GLfloat) sampObj->CompareMode;
1244      break;
1245   case GL_TEXTURE_COMPARE_FUNC:
1246      if (!ctx->Extensions.ARB_shadow)
1247         goto invalid_pname;
1248      *params = (GLfloat) sampObj->CompareFunc;
1249      break;
1250   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1251      *params = sampObj->MaxAnisotropy;
1252      break;
1253   case GL_TEXTURE_BORDER_COLOR:
1254      params[0] = sampObj->BorderColor.f[0];
1255      params[1] = sampObj->BorderColor.f[1];
1256      params[2] = sampObj->BorderColor.f[2];
1257      params[3] = sampObj->BorderColor.f[3];
1258      break;
1259   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1260      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1261         goto invalid_pname;
1262      *params = (GLfloat) sampObj->CubeMapSeamless;
1263      break;
1264   case GL_TEXTURE_SRGB_DECODE_EXT:
1265      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1266         goto invalid_pname;
1267      *params = (GLfloat) sampObj->sRGBDecode;
1268      break;
1269   default:
1270      goto invalid_pname;
1271   }
1272   return;
1273
1274invalid_pname:
1275   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
1276               _mesa_lookup_enum_by_nr(pname));
1277}
1278
1279
1280static void GLAPIENTRY
1281_mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
1282{
1283   struct gl_sampler_object *sampObj;
1284   GET_CURRENT_CONTEXT(ctx);
1285
1286   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1287   if (!sampObj) {
1288      _mesa_error(ctx, GL_INVALID_VALUE,
1289                  "glGetSamplerParameterIiv(sampler %u)",
1290                  sampler);
1291      return;
1292   }
1293
1294   switch (pname) {
1295   case GL_TEXTURE_WRAP_S:
1296      *params = sampObj->WrapS;
1297      break;
1298   case GL_TEXTURE_WRAP_T:
1299      *params = sampObj->WrapT;
1300      break;
1301   case GL_TEXTURE_WRAP_R:
1302      *params = sampObj->WrapR;
1303      break;
1304   case GL_TEXTURE_MIN_FILTER:
1305      *params = sampObj->MinFilter;
1306      break;
1307   case GL_TEXTURE_MAG_FILTER:
1308      *params = sampObj->MagFilter;
1309      break;
1310   case GL_TEXTURE_MIN_LOD:
1311      *params = (GLint) sampObj->MinLod;
1312      break;
1313   case GL_TEXTURE_MAX_LOD:
1314      *params = (GLint) sampObj->MaxLod;
1315      break;
1316   case GL_TEXTURE_LOD_BIAS:
1317      *params = (GLint) sampObj->LodBias;
1318      break;
1319   case GL_TEXTURE_COMPARE_MODE:
1320      if (!ctx->Extensions.ARB_shadow)
1321         goto invalid_pname;
1322      *params = sampObj->CompareMode;
1323      break;
1324   case GL_TEXTURE_COMPARE_FUNC:
1325      if (!ctx->Extensions.ARB_shadow)
1326         goto invalid_pname;
1327      *params = sampObj->CompareFunc;
1328      break;
1329   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1330      *params = (GLint) sampObj->MaxAnisotropy;
1331      break;
1332   case GL_TEXTURE_BORDER_COLOR:
1333      params[0] = sampObj->BorderColor.i[0];
1334      params[1] = sampObj->BorderColor.i[1];
1335      params[2] = sampObj->BorderColor.i[2];
1336      params[3] = sampObj->BorderColor.i[3];
1337      break;
1338   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1339      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1340         goto invalid_pname;
1341      *params = sampObj->CubeMapSeamless;
1342      break;
1343   case GL_TEXTURE_SRGB_DECODE_EXT:
1344      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1345         goto invalid_pname;
1346      *params = (GLenum) sampObj->sRGBDecode;
1347      break;
1348   default:
1349      goto invalid_pname;
1350   }
1351   return;
1352
1353invalid_pname:
1354   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
1355               _mesa_lookup_enum_by_nr(pname));
1356}
1357
1358
1359static void GLAPIENTRY
1360_mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
1361{
1362   struct gl_sampler_object *sampObj;
1363   GET_CURRENT_CONTEXT(ctx);
1364
1365   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
1366   if (!sampObj) {
1367      _mesa_error(ctx, GL_INVALID_VALUE,
1368                  "glGetSamplerParameterIuiv(sampler %u)",
1369                  sampler);
1370      return;
1371   }
1372
1373   switch (pname) {
1374   case GL_TEXTURE_WRAP_S:
1375      *params = sampObj->WrapS;
1376      break;
1377   case GL_TEXTURE_WRAP_T:
1378      *params = sampObj->WrapT;
1379      break;
1380   case GL_TEXTURE_WRAP_R:
1381      *params = sampObj->WrapR;
1382      break;
1383   case GL_TEXTURE_MIN_FILTER:
1384      *params = sampObj->MinFilter;
1385      break;
1386   case GL_TEXTURE_MAG_FILTER:
1387      *params = sampObj->MagFilter;
1388      break;
1389   case GL_TEXTURE_MIN_LOD:
1390      *params = (GLuint) sampObj->MinLod;
1391      break;
1392   case GL_TEXTURE_MAX_LOD:
1393      *params = (GLuint) sampObj->MaxLod;
1394      break;
1395   case GL_TEXTURE_LOD_BIAS:
1396      *params = (GLuint) sampObj->LodBias;
1397      break;
1398   case GL_TEXTURE_COMPARE_MODE:
1399      if (!ctx->Extensions.ARB_shadow)
1400         goto invalid_pname;
1401      *params = sampObj->CompareMode;
1402      break;
1403   case GL_TEXTURE_COMPARE_FUNC:
1404      if (!ctx->Extensions.ARB_shadow)
1405         goto invalid_pname;
1406      *params = sampObj->CompareFunc;
1407      break;
1408   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1409      *params = (GLuint) sampObj->MaxAnisotropy;
1410      break;
1411   case GL_TEXTURE_BORDER_COLOR:
1412      params[0] = sampObj->BorderColor.ui[0];
1413      params[1] = sampObj->BorderColor.ui[1];
1414      params[2] = sampObj->BorderColor.ui[2];
1415      params[3] = sampObj->BorderColor.ui[3];
1416      break;
1417   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1418      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1419         goto invalid_pname;
1420      *params = sampObj->CubeMapSeamless;
1421      break;
1422   case GL_TEXTURE_SRGB_DECODE_EXT:
1423      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1424         goto invalid_pname;
1425      *params = (GLenum) sampObj->sRGBDecode;
1426      break;
1427   default:
1428      goto invalid_pname;
1429   }
1430   return;
1431
1432invalid_pname:
1433   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
1434               _mesa_lookup_enum_by_nr(pname));
1435}
1436
1437
1438void
1439_mesa_init_sampler_object_functions(struct dd_function_table *driver)
1440{
1441   driver->NewSamplerObject = _mesa_new_sampler_object;
1442   driver->DeleteSamplerObject = _mesa_delete_sampler_object;
1443}
1444
1445
1446void
1447_mesa_init_sampler_object_dispatch(struct _glapi_table *disp)
1448{
1449   SET_GenSamplers(disp, _mesa_GenSamplers);
1450   SET_DeleteSamplers(disp, _mesa_DeleteSamplers);
1451   SET_IsSampler(disp, _mesa_IsSampler);
1452   SET_BindSampler(disp, _mesa_BindSampler);
1453   SET_SamplerParameteri(disp, _mesa_SamplerParameteri);
1454   SET_SamplerParameterf(disp, _mesa_SamplerParameterf);
1455   SET_SamplerParameteriv(disp, _mesa_SamplerParameteriv);
1456   SET_SamplerParameterfv(disp, _mesa_SamplerParameterfv);
1457   SET_SamplerParameterIiv(disp, _mesa_SamplerParameterIiv);
1458   SET_SamplerParameterIuiv(disp, _mesa_SamplerParameterIuiv);
1459   SET_GetSamplerParameteriv(disp, _mesa_GetSamplerParameteriv);
1460   SET_GetSamplerParameterfv(disp, _mesa_GetSamplerParameterfv);
1461   SET_GetSamplerParameterIiv(disp, _mesa_GetSamplerParameterIiv);
1462   SET_GetSamplerParameterIuiv(disp, _mesa_GetSamplerParameterIuiv);
1463}
1464