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