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