1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 2011  VMware, Inc.  All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg/**
27848b8605Smrg * \file samplerobj.c
28848b8605Smrg * \brief Functions for the GL_ARB_sampler_objects extension.
29848b8605Smrg * \author Brian Paul
30848b8605Smrg */
31848b8605Smrg
32848b8605Smrg
33848b8605Smrg#include "main/glheader.h"
34848b8605Smrg#include "main/context.h"
35848b8605Smrg#include "main/enums.h"
36848b8605Smrg#include "main/hash.h"
37848b8605Smrg#include "main/macros.h"
38848b8605Smrg#include "main/mtypes.h"
39848b8605Smrg#include "main/samplerobj.h"
40b8e80941Smrg#include "main/texturebindless.h"
41848b8605Smrg
42848b8605Smrg
43848b8605Smrgstruct gl_sampler_object *
44848b8605Smrg_mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name)
45848b8605Smrg{
46848b8605Smrg   if (name == 0)
47848b8605Smrg      return NULL;
48848b8605Smrg   else
49848b8605Smrg      return (struct gl_sampler_object *)
50848b8605Smrg         _mesa_HashLookup(ctx->Shared->SamplerObjects, name);
51848b8605Smrg}
52848b8605Smrg
53848b8605Smrgstatic inline struct gl_sampler_object *
54848b8605Smrglookup_samplerobj_locked(struct gl_context *ctx, GLuint name)
55848b8605Smrg{
56848b8605Smrg   return (struct gl_sampler_object *)
57848b8605Smrg         _mesa_HashLookupLocked(ctx->Shared->SamplerObjects, name);
58848b8605Smrg}
59848b8605Smrg
60b8e80941Smrgstatic void
61b8e80941Smrgdelete_sampler_object(struct gl_context *ctx,
62b8e80941Smrg                      struct gl_sampler_object *sampObj)
63b8e80941Smrg{
64b8e80941Smrg   _mesa_delete_sampler_handles(ctx, sampObj);
65b8e80941Smrg   simple_mtx_destroy(&sampObj->Mutex);
66b8e80941Smrg   free(sampObj->Label);
67b8e80941Smrg   free(sampObj);
68b8e80941Smrg}
69848b8605Smrg
70848b8605Smrg/**
71848b8605Smrg * Handle reference counting.
72848b8605Smrg */
73848b8605Smrgvoid
74848b8605Smrg_mesa_reference_sampler_object_(struct gl_context *ctx,
75848b8605Smrg                                struct gl_sampler_object **ptr,
76848b8605Smrg                                struct gl_sampler_object *samp)
77848b8605Smrg{
78848b8605Smrg   assert(*ptr != samp); /* The inline wrapper should prevent no-op calls */
79848b8605Smrg
80848b8605Smrg   if (*ptr) {
81848b8605Smrg      /* Unreference the old sampler */
82848b8605Smrg      GLboolean deleteFlag = GL_FALSE;
83848b8605Smrg      struct gl_sampler_object *oldSamp = *ptr;
84848b8605Smrg
85b8e80941Smrg      simple_mtx_lock(&oldSamp->Mutex);
86b8e80941Smrg      assert(oldSamp->RefCount > 0);
87848b8605Smrg      oldSamp->RefCount--;
88848b8605Smrg      deleteFlag = (oldSamp->RefCount == 0);
89b8e80941Smrg      simple_mtx_unlock(&oldSamp->Mutex);
90848b8605Smrg
91b8e80941Smrg      if (deleteFlag)
92b8e80941Smrg         delete_sampler_object(ctx, oldSamp);
93848b8605Smrg
94848b8605Smrg      *ptr = NULL;
95848b8605Smrg   }
96b8e80941Smrg   assert(!*ptr);
97848b8605Smrg
98848b8605Smrg   if (samp) {
99848b8605Smrg      /* reference new sampler */
100b8e80941Smrg      simple_mtx_lock(&samp->Mutex);
101b8e80941Smrg      assert(samp->RefCount > 0);
102b8e80941Smrg
103b8e80941Smrg      samp->RefCount++;
104b8e80941Smrg      *ptr = samp;
105b8e80941Smrg      simple_mtx_unlock(&samp->Mutex);
106848b8605Smrg   }
107848b8605Smrg}
108848b8605Smrg
109848b8605Smrg
110848b8605Smrg/**
111848b8605Smrg * Initialize the fields of the given sampler object.
112848b8605Smrg */
113848b8605Smrgstatic void
114848b8605Smrg_mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
115848b8605Smrg{
116b8e80941Smrg   simple_mtx_init(&sampObj->Mutex, mtx_plain);
117848b8605Smrg   sampObj->Name = name;
118848b8605Smrg   sampObj->RefCount = 1;
119848b8605Smrg   sampObj->WrapS = GL_REPEAT;
120848b8605Smrg   sampObj->WrapT = GL_REPEAT;
121848b8605Smrg   sampObj->WrapR = GL_REPEAT;
122848b8605Smrg   sampObj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
123848b8605Smrg   sampObj->MagFilter = GL_LINEAR;
124848b8605Smrg   sampObj->BorderColor.f[0] = 0.0;
125848b8605Smrg   sampObj->BorderColor.f[1] = 0.0;
126848b8605Smrg   sampObj->BorderColor.f[2] = 0.0;
127848b8605Smrg   sampObj->BorderColor.f[3] = 0.0;
128848b8605Smrg   sampObj->MinLod = -1000.0F;
129848b8605Smrg   sampObj->MaxLod = 1000.0F;
130848b8605Smrg   sampObj->LodBias = 0.0F;
131848b8605Smrg   sampObj->MaxAnisotropy = 1.0F;
132848b8605Smrg   sampObj->CompareMode = GL_NONE;
133848b8605Smrg   sampObj->CompareFunc = GL_LEQUAL;
134848b8605Smrg   sampObj->sRGBDecode = GL_DECODE_EXT;
135848b8605Smrg   sampObj->CubeMapSeamless = GL_FALSE;
136b8e80941Smrg   sampObj->HandleAllocated = GL_FALSE;
137b8e80941Smrg
138b8e80941Smrg   /* GL_ARB_bindless_texture */
139b8e80941Smrg   _mesa_init_sampler_handles(sampObj);
140848b8605Smrg}
141848b8605Smrg
142848b8605Smrg/**
143848b8605Smrg * Fallback for ctx->Driver.NewSamplerObject();
144848b8605Smrg */
145848b8605Smrgstruct gl_sampler_object *
146848b8605Smrg_mesa_new_sampler_object(struct gl_context *ctx, GLuint name)
147848b8605Smrg{
148848b8605Smrg   struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object);
149848b8605Smrg   if (sampObj) {
150848b8605Smrg      _mesa_init_sampler_object(sampObj, name);
151848b8605Smrg   }
152848b8605Smrg   return sampObj;
153848b8605Smrg}
154848b8605Smrg
155848b8605Smrgstatic void
156b8e80941Smrgcreate_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers,
157b8e80941Smrg                const char *caller)
158848b8605Smrg{
159b8e80941Smrg   GLuint first;
160b8e80941Smrg   GLint i;
161848b8605Smrg
162b8e80941Smrg   if (!samplers)
163b8e80941Smrg      return;
164848b8605Smrg
165b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
166b8e80941Smrg
167b8e80941Smrg   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count);
168b8e80941Smrg
169b8e80941Smrg   /* Insert the ID and pointer to new sampler object into hash table */
170b8e80941Smrg   for (i = 0; i < count; i++) {
171b8e80941Smrg      struct gl_sampler_object *sampObj;
172b8e80941Smrg      GLuint name = first + i;
173b8e80941Smrg
174b8e80941Smrg      sampObj = ctx->Driver.NewSamplerObject(ctx, name);
175b8e80941Smrg      if (!sampObj) {
176b8e80941Smrg         _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
177b8e80941Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
178b8e80941Smrg         return;
179b8e80941Smrg      }
180b8e80941Smrg
181b8e80941Smrg      _mesa_HashInsertLocked(ctx->Shared->SamplerObjects, name, sampObj);
182b8e80941Smrg      samplers[i] = name;
183b8e80941Smrg   }
184b8e80941Smrg
185b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
186b8e80941Smrg}
187b8e80941Smrg
188b8e80941Smrgstatic void
189b8e80941Smrgcreate_samplers_err(struct gl_context *ctx, GLsizei count, GLuint *samplers,
190b8e80941Smrg                    const char *caller)
191848b8605Smrg{
192848b8605Smrg
193848b8605Smrg   if (MESA_VERBOSE & VERBOSE_API)
194b8e80941Smrg      _mesa_debug(ctx, "%s(%d)\n", caller, count);
195848b8605Smrg
196848b8605Smrg   if (count < 0) {
197b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller);
198848b8605Smrg      return;
199848b8605Smrg   }
200848b8605Smrg
201b8e80941Smrg   create_samplers(ctx, count, samplers, caller);
202b8e80941Smrg}
203848b8605Smrg
204b8e80941Smrgvoid GLAPIENTRY
205b8e80941Smrg_mesa_GenSamplers_no_error(GLsizei count, GLuint *samplers)
206b8e80941Smrg{
207b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
208b8e80941Smrg   create_samplers(ctx, count, samplers, "glGenSamplers");
209b8e80941Smrg}
210848b8605Smrg
211b8e80941Smrgvoid GLAPIENTRY
212b8e80941Smrg_mesa_GenSamplers(GLsizei count, GLuint *samplers)
213b8e80941Smrg{
214b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
215b8e80941Smrg   create_samplers_err(ctx, count, samplers, "glGenSamplers");
216848b8605Smrg}
217848b8605Smrg
218b8e80941Smrgvoid GLAPIENTRY
219b8e80941Smrg_mesa_CreateSamplers_no_error(GLsizei count, GLuint *samplers)
220b8e80941Smrg{
221b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
222b8e80941Smrg   create_samplers(ctx, count, samplers, "glCreateSamplers");
223b8e80941Smrg}
224848b8605Smrg
225848b8605Smrgvoid GLAPIENTRY
226b8e80941Smrg_mesa_CreateSamplers(GLsizei count, GLuint *samplers)
227848b8605Smrg{
228848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
229b8e80941Smrg   create_samplers_err(ctx, count, samplers, "glCreateSamplers");
230b8e80941Smrg}
231848b8605Smrg
232848b8605Smrg
233b8e80941Smrgstatic void
234b8e80941Smrgdelete_samplers(struct gl_context *ctx, GLsizei count, const GLuint *samplers)
235b8e80941Smrg{
236b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
237848b8605Smrg
238b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
239848b8605Smrg
240b8e80941Smrg   for (GLsizei i = 0; i < count; i++) {
241848b8605Smrg      if (samplers[i]) {
242848b8605Smrg         GLuint j;
243848b8605Smrg         struct gl_sampler_object *sampObj =
244b8e80941Smrg            lookup_samplerobj_locked(ctx, samplers[i]);
245848b8605Smrg
246848b8605Smrg         if (sampObj) {
247848b8605Smrg            /* If the sampler is currently bound, unbind it. */
248848b8605Smrg            for (j = 0; j < ctx->Const.MaxCombinedTextureImageUnits; j++) {
249848b8605Smrg               if (ctx->Texture.Unit[j].Sampler == sampObj) {
250b8e80941Smrg                  FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
251848b8605Smrg                  _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[j].Sampler, NULL);
252848b8605Smrg               }
253848b8605Smrg            }
254848b8605Smrg
255848b8605Smrg            /* The ID is immediately freed for re-use */
256b8e80941Smrg            _mesa_HashRemoveLocked(ctx->Shared->SamplerObjects, samplers[i]);
257848b8605Smrg            /* But the object exists until its reference count goes to zero */
258848b8605Smrg            _mesa_reference_sampler_object(ctx, &sampObj, NULL);
259848b8605Smrg         }
260848b8605Smrg      }
261848b8605Smrg   }
262848b8605Smrg
263b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
264848b8605Smrg}
265848b8605Smrg
266848b8605Smrg
267b8e80941Smrgvoid GLAPIENTRY
268b8e80941Smrg_mesa_DeleteSamplers_no_error(GLsizei count, const GLuint *samplers)
269848b8605Smrg{
270848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
271b8e80941Smrg   delete_samplers(ctx, count, samplers);
272b8e80941Smrg}
273848b8605Smrg
274848b8605Smrg
275b8e80941Smrgvoid GLAPIENTRY
276b8e80941Smrg_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
277b8e80941Smrg{
278b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
279848b8605Smrg
280b8e80941Smrg   if (count < 0) {
281b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
282b8e80941Smrg      return;
283b8e80941Smrg   }
284848b8605Smrg
285b8e80941Smrg   delete_samplers(ctx, count, samplers);
286848b8605Smrg}
287848b8605Smrg
288848b8605Smrg
289b8e80941SmrgGLboolean GLAPIENTRY
290b8e80941Smrg_mesa_IsSampler(GLuint sampler)
291848b8605Smrg{
292848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
293848b8605Smrg
294b8e80941Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
295b8e80941Smrg
296b8e80941Smrg   return _mesa_lookup_samplerobj(ctx, sampler) != NULL;
297b8e80941Smrg}
298b8e80941Smrg
299b8e80941Smrgvoid
300b8e80941Smrg_mesa_bind_sampler(struct gl_context *ctx, GLuint unit,
301b8e80941Smrg                   struct gl_sampler_object *sampObj)
302b8e80941Smrg{
303b8e80941Smrg   if (ctx->Texture.Unit[unit].Sampler != sampObj) {
304b8e80941Smrg      FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
305848b8605Smrg   }
306848b8605Smrg
307b8e80941Smrg   _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler,
308b8e80941Smrg                                  sampObj);
309b8e80941Smrg}
310b8e80941Smrg
311b8e80941Smrgstatic ALWAYS_INLINE void
312b8e80941Smrgbind_sampler(struct gl_context *ctx, GLuint unit, GLuint sampler, bool no_error)
313b8e80941Smrg{
314b8e80941Smrg   struct gl_sampler_object *sampObj;
315b8e80941Smrg
316848b8605Smrg   if (sampler == 0) {
317848b8605Smrg      /* Use the default sampler object, the one contained in the texture
318848b8605Smrg       * object.
319848b8605Smrg       */
320848b8605Smrg      sampObj = NULL;
321b8e80941Smrg   } else {
322848b8605Smrg      /* user-defined sampler object */
323848b8605Smrg      sampObj = _mesa_lookup_samplerobj(ctx, sampler);
324b8e80941Smrg      if (!no_error && !sampObj) {
325848b8605Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)");
326848b8605Smrg         return;
327848b8605Smrg      }
328848b8605Smrg   }
329848b8605Smrg
330848b8605Smrg   /* bind new sampler */
331b8e80941Smrg   _mesa_bind_sampler(ctx, unit, sampObj);
332848b8605Smrg}
333848b8605Smrg
334b8e80941Smrgvoid GLAPIENTRY
335b8e80941Smrg_mesa_BindSampler_no_error(GLuint unit, GLuint sampler)
336b8e80941Smrg{
337b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
338b8e80941Smrg   bind_sampler(ctx, unit, sampler, true);
339b8e80941Smrg}
340848b8605Smrg
341848b8605Smrgvoid GLAPIENTRY
342b8e80941Smrg_mesa_BindSampler(GLuint unit, GLuint sampler)
343848b8605Smrg{
344848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
345848b8605Smrg
346b8e80941Smrg   if (unit >= ctx->Const.MaxCombinedTextureImageUnits) {
347b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
348848b8605Smrg      return;
349848b8605Smrg   }
350848b8605Smrg
351b8e80941Smrg   bind_sampler(ctx, unit, sampler, false);
352b8e80941Smrg}
353b8e80941Smrg
354b8e80941Smrg
355b8e80941Smrgstatic ALWAYS_INLINE void
356b8e80941Smrgbind_samplers(struct gl_context *ctx, GLuint first, GLsizei count,
357b8e80941Smrg              const GLuint *samplers, bool no_error)
358b8e80941Smrg{
359b8e80941Smrg   GLsizei i;
360b8e80941Smrg
361848b8605Smrg   FLUSH_VERTICES(ctx, 0);
362848b8605Smrg
363848b8605Smrg   if (samplers) {
364848b8605Smrg      /* Note that the error semantics for multi-bind commands differ from
365848b8605Smrg       * those of other GL commands.
366848b8605Smrg       *
367848b8605Smrg       * The Issues section in the ARB_multi_bind spec says:
368848b8605Smrg       *
369848b8605Smrg       *    "(11) Typically, OpenGL specifies that if an error is generated by
370848b8605Smrg       *          a command, that command has no effect.  This is somewhat
371848b8605Smrg       *          unfortunate for multi-bind commands, because it would require
372848b8605Smrg       *          a first pass to scan the entire list of bound objects for
373848b8605Smrg       *          errors and then a second pass to actually perform the
374848b8605Smrg       *          bindings.  Should we have different error semantics?
375848b8605Smrg       *
376848b8605Smrg       *       RESOLVED:  Yes.  In this specification, when the parameters for
377848b8605Smrg       *       one of the <count> binding points are invalid, that binding
378848b8605Smrg       *       point is not updated and an error will be generated.  However,
379848b8605Smrg       *       other binding points in the same command will be updated if
380848b8605Smrg       *       their parameters are valid and no other error occurs."
381848b8605Smrg       */
382848b8605Smrg
383b8e80941Smrg      _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
384848b8605Smrg
385848b8605Smrg      for (i = 0; i < count; i++) {
386848b8605Smrg         const GLuint unit = first + i;
387848b8605Smrg         struct gl_sampler_object * const currentSampler =
388848b8605Smrg             ctx->Texture.Unit[unit].Sampler;
389848b8605Smrg         struct gl_sampler_object *sampObj;
390848b8605Smrg
391848b8605Smrg         if (samplers[i] != 0) {
392848b8605Smrg            if (currentSampler && currentSampler->Name == samplers[i])
393848b8605Smrg               sampObj = currentSampler;
394848b8605Smrg            else
395848b8605Smrg               sampObj = lookup_samplerobj_locked(ctx, samplers[i]);
396848b8605Smrg
397848b8605Smrg            /* The ARB_multi_bind spec says:
398848b8605Smrg             *
399848b8605Smrg             *    "An INVALID_OPERATION error is generated if any value
400848b8605Smrg             *     in <samplers> is not zero or the name of an existing
401848b8605Smrg             *     sampler object (per binding)."
402848b8605Smrg             */
403b8e80941Smrg            if (!no_error && !sampObj) {
404848b8605Smrg               _mesa_error(ctx, GL_INVALID_OPERATION,
405848b8605Smrg                           "glBindSamplers(samplers[%d]=%u is not zero or "
406848b8605Smrg                           "the name of an existing sampler object)",
407848b8605Smrg                           i, samplers[i]);
408848b8605Smrg               continue;
409848b8605Smrg            }
410848b8605Smrg         } else {
411848b8605Smrg            sampObj = NULL;
412848b8605Smrg         }
413848b8605Smrg
414848b8605Smrg         /* Bind the new sampler */
415848b8605Smrg         if (sampObj != currentSampler) {
416848b8605Smrg            _mesa_reference_sampler_object(ctx,
417848b8605Smrg                                           &ctx->Texture.Unit[unit].Sampler,
418848b8605Smrg                                           sampObj);
419b8e80941Smrg            ctx->NewState |= _NEW_TEXTURE_OBJECT;
420848b8605Smrg         }
421848b8605Smrg      }
422848b8605Smrg
423b8e80941Smrg      _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
424848b8605Smrg   } else {
425848b8605Smrg      /* Unbind all samplers in the range <first> through <first>+<count>-1 */
426848b8605Smrg      for (i = 0; i < count; i++) {
427848b8605Smrg         const GLuint unit = first + i;
428848b8605Smrg
429848b8605Smrg         if (ctx->Texture.Unit[unit].Sampler) {
430848b8605Smrg            _mesa_reference_sampler_object(ctx,
431848b8605Smrg                                           &ctx->Texture.Unit[unit].Sampler,
432848b8605Smrg                                           NULL);
433b8e80941Smrg            ctx->NewState |= _NEW_TEXTURE_OBJECT;
434848b8605Smrg         }
435848b8605Smrg      }
436848b8605Smrg   }
437848b8605Smrg}
438848b8605Smrg
439848b8605Smrg
440b8e80941Smrgvoid GLAPIENTRY
441b8e80941Smrg_mesa_BindSamplers_no_error(GLuint first, GLsizei count, const GLuint *samplers)
442b8e80941Smrg{
443b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
444b8e80941Smrg   bind_samplers(ctx, first, count, samplers, true);
445b8e80941Smrg}
446b8e80941Smrg
447b8e80941Smrg
448b8e80941Smrgvoid GLAPIENTRY
449b8e80941Smrg_mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
450b8e80941Smrg{
451b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
452b8e80941Smrg
453b8e80941Smrg   /* The ARB_multi_bind spec says:
454b8e80941Smrg    *
455b8e80941Smrg    *   "An INVALID_OPERATION error is generated if <first> + <count> is
456b8e80941Smrg    *    greater than the number of texture image units supported by
457b8e80941Smrg    *    the implementation."
458b8e80941Smrg    */
459b8e80941Smrg   if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
460b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
461b8e80941Smrg                  "glBindSamplers(first=%u + count=%d > the value of "
462b8e80941Smrg                  "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
463b8e80941Smrg                  first, count, ctx->Const.MaxCombinedTextureImageUnits);
464b8e80941Smrg      return;
465b8e80941Smrg   }
466b8e80941Smrg
467b8e80941Smrg   bind_samplers(ctx, first, count, samplers, false);
468b8e80941Smrg}
469b8e80941Smrg
470b8e80941Smrg
471848b8605Smrg/**
472848b8605Smrg * Check if a coordinate wrap mode is legal.
473848b8605Smrg * \return GL_TRUE if legal, GL_FALSE otherwise
474848b8605Smrg */
475848b8605Smrgstatic GLboolean
476848b8605Smrgvalidate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap)
477848b8605Smrg{
478848b8605Smrg   const struct gl_extensions * const e = &ctx->Extensions;
479848b8605Smrg
480848b8605Smrg   switch (wrap) {
481848b8605Smrg   case GL_CLAMP:
482848b8605Smrg   case GL_CLAMP_TO_EDGE:
483848b8605Smrg   case GL_REPEAT:
484848b8605Smrg   case GL_MIRRORED_REPEAT:
485848b8605Smrg      return GL_TRUE;
486848b8605Smrg   case GL_CLAMP_TO_BORDER:
487848b8605Smrg      return e->ARB_texture_border_clamp;
488848b8605Smrg   case GL_MIRROR_CLAMP_EXT:
489848b8605Smrg      return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
490848b8605Smrg   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
491848b8605Smrg      return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp || e->ARB_texture_mirror_clamp_to_edge;
492848b8605Smrg   case GL_MIRROR_CLAMP_TO_BORDER_EXT:
493848b8605Smrg      return e->EXT_texture_mirror_clamp;
494848b8605Smrg   default:
495848b8605Smrg      return GL_FALSE;
496848b8605Smrg   }
497848b8605Smrg}
498848b8605Smrg
499848b8605Smrg
500848b8605Smrg/**
501848b8605Smrg * This is called just prior to changing any sampler object state.
502848b8605Smrg */
503848b8605Smrgstatic inline void
504848b8605Smrgflush(struct gl_context *ctx)
505848b8605Smrg{
506b8e80941Smrg   FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
507848b8605Smrg}
508848b8605Smrg
509b8e80941Smrgvoid
510b8e80941Smrg_mesa_set_sampler_wrap(struct gl_context *ctx, struct gl_sampler_object *samp,
511b8e80941Smrg                       GLenum s, GLenum t, GLenum r)
512b8e80941Smrg{
513b8e80941Smrg   assert(validate_texture_wrap_mode(ctx, s));
514b8e80941Smrg   assert(validate_texture_wrap_mode(ctx, t));
515b8e80941Smrg   assert(validate_texture_wrap_mode(ctx, r));
516b8e80941Smrg
517b8e80941Smrg   if (samp->WrapS == s && samp->WrapT == t && samp->WrapR == r)
518b8e80941Smrg      return;
519b8e80941Smrg
520b8e80941Smrg   flush(ctx);
521b8e80941Smrg   samp->WrapS = s;
522b8e80941Smrg   samp->WrapT = t;
523b8e80941Smrg   samp->WrapR = r;
524b8e80941Smrg}
525848b8605Smrg
526848b8605Smrg#define INVALID_PARAM 0x100
527848b8605Smrg#define INVALID_PNAME 0x101
528848b8605Smrg#define INVALID_VALUE 0x102
529848b8605Smrg
530848b8605Smrgstatic GLuint
531848b8605Smrgset_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
532848b8605Smrg                   GLint param)
533848b8605Smrg{
534848b8605Smrg   if (samp->WrapS == param)
535848b8605Smrg      return GL_FALSE;
536848b8605Smrg   if (validate_texture_wrap_mode(ctx, param)) {
537848b8605Smrg      flush(ctx);
538848b8605Smrg      samp->WrapS = param;
539848b8605Smrg      return GL_TRUE;
540848b8605Smrg   }
541848b8605Smrg   return INVALID_PARAM;
542848b8605Smrg}
543848b8605Smrg
544848b8605Smrg
545848b8605Smrgstatic GLuint
546848b8605Smrgset_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
547848b8605Smrg                   GLint param)
548848b8605Smrg{
549848b8605Smrg   if (samp->WrapT == param)
550848b8605Smrg      return GL_FALSE;
551848b8605Smrg   if (validate_texture_wrap_mode(ctx, param)) {
552848b8605Smrg      flush(ctx);
553848b8605Smrg      samp->WrapT = param;
554848b8605Smrg      return GL_TRUE;
555848b8605Smrg   }
556848b8605Smrg   return INVALID_PARAM;
557848b8605Smrg}
558848b8605Smrg
559848b8605Smrg
560848b8605Smrgstatic GLuint
561848b8605Smrgset_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
562848b8605Smrg                   GLint param)
563848b8605Smrg{
564848b8605Smrg   if (samp->WrapR == param)
565848b8605Smrg      return GL_FALSE;
566848b8605Smrg   if (validate_texture_wrap_mode(ctx, param)) {
567848b8605Smrg      flush(ctx);
568848b8605Smrg      samp->WrapR = param;
569848b8605Smrg      return GL_TRUE;
570848b8605Smrg   }
571848b8605Smrg   return INVALID_PARAM;
572848b8605Smrg}
573848b8605Smrg
574b8e80941Smrgvoid
575b8e80941Smrg_mesa_set_sampler_filters(struct gl_context *ctx,
576b8e80941Smrg                          struct gl_sampler_object *samp,
577b8e80941Smrg                          GLenum min_filter, GLenum mag_filter)
578b8e80941Smrg{
579b8e80941Smrg   assert(min_filter == GL_NEAREST ||
580b8e80941Smrg          min_filter == GL_LINEAR ||
581b8e80941Smrg          min_filter == GL_NEAREST_MIPMAP_NEAREST ||
582b8e80941Smrg          min_filter == GL_LINEAR_MIPMAP_NEAREST ||
583b8e80941Smrg          min_filter == GL_NEAREST_MIPMAP_LINEAR ||
584b8e80941Smrg          min_filter == GL_LINEAR_MIPMAP_LINEAR);
585b8e80941Smrg   assert(mag_filter == GL_NEAREST ||
586b8e80941Smrg          mag_filter == GL_LINEAR);
587b8e80941Smrg
588b8e80941Smrg   if (samp->MinFilter == min_filter && samp->MagFilter == mag_filter)
589b8e80941Smrg      return;
590b8e80941Smrg
591b8e80941Smrg   flush(ctx);
592b8e80941Smrg   samp->MinFilter = min_filter;
593b8e80941Smrg   samp->MagFilter = mag_filter;
594b8e80941Smrg}
595848b8605Smrg
596848b8605Smrgstatic GLuint
597848b8605Smrgset_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
598848b8605Smrg                       GLint param)
599848b8605Smrg{
600848b8605Smrg   if (samp->MinFilter == param)
601848b8605Smrg      return GL_FALSE;
602848b8605Smrg
603848b8605Smrg   switch (param) {
604848b8605Smrg   case GL_NEAREST:
605848b8605Smrg   case GL_LINEAR:
606848b8605Smrg   case GL_NEAREST_MIPMAP_NEAREST:
607848b8605Smrg   case GL_LINEAR_MIPMAP_NEAREST:
608848b8605Smrg   case GL_NEAREST_MIPMAP_LINEAR:
609848b8605Smrg   case GL_LINEAR_MIPMAP_LINEAR:
610848b8605Smrg      flush(ctx);
611848b8605Smrg      samp->MinFilter = param;
612848b8605Smrg      return GL_TRUE;
613848b8605Smrg   default:
614848b8605Smrg      return INVALID_PARAM;
615848b8605Smrg   }
616848b8605Smrg}
617848b8605Smrg
618848b8605Smrg
619848b8605Smrgstatic GLuint
620848b8605Smrgset_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
621848b8605Smrg                       GLint param)
622848b8605Smrg{
623848b8605Smrg   if (samp->MagFilter == param)
624848b8605Smrg      return GL_FALSE;
625848b8605Smrg
626848b8605Smrg   switch (param) {
627848b8605Smrg   case GL_NEAREST:
628848b8605Smrg   case GL_LINEAR:
629848b8605Smrg      flush(ctx);
630848b8605Smrg      samp->MagFilter = param;
631848b8605Smrg      return GL_TRUE;
632848b8605Smrg   default:
633848b8605Smrg      return INVALID_PARAM;
634848b8605Smrg   }
635848b8605Smrg}
636848b8605Smrg
637848b8605Smrg
638848b8605Smrgstatic GLuint
639848b8605Smrgset_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
640848b8605Smrg                     GLfloat param)
641848b8605Smrg{
642848b8605Smrg   if (samp->LodBias == param)
643848b8605Smrg      return GL_FALSE;
644848b8605Smrg
645848b8605Smrg   flush(ctx);
646848b8605Smrg   samp->LodBias = param;
647848b8605Smrg   return GL_TRUE;
648848b8605Smrg}
649848b8605Smrg
650848b8605Smrg
651848b8605Smrgstatic GLuint
652848b8605Smrgset_sampler_border_colorf(struct gl_context *ctx,
653848b8605Smrg                          struct gl_sampler_object *samp,
654848b8605Smrg                          const GLfloat params[4])
655848b8605Smrg{
656848b8605Smrg   flush(ctx);
657848b8605Smrg   samp->BorderColor.f[RCOMP] = params[0];
658848b8605Smrg   samp->BorderColor.f[GCOMP] = params[1];
659848b8605Smrg   samp->BorderColor.f[BCOMP] = params[2];
660848b8605Smrg   samp->BorderColor.f[ACOMP] = params[3];
661848b8605Smrg   return GL_TRUE;
662848b8605Smrg}
663848b8605Smrg
664848b8605Smrg
665848b8605Smrgstatic GLuint
666848b8605Smrgset_sampler_border_colori(struct gl_context *ctx,
667848b8605Smrg                          struct gl_sampler_object *samp,
668848b8605Smrg                          const GLint params[4])
669848b8605Smrg{
670848b8605Smrg   flush(ctx);
671848b8605Smrg   samp->BorderColor.i[RCOMP] = params[0];
672848b8605Smrg   samp->BorderColor.i[GCOMP] = params[1];
673848b8605Smrg   samp->BorderColor.i[BCOMP] = params[2];
674848b8605Smrg   samp->BorderColor.i[ACOMP] = params[3];
675848b8605Smrg   return GL_TRUE;
676848b8605Smrg}
677848b8605Smrg
678848b8605Smrg
679848b8605Smrgstatic GLuint
680848b8605Smrgset_sampler_border_colorui(struct gl_context *ctx,
681848b8605Smrg                           struct gl_sampler_object *samp,
682848b8605Smrg                           const GLuint params[4])
683848b8605Smrg{
684848b8605Smrg   flush(ctx);
685848b8605Smrg   samp->BorderColor.ui[RCOMP] = params[0];
686848b8605Smrg   samp->BorderColor.ui[GCOMP] = params[1];
687848b8605Smrg   samp->BorderColor.ui[BCOMP] = params[2];
688848b8605Smrg   samp->BorderColor.ui[ACOMP] = params[3];
689848b8605Smrg   return GL_TRUE;
690848b8605Smrg}
691848b8605Smrg
692848b8605Smrg
693848b8605Smrgstatic GLuint
694848b8605Smrgset_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
695848b8605Smrg                    GLfloat param)
696848b8605Smrg{
697848b8605Smrg   if (samp->MinLod == param)
698848b8605Smrg      return GL_FALSE;
699848b8605Smrg
700848b8605Smrg   flush(ctx);
701848b8605Smrg   samp->MinLod = param;
702848b8605Smrg   return GL_TRUE;
703848b8605Smrg}
704848b8605Smrg
705848b8605Smrg
706848b8605Smrgstatic GLuint
707848b8605Smrgset_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
708848b8605Smrg                    GLfloat param)
709848b8605Smrg{
710848b8605Smrg   if (samp->MaxLod == param)
711848b8605Smrg      return GL_FALSE;
712848b8605Smrg
713848b8605Smrg   flush(ctx);
714848b8605Smrg   samp->MaxLod = param;
715848b8605Smrg   return GL_TRUE;
716848b8605Smrg}
717848b8605Smrg
718848b8605Smrg
719848b8605Smrgstatic GLuint
720848b8605Smrgset_sampler_compare_mode(struct gl_context *ctx,
721848b8605Smrg                         struct gl_sampler_object *samp, GLint param)
722848b8605Smrg{
723b8e80941Smrg    /* If GL_ARB_shadow is not supported, don't report an error.  The
724b8e80941Smrg     * sampler object extension spec isn't clear on this extension interaction.
725b8e80941Smrg     * Silences errors with Wine on older GPUs such as R200.
726b8e80941Smrg     */
727848b8605Smrg   if (!ctx->Extensions.ARB_shadow)
728b8e80941Smrg      return GL_FALSE;
729848b8605Smrg
730848b8605Smrg   if (samp->CompareMode == param)
731848b8605Smrg      return GL_FALSE;
732848b8605Smrg
733848b8605Smrg   if (param == GL_NONE ||
734848b8605Smrg       param == GL_COMPARE_R_TO_TEXTURE_ARB) {
735848b8605Smrg      flush(ctx);
736848b8605Smrg      samp->CompareMode = param;
737848b8605Smrg      return GL_TRUE;
738848b8605Smrg   }
739848b8605Smrg
740848b8605Smrg   return INVALID_PARAM;
741848b8605Smrg}
742848b8605Smrg
743848b8605Smrg
744848b8605Smrgstatic GLuint
745848b8605Smrgset_sampler_compare_func(struct gl_context *ctx,
746848b8605Smrg                         struct gl_sampler_object *samp, GLint param)
747848b8605Smrg{
748b8e80941Smrg    /* If GL_ARB_shadow is not supported, don't report an error.  The
749b8e80941Smrg     * sampler object extension spec isn't clear on this extension interaction.
750b8e80941Smrg     * Silences errors with Wine on older GPUs such as R200.
751b8e80941Smrg     */
752848b8605Smrg   if (!ctx->Extensions.ARB_shadow)
753b8e80941Smrg      return GL_FALSE;
754848b8605Smrg
755848b8605Smrg   if (samp->CompareFunc == param)
756848b8605Smrg      return GL_FALSE;
757848b8605Smrg
758848b8605Smrg   switch (param) {
759848b8605Smrg   case GL_LEQUAL:
760848b8605Smrg   case GL_GEQUAL:
761848b8605Smrg   case GL_EQUAL:
762848b8605Smrg   case GL_NOTEQUAL:
763848b8605Smrg   case GL_LESS:
764848b8605Smrg   case GL_GREATER:
765848b8605Smrg   case GL_ALWAYS:
766848b8605Smrg   case GL_NEVER:
767848b8605Smrg      flush(ctx);
768848b8605Smrg      samp->CompareFunc = param;
769848b8605Smrg      return GL_TRUE;
770848b8605Smrg   default:
771848b8605Smrg      return INVALID_PARAM;
772848b8605Smrg   }
773848b8605Smrg}
774848b8605Smrg
775848b8605Smrg
776848b8605Smrgstatic GLuint
777848b8605Smrgset_sampler_max_anisotropy(struct gl_context *ctx,
778848b8605Smrg                           struct gl_sampler_object *samp, GLfloat param)
779848b8605Smrg{
780848b8605Smrg   if (!ctx->Extensions.EXT_texture_filter_anisotropic)
781848b8605Smrg      return INVALID_PNAME;
782848b8605Smrg
783848b8605Smrg   if (samp->MaxAnisotropy == param)
784848b8605Smrg      return GL_FALSE;
785848b8605Smrg
786b8e80941Smrg   if (param < 1.0F)
787848b8605Smrg      return INVALID_VALUE;
788848b8605Smrg
789848b8605Smrg   flush(ctx);
790848b8605Smrg   /* clamp to max, that's what NVIDIA does */
791848b8605Smrg   samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
792848b8605Smrg   return GL_TRUE;
793848b8605Smrg}
794848b8605Smrg
795848b8605Smrg
796848b8605Smrgstatic GLuint
797848b8605Smrgset_sampler_cube_map_seamless(struct gl_context *ctx,
798848b8605Smrg                              struct gl_sampler_object *samp, GLboolean param)
799848b8605Smrg{
800848b8605Smrg   if (!_mesa_is_desktop_gl(ctx)
801848b8605Smrg       || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
802848b8605Smrg      return INVALID_PNAME;
803848b8605Smrg
804848b8605Smrg   if (samp->CubeMapSeamless == param)
805848b8605Smrg      return GL_FALSE;
806848b8605Smrg
807848b8605Smrg   if (param != GL_TRUE && param != GL_FALSE)
808848b8605Smrg      return INVALID_VALUE;
809848b8605Smrg
810848b8605Smrg   flush(ctx);
811848b8605Smrg   samp->CubeMapSeamless = param;
812848b8605Smrg   return GL_TRUE;
813848b8605Smrg}
814848b8605Smrg
815b8e80941Smrgvoid
816b8e80941Smrg_mesa_set_sampler_srgb_decode(struct gl_context *ctx,
817b8e80941Smrg                              struct gl_sampler_object *samp, GLenum param)
818b8e80941Smrg{
819b8e80941Smrg   assert(param == GL_DECODE_EXT || param == GL_SKIP_DECODE_EXT);
820b8e80941Smrg
821b8e80941Smrg   flush(ctx);
822b8e80941Smrg   samp->sRGBDecode = param;
823b8e80941Smrg}
824b8e80941Smrg
825848b8605Smrgstatic GLuint
826848b8605Smrgset_sampler_srgb_decode(struct gl_context *ctx,
827848b8605Smrg                              struct gl_sampler_object *samp, GLenum param)
828848b8605Smrg{
829848b8605Smrg   if (!ctx->Extensions.EXT_texture_sRGB_decode)
830848b8605Smrg      return INVALID_PNAME;
831848b8605Smrg
832848b8605Smrg   if (samp->sRGBDecode == param)
833848b8605Smrg      return GL_FALSE;
834848b8605Smrg
835b8e80941Smrg   /* The EXT_texture_sRGB_decode spec says:
836b8e80941Smrg    *
837b8e80941Smrg    *    "INVALID_ENUM is generated if the <pname> parameter of
838b8e80941Smrg    *     TexParameter[i,f,Ii,Iui][v][EXT],
839b8e80941Smrg    *     MultiTexParameter[i,f,Ii,Iui][v]EXT,
840b8e80941Smrg    *     TextureParameter[i,f,Ii,Iui][v]EXT, SamplerParameter[i,f,Ii,Iui][v]
841b8e80941Smrg    *     is TEXTURE_SRGB_DECODE_EXT when the <param> parameter is not one of
842b8e80941Smrg    *     DECODE_EXT or SKIP_DECODE_EXT.
843b8e80941Smrg    *
844b8e80941Smrg    * Returning INVALID_PARAM makes that happen.
845b8e80941Smrg    */
846848b8605Smrg   if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
847b8e80941Smrg      return INVALID_PARAM;
848848b8605Smrg
849848b8605Smrg   flush(ctx);
850848b8605Smrg   samp->sRGBDecode = param;
851848b8605Smrg   return GL_TRUE;
852848b8605Smrg}
853848b8605Smrg
854b8e80941Smrgstatic struct gl_sampler_object *
855b8e80941Smrgsampler_parameter_error_check(struct gl_context *ctx, GLuint sampler,
856b8e80941Smrg                              bool get, const char *name)
857b8e80941Smrg{
858b8e80941Smrg   struct gl_sampler_object *sampObj;
859b8e80941Smrg
860b8e80941Smrg   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
861b8e80941Smrg   if (!sampObj) {
862b8e80941Smrg      /* OpenGL 4.5 spec, section "8.2 Sampler Objects", page 176 of the PDF
863b8e80941Smrg       * states:
864b8e80941Smrg       *
865b8e80941Smrg       *    "An INVALID_OPERATION error is generated if sampler is not the name
866b8e80941Smrg       *    of a sampler object previously returned from a call to
867b8e80941Smrg       *    GenSamplers."
868b8e80941Smrg       */
869b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid sampler)", name);
870b8e80941Smrg      return NULL;
871b8e80941Smrg   }
872b8e80941Smrg
873b8e80941Smrg   if (!get && sampObj->HandleAllocated) {
874b8e80941Smrg      /* The ARB_bindless_texture spec says:
875b8e80941Smrg       *
876b8e80941Smrg       * "The error INVALID_OPERATION is generated by SamplerParameter* if
877b8e80941Smrg       *  <sampler> identifies a sampler object referenced by one or more
878b8e80941Smrg       *  texture handles."
879b8e80941Smrg       */
880b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable sampler)", name);
881b8e80941Smrg      return NULL;
882b8e80941Smrg   }
883b8e80941Smrg
884b8e80941Smrg   return sampObj;
885b8e80941Smrg}
886b8e80941Smrg
887848b8605Smrgvoid GLAPIENTRY
888848b8605Smrg_mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
889848b8605Smrg{
890848b8605Smrg   struct gl_sampler_object *sampObj;
891848b8605Smrg   GLuint res;
892848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
893848b8605Smrg
894b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, false,
895b8e80941Smrg                                           "glSamplerParameteri");
896b8e80941Smrg   if (!sampObj)
897848b8605Smrg      return;
898848b8605Smrg
899848b8605Smrg   switch (pname) {
900848b8605Smrg   case GL_TEXTURE_WRAP_S:
901848b8605Smrg      res = set_sampler_wrap_s(ctx, sampObj, param);
902848b8605Smrg      break;
903848b8605Smrg   case GL_TEXTURE_WRAP_T:
904848b8605Smrg      res = set_sampler_wrap_t(ctx, sampObj, param);
905848b8605Smrg      break;
906848b8605Smrg   case GL_TEXTURE_WRAP_R:
907848b8605Smrg      res = set_sampler_wrap_r(ctx, sampObj, param);
908848b8605Smrg      break;
909848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
910848b8605Smrg      res = set_sampler_min_filter(ctx, sampObj, param);
911848b8605Smrg      break;
912848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
913848b8605Smrg      res = set_sampler_mag_filter(ctx, sampObj, param);
914848b8605Smrg      break;
915848b8605Smrg   case GL_TEXTURE_MIN_LOD:
916848b8605Smrg      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
917848b8605Smrg      break;
918848b8605Smrg   case GL_TEXTURE_MAX_LOD:
919848b8605Smrg      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
920848b8605Smrg      break;
921848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
922848b8605Smrg      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
923848b8605Smrg      break;
924848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
925848b8605Smrg      res = set_sampler_compare_mode(ctx, sampObj, param);
926848b8605Smrg      break;
927848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
928848b8605Smrg      res = set_sampler_compare_func(ctx, sampObj, param);
929848b8605Smrg      break;
930848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
931848b8605Smrg      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
932848b8605Smrg      break;
933848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
934848b8605Smrg      res = set_sampler_cube_map_seamless(ctx, sampObj, param);
935848b8605Smrg      break;
936848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
937848b8605Smrg      res = set_sampler_srgb_decode(ctx, sampObj, param);
938848b8605Smrg      break;
939848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
940848b8605Smrg      /* fall-through */
941848b8605Smrg   default:
942848b8605Smrg      res = INVALID_PNAME;
943848b8605Smrg   }
944848b8605Smrg
945848b8605Smrg   switch (res) {
946848b8605Smrg   case GL_FALSE:
947848b8605Smrg      /* no change */
948848b8605Smrg      break;
949848b8605Smrg   case GL_TRUE:
950848b8605Smrg      /* state change - we do nothing special at this time */
951848b8605Smrg      break;
952848b8605Smrg   case INVALID_PNAME:
953848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
954b8e80941Smrg                  _mesa_enum_to_string(pname));
955848b8605Smrg      break;
956848b8605Smrg   case INVALID_PARAM:
957848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
958848b8605Smrg                  param);
959848b8605Smrg      break;
960848b8605Smrg   case INVALID_VALUE:
961848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
962848b8605Smrg                  param);
963848b8605Smrg      break;
964848b8605Smrg   default:
965848b8605Smrg      ;
966848b8605Smrg   }
967848b8605Smrg}
968848b8605Smrg
969848b8605Smrg
970848b8605Smrgvoid GLAPIENTRY
971848b8605Smrg_mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
972848b8605Smrg{
973848b8605Smrg   struct gl_sampler_object *sampObj;
974848b8605Smrg   GLuint res;
975848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
976848b8605Smrg
977b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, false,
978b8e80941Smrg                                           "glSamplerParameterf");
979b8e80941Smrg   if (!sampObj)
980848b8605Smrg      return;
981848b8605Smrg
982848b8605Smrg   switch (pname) {
983848b8605Smrg   case GL_TEXTURE_WRAP_S:
984848b8605Smrg      res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
985848b8605Smrg      break;
986848b8605Smrg   case GL_TEXTURE_WRAP_T:
987848b8605Smrg      res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
988848b8605Smrg      break;
989848b8605Smrg   case GL_TEXTURE_WRAP_R:
990848b8605Smrg      res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
991848b8605Smrg      break;
992848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
993848b8605Smrg      res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
994848b8605Smrg      break;
995848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
996848b8605Smrg      res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
997848b8605Smrg      break;
998848b8605Smrg   case GL_TEXTURE_MIN_LOD:
999848b8605Smrg      res = set_sampler_min_lod(ctx, sampObj, param);
1000848b8605Smrg      break;
1001848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1002848b8605Smrg      res = set_sampler_max_lod(ctx, sampObj, param);
1003848b8605Smrg      break;
1004848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1005848b8605Smrg      res = set_sampler_lod_bias(ctx, sampObj, param);
1006848b8605Smrg      break;
1007848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1008848b8605Smrg      res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
1009848b8605Smrg      break;
1010848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1011848b8605Smrg      res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
1012848b8605Smrg      break;
1013848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1014848b8605Smrg      res = set_sampler_max_anisotropy(ctx, sampObj, param);
1015848b8605Smrg      break;
1016848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1017848b8605Smrg      res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) param);
1018848b8605Smrg      break;
1019848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1020848b8605Smrg      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) param);
1021848b8605Smrg      break;
1022848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1023848b8605Smrg      /* fall-through */
1024848b8605Smrg   default:
1025848b8605Smrg      res = INVALID_PNAME;
1026848b8605Smrg   }
1027848b8605Smrg
1028848b8605Smrg   switch (res) {
1029848b8605Smrg   case GL_FALSE:
1030848b8605Smrg      /* no change */
1031848b8605Smrg      break;
1032848b8605Smrg   case GL_TRUE:
1033848b8605Smrg      /* state change - we do nothing special at this time */
1034848b8605Smrg      break;
1035848b8605Smrg   case INVALID_PNAME:
1036848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
1037b8e80941Smrg                  _mesa_enum_to_string(pname));
1038848b8605Smrg      break;
1039848b8605Smrg   case INVALID_PARAM:
1040848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
1041848b8605Smrg                  param);
1042848b8605Smrg      break;
1043848b8605Smrg   case INVALID_VALUE:
1044848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
1045848b8605Smrg                  param);
1046848b8605Smrg      break;
1047848b8605Smrg   default:
1048848b8605Smrg      ;
1049848b8605Smrg   }
1050848b8605Smrg}
1051848b8605Smrg
1052848b8605Smrgvoid GLAPIENTRY
1053848b8605Smrg_mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
1054848b8605Smrg{
1055848b8605Smrg   struct gl_sampler_object *sampObj;
1056848b8605Smrg   GLuint res;
1057848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1058848b8605Smrg
1059b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, false,
1060b8e80941Smrg                                           "glSamplerParameteriv");
1061b8e80941Smrg   if (!sampObj)
1062848b8605Smrg      return;
1063848b8605Smrg
1064848b8605Smrg   switch (pname) {
1065848b8605Smrg   case GL_TEXTURE_WRAP_S:
1066848b8605Smrg      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1067848b8605Smrg      break;
1068848b8605Smrg   case GL_TEXTURE_WRAP_T:
1069848b8605Smrg      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1070848b8605Smrg      break;
1071848b8605Smrg   case GL_TEXTURE_WRAP_R:
1072848b8605Smrg      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1073848b8605Smrg      break;
1074848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
1075848b8605Smrg      res = set_sampler_min_filter(ctx, sampObj, params[0]);
1076848b8605Smrg      break;
1077848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
1078848b8605Smrg      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1079848b8605Smrg      break;
1080848b8605Smrg   case GL_TEXTURE_MIN_LOD:
1081848b8605Smrg      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1082848b8605Smrg      break;
1083848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1084848b8605Smrg      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1085848b8605Smrg      break;
1086848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1087848b8605Smrg      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1088848b8605Smrg      break;
1089848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1090848b8605Smrg      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1091848b8605Smrg      break;
1092848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1093848b8605Smrg      res = set_sampler_compare_func(ctx, sampObj, params[0]);
1094848b8605Smrg      break;
1095848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1096848b8605Smrg      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1097848b8605Smrg      break;
1098848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1099848b8605Smrg      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1100848b8605Smrg      break;
1101848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1102848b8605Smrg      res = set_sampler_srgb_decode(ctx, sampObj, params[0]);
1103848b8605Smrg      break;
1104848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1105848b8605Smrg      {
1106848b8605Smrg         GLfloat c[4];
1107848b8605Smrg         c[0] = INT_TO_FLOAT(params[0]);
1108848b8605Smrg         c[1] = INT_TO_FLOAT(params[1]);
1109848b8605Smrg         c[2] = INT_TO_FLOAT(params[2]);
1110848b8605Smrg         c[3] = INT_TO_FLOAT(params[3]);
1111848b8605Smrg         res = set_sampler_border_colorf(ctx, sampObj, c);
1112848b8605Smrg      }
1113848b8605Smrg      break;
1114848b8605Smrg   default:
1115848b8605Smrg      res = INVALID_PNAME;
1116848b8605Smrg   }
1117848b8605Smrg
1118848b8605Smrg   switch (res) {
1119848b8605Smrg   case GL_FALSE:
1120848b8605Smrg      /* no change */
1121848b8605Smrg      break;
1122848b8605Smrg   case GL_TRUE:
1123848b8605Smrg      /* state change - we do nothing special at this time */
1124848b8605Smrg      break;
1125848b8605Smrg   case INVALID_PNAME:
1126848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
1127b8e80941Smrg                  _mesa_enum_to_string(pname));
1128848b8605Smrg      break;
1129848b8605Smrg   case INVALID_PARAM:
1130848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
1131848b8605Smrg                  params[0]);
1132848b8605Smrg      break;
1133848b8605Smrg   case INVALID_VALUE:
1134848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
1135848b8605Smrg                  params[0]);
1136848b8605Smrg      break;
1137848b8605Smrg   default:
1138848b8605Smrg      ;
1139848b8605Smrg   }
1140848b8605Smrg}
1141848b8605Smrg
1142848b8605Smrgvoid GLAPIENTRY
1143848b8605Smrg_mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
1144848b8605Smrg{
1145848b8605Smrg   struct gl_sampler_object *sampObj;
1146848b8605Smrg   GLuint res;
1147848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1148848b8605Smrg
1149b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, false,
1150b8e80941Smrg                                           "glSamplerParameterfv");
1151b8e80941Smrg   if (!sampObj)
1152848b8605Smrg      return;
1153848b8605Smrg
1154848b8605Smrg   switch (pname) {
1155848b8605Smrg   case GL_TEXTURE_WRAP_S:
1156848b8605Smrg      res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
1157848b8605Smrg      break;
1158848b8605Smrg   case GL_TEXTURE_WRAP_T:
1159848b8605Smrg      res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
1160848b8605Smrg      break;
1161848b8605Smrg   case GL_TEXTURE_WRAP_R:
1162848b8605Smrg      res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
1163848b8605Smrg      break;
1164848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
1165848b8605Smrg      res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
1166848b8605Smrg      break;
1167848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
1168848b8605Smrg      res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
1169848b8605Smrg      break;
1170848b8605Smrg   case GL_TEXTURE_MIN_LOD:
1171848b8605Smrg      res = set_sampler_min_lod(ctx, sampObj, params[0]);
1172848b8605Smrg      break;
1173848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1174848b8605Smrg      res = set_sampler_max_lod(ctx, sampObj, params[0]);
1175848b8605Smrg      break;
1176848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1177848b8605Smrg      res = set_sampler_lod_bias(ctx, sampObj, params[0]);
1178848b8605Smrg      break;
1179848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1180848b8605Smrg      res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
1181848b8605Smrg      break;
1182848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1183848b8605Smrg      res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
1184848b8605Smrg      break;
1185848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1186848b8605Smrg      res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
1187848b8605Smrg      break;
1188848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1189848b8605Smrg      res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]);
1190848b8605Smrg      break;
1191848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1192848b8605Smrg      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1193848b8605Smrg      break;
1194848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1195848b8605Smrg      res = set_sampler_border_colorf(ctx, sampObj, params);
1196848b8605Smrg      break;
1197848b8605Smrg   default:
1198848b8605Smrg      res = INVALID_PNAME;
1199848b8605Smrg   }
1200848b8605Smrg
1201848b8605Smrg   switch (res) {
1202848b8605Smrg   case GL_FALSE:
1203848b8605Smrg      /* no change */
1204848b8605Smrg      break;
1205848b8605Smrg   case GL_TRUE:
1206848b8605Smrg      /* state change - we do nothing special at this time */
1207848b8605Smrg      break;
1208848b8605Smrg   case INVALID_PNAME:
1209848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
1210b8e80941Smrg                  _mesa_enum_to_string(pname));
1211848b8605Smrg      break;
1212848b8605Smrg   case INVALID_PARAM:
1213848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
1214848b8605Smrg                  params[0]);
1215848b8605Smrg      break;
1216848b8605Smrg   case INVALID_VALUE:
1217848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
1218848b8605Smrg                  params[0]);
1219848b8605Smrg      break;
1220848b8605Smrg   default:
1221848b8605Smrg      ;
1222848b8605Smrg   }
1223848b8605Smrg}
1224848b8605Smrg
1225848b8605Smrgvoid GLAPIENTRY
1226848b8605Smrg_mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
1227848b8605Smrg{
1228848b8605Smrg   struct gl_sampler_object *sampObj;
1229848b8605Smrg   GLuint res;
1230848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1231848b8605Smrg
1232b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, false,
1233b8e80941Smrg                                           "glSamplerParameterIiv");
1234b8e80941Smrg   if (!sampObj)
1235848b8605Smrg      return;
1236848b8605Smrg
1237848b8605Smrg   switch (pname) {
1238848b8605Smrg   case GL_TEXTURE_WRAP_S:
1239848b8605Smrg      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1240848b8605Smrg      break;
1241848b8605Smrg   case GL_TEXTURE_WRAP_T:
1242848b8605Smrg      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1243848b8605Smrg      break;
1244848b8605Smrg   case GL_TEXTURE_WRAP_R:
1245848b8605Smrg      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1246848b8605Smrg      break;
1247848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
1248848b8605Smrg      res = set_sampler_min_filter(ctx, sampObj, params[0]);
1249848b8605Smrg      break;
1250848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
1251848b8605Smrg      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1252848b8605Smrg      break;
1253848b8605Smrg   case GL_TEXTURE_MIN_LOD:
1254848b8605Smrg      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1255848b8605Smrg      break;
1256848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1257848b8605Smrg      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1258848b8605Smrg      break;
1259848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1260848b8605Smrg      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1261848b8605Smrg      break;
1262848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1263848b8605Smrg      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1264848b8605Smrg      break;
1265848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1266848b8605Smrg      res = set_sampler_compare_func(ctx, sampObj, params[0]);
1267848b8605Smrg      break;
1268848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1269848b8605Smrg      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1270848b8605Smrg      break;
1271848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1272848b8605Smrg      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1273848b8605Smrg      break;
1274848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1275848b8605Smrg      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1276848b8605Smrg      break;
1277848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1278848b8605Smrg      res = set_sampler_border_colori(ctx, sampObj, params);
1279848b8605Smrg      break;
1280848b8605Smrg   default:
1281848b8605Smrg      res = INVALID_PNAME;
1282848b8605Smrg   }
1283848b8605Smrg
1284848b8605Smrg   switch (res) {
1285848b8605Smrg   case GL_FALSE:
1286848b8605Smrg      /* no change */
1287848b8605Smrg      break;
1288848b8605Smrg   case GL_TRUE:
1289848b8605Smrg      /* state change - we do nothing special at this time */
1290848b8605Smrg      break;
1291848b8605Smrg   case INVALID_PNAME:
1292848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
1293b8e80941Smrg                  _mesa_enum_to_string(pname));
1294848b8605Smrg      break;
1295848b8605Smrg   case INVALID_PARAM:
1296848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
1297848b8605Smrg                  params[0]);
1298848b8605Smrg      break;
1299848b8605Smrg   case INVALID_VALUE:
1300848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
1301848b8605Smrg                  params[0]);
1302848b8605Smrg      break;
1303848b8605Smrg   default:
1304848b8605Smrg      ;
1305848b8605Smrg   }
1306848b8605Smrg}
1307848b8605Smrg
1308848b8605Smrg
1309848b8605Smrgvoid GLAPIENTRY
1310848b8605Smrg_mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
1311848b8605Smrg{
1312848b8605Smrg   struct gl_sampler_object *sampObj;
1313848b8605Smrg   GLuint res;
1314848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1315848b8605Smrg
1316b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, false,
1317b8e80941Smrg                                           "glSamplerParameterIuiv");
1318b8e80941Smrg   if (!sampObj)
1319848b8605Smrg      return;
1320848b8605Smrg
1321848b8605Smrg   switch (pname) {
1322848b8605Smrg   case GL_TEXTURE_WRAP_S:
1323848b8605Smrg      res = set_sampler_wrap_s(ctx, sampObj, params[0]);
1324848b8605Smrg      break;
1325848b8605Smrg   case GL_TEXTURE_WRAP_T:
1326848b8605Smrg      res = set_sampler_wrap_t(ctx, sampObj, params[0]);
1327848b8605Smrg      break;
1328848b8605Smrg   case GL_TEXTURE_WRAP_R:
1329848b8605Smrg      res = set_sampler_wrap_r(ctx, sampObj, params[0]);
1330848b8605Smrg      break;
1331848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
1332848b8605Smrg      res = set_sampler_min_filter(ctx, sampObj, params[0]);
1333848b8605Smrg      break;
1334848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
1335848b8605Smrg      res = set_sampler_mag_filter(ctx, sampObj, params[0]);
1336848b8605Smrg      break;
1337848b8605Smrg   case GL_TEXTURE_MIN_LOD:
1338848b8605Smrg      res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
1339848b8605Smrg      break;
1340848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1341848b8605Smrg      res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
1342848b8605Smrg      break;
1343848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1344848b8605Smrg      res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
1345848b8605Smrg      break;
1346848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1347848b8605Smrg      res = set_sampler_compare_mode(ctx, sampObj, params[0]);
1348848b8605Smrg      break;
1349848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1350848b8605Smrg      res = set_sampler_compare_func(ctx, sampObj, params[0]);
1351848b8605Smrg      break;
1352848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1353848b8605Smrg      res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
1354848b8605Smrg      break;
1355848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1356848b8605Smrg      res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
1357848b8605Smrg      break;
1358848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1359848b8605Smrg      res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
1360848b8605Smrg      break;
1361848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1362848b8605Smrg      res = set_sampler_border_colorui(ctx, sampObj, params);
1363848b8605Smrg      break;
1364848b8605Smrg   default:
1365848b8605Smrg      res = INVALID_PNAME;
1366848b8605Smrg   }
1367848b8605Smrg
1368848b8605Smrg   switch (res) {
1369848b8605Smrg   case GL_FALSE:
1370848b8605Smrg      /* no change */
1371848b8605Smrg      break;
1372848b8605Smrg   case GL_TRUE:
1373848b8605Smrg      /* state change - we do nothing special at this time */
1374848b8605Smrg      break;
1375848b8605Smrg   case INVALID_PNAME:
1376848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
1377b8e80941Smrg                  _mesa_enum_to_string(pname));
1378848b8605Smrg      break;
1379848b8605Smrg   case INVALID_PARAM:
1380848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
1381848b8605Smrg                  params[0]);
1382848b8605Smrg      break;
1383848b8605Smrg   case INVALID_VALUE:
1384848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
1385848b8605Smrg                  params[0]);
1386848b8605Smrg      break;
1387848b8605Smrg   default:
1388848b8605Smrg      ;
1389848b8605Smrg   }
1390848b8605Smrg}
1391848b8605Smrg
1392848b8605Smrg
1393848b8605Smrgvoid GLAPIENTRY
1394848b8605Smrg_mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
1395848b8605Smrg{
1396848b8605Smrg   struct gl_sampler_object *sampObj;
1397848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1398848b8605Smrg
1399b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, true,
1400b8e80941Smrg                                           "glGetSamplerParameteriv");
1401b8e80941Smrg   if (!sampObj)
1402848b8605Smrg      return;
1403848b8605Smrg
1404848b8605Smrg   switch (pname) {
1405848b8605Smrg   case GL_TEXTURE_WRAP_S:
1406848b8605Smrg      *params = sampObj->WrapS;
1407848b8605Smrg      break;
1408848b8605Smrg   case GL_TEXTURE_WRAP_T:
1409848b8605Smrg      *params = sampObj->WrapT;
1410848b8605Smrg      break;
1411848b8605Smrg   case GL_TEXTURE_WRAP_R:
1412848b8605Smrg      *params = sampObj->WrapR;
1413848b8605Smrg      break;
1414848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
1415848b8605Smrg      *params = sampObj->MinFilter;
1416848b8605Smrg      break;
1417848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
1418848b8605Smrg      *params = sampObj->MagFilter;
1419848b8605Smrg      break;
1420848b8605Smrg   case GL_TEXTURE_MIN_LOD:
1421b8e80941Smrg      /* GL spec 'Data Conversions' section specifies that floating-point
1422b8e80941Smrg       * value in integer Get function is rounded to nearest integer
1423b8e80941Smrg       */
1424b8e80941Smrg      *params = IROUND(sampObj->MinLod);
1425848b8605Smrg      break;
1426848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1427b8e80941Smrg      /* GL spec 'Data Conversions' section specifies that floating-point
1428b8e80941Smrg       * value in integer Get function is rounded to nearest integer
1429b8e80941Smrg       */
1430b8e80941Smrg      *params = IROUND(sampObj->MaxLod);
1431848b8605Smrg      break;
1432848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1433b8e80941Smrg      /* GL spec 'Data Conversions' section specifies that floating-point
1434b8e80941Smrg       * value in integer Get function is rounded to nearest integer
1435b8e80941Smrg       */
1436b8e80941Smrg      *params = IROUND(sampObj->LodBias);
1437848b8605Smrg      break;
1438848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1439848b8605Smrg      *params = sampObj->CompareMode;
1440848b8605Smrg      break;
1441848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1442848b8605Smrg      *params = sampObj->CompareFunc;
1443848b8605Smrg      break;
1444848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1445b8e80941Smrg      /* GL spec 'Data Conversions' section specifies that floating-point
1446b8e80941Smrg       * value in integer Get function is rounded to nearest integer
1447b8e80941Smrg       */
1448b8e80941Smrg      *params = IROUND(sampObj->MaxAnisotropy);
1449848b8605Smrg      break;
1450848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1451848b8605Smrg      params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
1452848b8605Smrg      params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
1453848b8605Smrg      params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
1454848b8605Smrg      params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
1455848b8605Smrg      break;
1456848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1457848b8605Smrg      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1458848b8605Smrg         goto invalid_pname;
1459848b8605Smrg      *params = sampObj->CubeMapSeamless;
1460848b8605Smrg      break;
1461848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1462848b8605Smrg      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1463848b8605Smrg         goto invalid_pname;
1464848b8605Smrg      *params = (GLenum) sampObj->sRGBDecode;
1465848b8605Smrg      break;
1466848b8605Smrg   default:
1467848b8605Smrg      goto invalid_pname;
1468848b8605Smrg   }
1469848b8605Smrg   return;
1470848b8605Smrg
1471848b8605Smrginvalid_pname:
1472848b8605Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
1473b8e80941Smrg               _mesa_enum_to_string(pname));
1474848b8605Smrg}
1475848b8605Smrg
1476848b8605Smrg
1477848b8605Smrgvoid GLAPIENTRY
1478848b8605Smrg_mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
1479848b8605Smrg{
1480848b8605Smrg   struct gl_sampler_object *sampObj;
1481848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1482848b8605Smrg
1483b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, true,
1484b8e80941Smrg                                           "glGetSamplerParameterfv");
1485b8e80941Smrg   if (!sampObj)
1486848b8605Smrg      return;
1487848b8605Smrg
1488848b8605Smrg   switch (pname) {
1489848b8605Smrg   case GL_TEXTURE_WRAP_S:
1490848b8605Smrg      *params = (GLfloat) sampObj->WrapS;
1491848b8605Smrg      break;
1492848b8605Smrg   case GL_TEXTURE_WRAP_T:
1493848b8605Smrg      *params = (GLfloat) sampObj->WrapT;
1494848b8605Smrg      break;
1495848b8605Smrg   case GL_TEXTURE_WRAP_R:
1496848b8605Smrg      *params = (GLfloat) sampObj->WrapR;
1497848b8605Smrg      break;
1498848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
1499848b8605Smrg      *params = (GLfloat) sampObj->MinFilter;
1500848b8605Smrg      break;
1501848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
1502848b8605Smrg      *params = (GLfloat) sampObj->MagFilter;
1503848b8605Smrg      break;
1504848b8605Smrg   case GL_TEXTURE_MIN_LOD:
1505848b8605Smrg      *params = sampObj->MinLod;
1506848b8605Smrg      break;
1507848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1508848b8605Smrg      *params = sampObj->MaxLod;
1509848b8605Smrg      break;
1510848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1511848b8605Smrg      *params = sampObj->LodBias;
1512848b8605Smrg      break;
1513848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1514848b8605Smrg      *params = (GLfloat) sampObj->CompareMode;
1515848b8605Smrg      break;
1516848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1517848b8605Smrg      *params = (GLfloat) sampObj->CompareFunc;
1518848b8605Smrg      break;
1519848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1520848b8605Smrg      *params = sampObj->MaxAnisotropy;
1521848b8605Smrg      break;
1522848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1523848b8605Smrg      params[0] = sampObj->BorderColor.f[0];
1524848b8605Smrg      params[1] = sampObj->BorderColor.f[1];
1525848b8605Smrg      params[2] = sampObj->BorderColor.f[2];
1526848b8605Smrg      params[3] = sampObj->BorderColor.f[3];
1527848b8605Smrg      break;
1528848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1529848b8605Smrg      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1530848b8605Smrg         goto invalid_pname;
1531848b8605Smrg      *params = (GLfloat) sampObj->CubeMapSeamless;
1532848b8605Smrg      break;
1533848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1534848b8605Smrg      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1535848b8605Smrg         goto invalid_pname;
1536848b8605Smrg      *params = (GLfloat) sampObj->sRGBDecode;
1537848b8605Smrg      break;
1538848b8605Smrg   default:
1539848b8605Smrg      goto invalid_pname;
1540848b8605Smrg   }
1541848b8605Smrg   return;
1542848b8605Smrg
1543848b8605Smrginvalid_pname:
1544848b8605Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
1545b8e80941Smrg               _mesa_enum_to_string(pname));
1546848b8605Smrg}
1547848b8605Smrg
1548848b8605Smrg
1549848b8605Smrgvoid GLAPIENTRY
1550848b8605Smrg_mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
1551848b8605Smrg{
1552848b8605Smrg   struct gl_sampler_object *sampObj;
1553848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1554848b8605Smrg
1555b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, true,
1556b8e80941Smrg                                           "glGetSamplerParameterIiv");
1557b8e80941Smrg   if (!sampObj)
1558848b8605Smrg      return;
1559848b8605Smrg
1560848b8605Smrg   switch (pname) {
1561848b8605Smrg   case GL_TEXTURE_WRAP_S:
1562848b8605Smrg      *params = sampObj->WrapS;
1563848b8605Smrg      break;
1564848b8605Smrg   case GL_TEXTURE_WRAP_T:
1565848b8605Smrg      *params = sampObj->WrapT;
1566848b8605Smrg      break;
1567848b8605Smrg   case GL_TEXTURE_WRAP_R:
1568848b8605Smrg      *params = sampObj->WrapR;
1569848b8605Smrg      break;
1570848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
1571848b8605Smrg      *params = sampObj->MinFilter;
1572848b8605Smrg      break;
1573848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
1574848b8605Smrg      *params = sampObj->MagFilter;
1575848b8605Smrg      break;
1576848b8605Smrg   case GL_TEXTURE_MIN_LOD:
1577848b8605Smrg      *params = (GLint) sampObj->MinLod;
1578848b8605Smrg      break;
1579848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1580848b8605Smrg      *params = (GLint) sampObj->MaxLod;
1581848b8605Smrg      break;
1582848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1583848b8605Smrg      *params = (GLint) sampObj->LodBias;
1584848b8605Smrg      break;
1585848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1586848b8605Smrg      *params = sampObj->CompareMode;
1587848b8605Smrg      break;
1588848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1589848b8605Smrg      *params = sampObj->CompareFunc;
1590848b8605Smrg      break;
1591848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1592848b8605Smrg      *params = (GLint) sampObj->MaxAnisotropy;
1593848b8605Smrg      break;
1594848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1595848b8605Smrg      params[0] = sampObj->BorderColor.i[0];
1596848b8605Smrg      params[1] = sampObj->BorderColor.i[1];
1597848b8605Smrg      params[2] = sampObj->BorderColor.i[2];
1598848b8605Smrg      params[3] = sampObj->BorderColor.i[3];
1599848b8605Smrg      break;
1600848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1601848b8605Smrg      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1602848b8605Smrg         goto invalid_pname;
1603848b8605Smrg      *params = sampObj->CubeMapSeamless;
1604848b8605Smrg      break;
1605848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1606848b8605Smrg      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1607848b8605Smrg         goto invalid_pname;
1608848b8605Smrg      *params = (GLenum) sampObj->sRGBDecode;
1609848b8605Smrg      break;
1610848b8605Smrg   default:
1611848b8605Smrg      goto invalid_pname;
1612848b8605Smrg   }
1613848b8605Smrg   return;
1614848b8605Smrg
1615848b8605Smrginvalid_pname:
1616848b8605Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
1617b8e80941Smrg               _mesa_enum_to_string(pname));
1618848b8605Smrg}
1619848b8605Smrg
1620848b8605Smrg
1621848b8605Smrgvoid GLAPIENTRY
1622848b8605Smrg_mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
1623848b8605Smrg{
1624848b8605Smrg   struct gl_sampler_object *sampObj;
1625848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1626848b8605Smrg
1627b8e80941Smrg   sampObj = sampler_parameter_error_check(ctx, sampler, true,
1628b8e80941Smrg                                           "glGetSamplerParameterIuiv");
1629b8e80941Smrg   if (!sampObj)
1630848b8605Smrg      return;
1631848b8605Smrg
1632848b8605Smrg   switch (pname) {
1633848b8605Smrg   case GL_TEXTURE_WRAP_S:
1634848b8605Smrg      *params = sampObj->WrapS;
1635848b8605Smrg      break;
1636848b8605Smrg   case GL_TEXTURE_WRAP_T:
1637848b8605Smrg      *params = sampObj->WrapT;
1638848b8605Smrg      break;
1639848b8605Smrg   case GL_TEXTURE_WRAP_R:
1640848b8605Smrg      *params = sampObj->WrapR;
1641848b8605Smrg      break;
1642848b8605Smrg   case GL_TEXTURE_MIN_FILTER:
1643848b8605Smrg      *params = sampObj->MinFilter;
1644848b8605Smrg      break;
1645848b8605Smrg   case GL_TEXTURE_MAG_FILTER:
1646848b8605Smrg      *params = sampObj->MagFilter;
1647848b8605Smrg      break;
1648848b8605Smrg   case GL_TEXTURE_MIN_LOD:
1649848b8605Smrg      *params = (GLuint) sampObj->MinLod;
1650848b8605Smrg      break;
1651848b8605Smrg   case GL_TEXTURE_MAX_LOD:
1652848b8605Smrg      *params = (GLuint) sampObj->MaxLod;
1653848b8605Smrg      break;
1654848b8605Smrg   case GL_TEXTURE_LOD_BIAS:
1655848b8605Smrg      *params = (GLuint) sampObj->LodBias;
1656848b8605Smrg      break;
1657848b8605Smrg   case GL_TEXTURE_COMPARE_MODE:
1658848b8605Smrg      *params = sampObj->CompareMode;
1659848b8605Smrg      break;
1660848b8605Smrg   case GL_TEXTURE_COMPARE_FUNC:
1661848b8605Smrg      *params = sampObj->CompareFunc;
1662848b8605Smrg      break;
1663848b8605Smrg   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1664848b8605Smrg      *params = (GLuint) sampObj->MaxAnisotropy;
1665848b8605Smrg      break;
1666848b8605Smrg   case GL_TEXTURE_BORDER_COLOR:
1667848b8605Smrg      params[0] = sampObj->BorderColor.ui[0];
1668848b8605Smrg      params[1] = sampObj->BorderColor.ui[1];
1669848b8605Smrg      params[2] = sampObj->BorderColor.ui[2];
1670848b8605Smrg      params[3] = sampObj->BorderColor.ui[3];
1671848b8605Smrg      break;
1672848b8605Smrg   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1673848b8605Smrg      if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1674848b8605Smrg         goto invalid_pname;
1675848b8605Smrg      *params = sampObj->CubeMapSeamless;
1676848b8605Smrg      break;
1677848b8605Smrg   case GL_TEXTURE_SRGB_DECODE_EXT:
1678848b8605Smrg      if (!ctx->Extensions.EXT_texture_sRGB_decode)
1679848b8605Smrg         goto invalid_pname;
1680848b8605Smrg      *params = (GLenum) sampObj->sRGBDecode;
1681848b8605Smrg      break;
1682848b8605Smrg   default:
1683848b8605Smrg      goto invalid_pname;
1684848b8605Smrg   }
1685848b8605Smrg   return;
1686848b8605Smrg
1687848b8605Smrginvalid_pname:
1688848b8605Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
1689b8e80941Smrg               _mesa_enum_to_string(pname));
1690848b8605Smrg}
1691848b8605Smrg
1692848b8605Smrg
1693848b8605Smrgvoid
1694848b8605Smrg_mesa_init_sampler_object_functions(struct dd_function_table *driver)
1695848b8605Smrg{
1696848b8605Smrg   driver->NewSamplerObject = _mesa_new_sampler_object;
1697848b8605Smrg}
1698