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