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