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