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