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