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  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     20  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 
     25 /**
     26  * \file samplerobj.c
     27  * \brief Functions for the GL_ARB_sampler_objects extension.
     28  * \author Brian Paul
     29  */
     30 
     31 
     32 #include "main/glheader.h"
     33 #include "main/context.h"
     34 #include "main/dispatch.h"
     35 #include "main/enums.h"
     36 #include "main/hash.h"
     37 #include "main/macros.h"
     38 #include "main/mfeatures.h"
     39 #include "main/mtypes.h"
     40 #include "main/samplerobj.h"
     41 
     42 
     43 static 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 
     54 /**
     55  * Handle reference counting.
     56  */
     57 void
     58 _mesa_reference_sampler_object_(struct gl_context *ctx,
     59                                 struct gl_sampler_object **ptr,
     60                                 struct gl_sampler_object *samp)
     61 {
     62    assert(*ptr != samp); /* The inline wrapper should prevent no-op calls */
     63 
     64    if (*ptr) {
     65       /* Unreference the old sampler */
     66       GLboolean deleteFlag = GL_FALSE;
     67       struct gl_sampler_object *oldSamp = *ptr;
     68 
     69       /*_glthread_LOCK_MUTEX(oldSamp->Mutex);*/
     70       ASSERT(oldSamp->RefCount > 0);
     71       oldSamp->RefCount--;
     72 #if 0
     73       printf("SamplerObj %p %d DECR to %d\n",
     74              (void *) oldSamp, oldSamp->Name, oldSamp->RefCount);
     75 #endif
     76       deleteFlag = (oldSamp->RefCount == 0);
     77       /*_glthread_UNLOCK_MUTEX(oldSamp->Mutex);*/
     78 
     79       if (deleteFlag) {
     80 	 ASSERT(ctx->Driver.DeleteSamplerObject);
     81          ctx->Driver.DeleteSamplerObject(ctx, oldSamp);
     82       }
     83 
     84       *ptr = NULL;
     85    }
     86    ASSERT(!*ptr);
     87 
     88    if (samp) {
     89       /* reference new sampler */
     90       /*_glthread_LOCK_MUTEX(samp->Mutex);*/
     91       if (samp->RefCount == 0) {
     92          /* this sampler's being deleted (look just above) */
     93          /* Not sure this can every really happen.  Warn if it does. */
     94          _mesa_problem(NULL, "referencing deleted sampler object");
     95          *ptr = NULL;
     96       }
     97       else {
     98          samp->RefCount++;
     99 #if 0
    100          printf("SamplerObj %p %d INCR to %d\n",
    101                 (void *) samp, samp->Name, samp->RefCount);
    102 #endif
    103          *ptr = samp;
    104       }
    105       /*_glthread_UNLOCK_MUTEX(samp->Mutex);*/
    106    }
    107 }
    108 
    109 
    110 /**
    111  * Initialize the fields of the given sampler object.
    112  */
    113 void
    114 _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
    115 {
    116    sampObj->Name = name;
    117    sampObj->RefCount = 1;
    118    sampObj->WrapS = GL_REPEAT;
    119    sampObj->WrapT = GL_REPEAT;
    120    sampObj->WrapR = GL_REPEAT;
    121    sampObj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
    122    sampObj->MagFilter = GL_LINEAR;
    123    sampObj->BorderColor.f[0] = 0.0;
    124    sampObj->BorderColor.f[1] = 0.0;
    125    sampObj->BorderColor.f[2] = 0.0;
    126    sampObj->BorderColor.f[3] = 0.0;
    127    sampObj->MinLod = -1000.0F;
    128    sampObj->MaxLod = 1000.0F;
    129    sampObj->LodBias = 0.0F;
    130    sampObj->MaxAnisotropy = 1.0F;
    131    sampObj->CompareMode = GL_NONE;
    132    sampObj->CompareFunc = GL_LEQUAL;
    133    sampObj->sRGBDecode = GL_DECODE_EXT;
    134    sampObj->CubeMapSeamless = GL_FALSE;
    135 }
    136 
    137 /**
    138  * Fallback for ctx->Driver.NewSamplerObject();
    139  */
    140 struct gl_sampler_object *
    141 _mesa_new_sampler_object(struct gl_context *ctx, GLuint name)
    142 {
    143    struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object);
    144    if (sampObj) {
    145       _mesa_init_sampler_object(sampObj, name);
    146    }
    147    return sampObj;
    148 }
    149 
    150 
    151 /**
    152  * Fallback for ctx->Driver.DeleteSamplerObject();
    153  */
    154 void
    155 _mesa_delete_sampler_object(struct gl_context *ctx,
    156                             struct gl_sampler_object *sampObj)
    157 {
    158    FREE(sampObj);
    159 }
    160 
    161 
    162 void GLAPIENTRY
    163 _mesa_GenSamplers(GLsizei count, GLuint *samplers)
    164 {
    165    GET_CURRENT_CONTEXT(ctx);
    166    GLuint first;
    167    GLint i;
    168 
    169    ASSERT_OUTSIDE_BEGIN_END(ctx);
    170 
    171    if (MESA_VERBOSE & VERBOSE_API)
    172       _mesa_debug(ctx, "glGenSamplers(%d)\n", count);
    173 
    174    if (count < 0) {
    175       _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers");
    176       return;
    177    }
    178 
    179    if (!samplers)
    180       return;
    181 
    182    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count);
    183 
    184    /* Insert the ID and pointer to new sampler object into hash table */
    185    for (i = 0; i < count; i++) {
    186       struct gl_sampler_object *sampObj =
    187          ctx->Driver.NewSamplerObject(ctx, first + i);
    188       _mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj);
    189       samplers[i] = first + i;
    190    }
    191 }
    192 
    193 
    194 void GLAPIENTRY
    195 _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
    196 {
    197    GET_CURRENT_CONTEXT(ctx);
    198    GLsizei i;
    199 
    200    ASSERT_OUTSIDE_BEGIN_END(ctx);
    201    FLUSH_VERTICES(ctx, 0);
    202 
    203    if (count < 0) {
    204       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
    205       return;
    206    }
    207 
    208    _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
    209 
    210    for (i = 0; i < count; i++) {
    211       if (samplers[i]) {
    212          struct gl_sampler_object *sampObj =
    213             _mesa_lookup_samplerobj(ctx, samplers[i]);
    214          if (sampObj) {
    215             /* The ID is immediately freed for re-use */
    216             _mesa_HashRemove(ctx->Shared->SamplerObjects, samplers[i]);
    217             /* But the object exists until its reference count goes to zero */
    218             _mesa_reference_sampler_object(ctx, &sampObj, NULL);
    219          }
    220       }
    221    }
    222 
    223    _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
    224 }
    225 
    226 
    227 static GLboolean GLAPIENTRY
    228 _mesa_IsSampler(GLuint sampler)
    229 {
    230    struct gl_sampler_object *sampObj;
    231    GET_CURRENT_CONTEXT(ctx);
    232 
    233    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
    234 
    235    if (sampler == 0)
    236       return GL_FALSE;
    237 
    238    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
    239 
    240    return sampObj != NULL;
    241 }
    242 
    243 
    244 void GLAPIENTRY
    245 _mesa_BindSampler(GLuint unit, GLuint sampler)
    246 {
    247    struct gl_sampler_object *sampObj;
    248    GET_CURRENT_CONTEXT(ctx);
    249 
    250    if (unit >= ctx->Const.MaxCombinedTextureImageUnits) {
    251       _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
    252       return;
    253    }
    254 
    255    if (sampler == 0) {
    256       /* Use the default sampler object, the one contained in the texture
    257        * object.
    258        */
    259       sampObj = NULL;
    260    }
    261    else {
    262       /* user-defined sampler object */
    263       sampObj = _mesa_lookup_samplerobj(ctx, sampler);
    264       if (!sampObj) {
    265          _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)");
    266          return;
    267       }
    268    }
    269 
    270    if (ctx->Texture.Unit[unit].Sampler != sampObj) {
    271       FLUSH_VERTICES(ctx, _NEW_TEXTURE);
    272    }
    273 
    274    /* bind new sampler */
    275    _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler,
    276                                   sampObj);
    277 }
    278 
    279 
    280 /**
    281  * Check if a coordinate wrap mode is legal.
    282  * \return GL_TRUE if legal, GL_FALSE otherwise
    283  */
    284 static GLboolean
    285 validate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap)
    286 {
    287    const struct gl_extensions * const e = &ctx->Extensions;
    288 
    289    switch (wrap) {
    290    case GL_CLAMP:
    291    case GL_CLAMP_TO_EDGE:
    292    case GL_REPEAT:
    293    case GL_MIRRORED_REPEAT:
    294       return GL_TRUE;
    295    case GL_CLAMP_TO_BORDER:
    296       return e->ARB_texture_border_clamp;
    297    case GL_MIRROR_CLAMP_EXT:
    298       return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
    299    case GL_MIRROR_CLAMP_TO_EDGE_EXT:
    300       return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
    301    case GL_MIRROR_CLAMP_TO_BORDER_EXT:
    302       return e->EXT_texture_mirror_clamp;
    303    default:
    304       return GL_FALSE;
    305    }
    306 }
    307 
    308 
    309 /**
    310  * This is called just prior to changing any sampler object state.
    311  */
    312 static inline void
    313 flush(struct gl_context *ctx)
    314 {
    315    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
    316 }
    317 
    318 
    319 #define INVALID_PARAM 0x100
    320 #define INVALID_PNAME 0x101
    321 #define INVALID_VALUE 0x102
    322 
    323 static GLuint
    324 set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
    325                    GLint param)
    326 {
    327    if (samp->WrapS == param)
    328       return GL_FALSE;
    329    if (validate_texture_wrap_mode(ctx, param)) {
    330       flush(ctx);
    331       samp->WrapS = param;
    332       return GL_TRUE;
    333    }
    334    return INVALID_PARAM;
    335 }
    336 
    337 
    338 static GLuint
    339 set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
    340                    GLint param)
    341 {
    342    if (samp->WrapT == param)
    343       return GL_FALSE;
    344    if (validate_texture_wrap_mode(ctx, param)) {
    345       flush(ctx);
    346       samp->WrapT = param;
    347       return GL_TRUE;
    348    }
    349    return INVALID_PARAM;
    350 }
    351 
    352 
    353 static GLuint
    354 set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
    355                    GLint param)
    356 {
    357    if (samp->WrapR == param)
    358       return GL_FALSE;
    359    if (validate_texture_wrap_mode(ctx, param)) {
    360       flush(ctx);
    361       samp->WrapR = param;
    362       return GL_TRUE;
    363    }
    364    return INVALID_PARAM;
    365 }
    366 
    367 
    368 static GLuint
    369 set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
    370                        GLint param)
    371 {
    372    if (samp->MinFilter == param)
    373       return GL_FALSE;
    374 
    375    switch (param) {
    376    case GL_NEAREST:
    377    case GL_LINEAR:
    378    case GL_NEAREST_MIPMAP_NEAREST:
    379    case GL_LINEAR_MIPMAP_NEAREST:
    380    case GL_NEAREST_MIPMAP_LINEAR:
    381    case GL_LINEAR_MIPMAP_LINEAR:
    382       flush(ctx);
    383       samp->MinFilter = param;
    384       return GL_TRUE;
    385    default:
    386       return INVALID_PARAM;
    387    }
    388 }
    389 
    390 
    391 static GLuint
    392 set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
    393                        GLint param)
    394 {
    395    if (samp->MagFilter == param)
    396       return GL_FALSE;
    397 
    398    switch (param) {
    399    case GL_NEAREST:
    400    case GL_LINEAR:
    401       flush(ctx);
    402       samp->MagFilter = param;
    403       return GL_TRUE;
    404    default:
    405       return INVALID_PARAM;
    406    }
    407 }
    408 
    409 
    410 static GLuint
    411 set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
    412                      GLfloat param)
    413 {
    414    if (samp->LodBias == param)
    415       return GL_FALSE;
    416 
    417    flush(ctx);
    418    samp->LodBias = param;
    419    return GL_TRUE;
    420 }
    421 
    422 
    423 static GLuint
    424 set_sampler_border_colorf(struct gl_context *ctx,
    425                           struct gl_sampler_object *samp,
    426                           const GLfloat params[4])
    427 {
    428    flush(ctx);
    429    samp->BorderColor.f[RCOMP] = params[0];
    430    samp->BorderColor.f[GCOMP] = params[1];
    431    samp->BorderColor.f[BCOMP] = params[2];
    432    samp->BorderColor.f[ACOMP] = params[3];
    433    return GL_TRUE;
    434 }
    435 
    436 
    437 static GLuint
    438 set_sampler_border_colori(struct gl_context *ctx,
    439                           struct gl_sampler_object *samp,
    440                           const GLint params[4])
    441 {
    442    flush(ctx);
    443    samp->BorderColor.i[RCOMP] = params[0];
    444    samp->BorderColor.i[GCOMP] = params[1];
    445    samp->BorderColor.i[BCOMP] = params[2];
    446    samp->BorderColor.i[ACOMP] = params[3];
    447    return GL_TRUE;
    448 }
    449 
    450 
    451 static GLuint
    452 set_sampler_border_colorui(struct gl_context *ctx,
    453                            struct gl_sampler_object *samp,
    454                            const GLuint params[4])
    455 {
    456    flush(ctx);
    457    samp->BorderColor.ui[RCOMP] = params[0];
    458    samp->BorderColor.ui[GCOMP] = params[1];
    459    samp->BorderColor.ui[BCOMP] = params[2];
    460    samp->BorderColor.ui[ACOMP] = params[3];
    461    return GL_TRUE;
    462 }
    463 
    464 
    465 static GLuint
    466 set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
    467                     GLfloat param)
    468 {
    469    if (samp->MinLod == param)
    470       return GL_FALSE;
    471 
    472    flush(ctx);
    473    samp->MinLod = param;
    474    return GL_TRUE;
    475 }
    476 
    477 
    478 static GLuint
    479 set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
    480                     GLfloat param)
    481 {
    482    if (samp->MaxLod == param)
    483       return GL_FALSE;
    484 
    485    flush(ctx);
    486    samp->MaxLod = param;
    487    return GL_TRUE;
    488 }
    489 
    490 
    491 static GLuint
    492 set_sampler_compare_mode(struct gl_context *ctx,
    493                          struct gl_sampler_object *samp, GLint param)
    494 {
    495    if (!ctx->Extensions.ARB_shadow)
    496       return INVALID_PNAME;
    497 
    498    if (samp->CompareMode == param)
    499       return GL_FALSE;
    500 
    501    if (param == GL_NONE ||
    502        param == GL_COMPARE_R_TO_TEXTURE_ARB) {
    503       flush(ctx);
    504       samp->CompareMode = param;
    505       return GL_TRUE;
    506    }
    507 
    508    return INVALID_PARAM;
    509 }
    510 
    511 
    512 static GLuint
    513 set_sampler_compare_func(struct gl_context *ctx,
    514                          struct gl_sampler_object *samp, GLint param)
    515 {
    516    if (!ctx->Extensions.ARB_shadow)
    517       return INVALID_PNAME;
    518 
    519    if (samp->CompareFunc == param)
    520       return GL_FALSE;
    521 
    522    switch (param) {
    523    case GL_LEQUAL:
    524    case GL_GEQUAL:
    525       flush(ctx);
    526       samp->CompareFunc = param;
    527       return GL_TRUE;
    528    case GL_EQUAL:
    529    case GL_NOTEQUAL:
    530    case GL_LESS:
    531    case GL_GREATER:
    532    case GL_ALWAYS:
    533    case GL_NEVER:
    534       if (ctx->Extensions.EXT_shadow_funcs) {
    535          flush(ctx);
    536          samp->CompareFunc = param;
    537          return GL_TRUE;
    538       }
    539       /* fall-through */
    540    default:
    541       return INVALID_PARAM;
    542    }
    543 }
    544 
    545 
    546 static GLuint
    547 set_sampler_max_anisotropy(struct gl_context *ctx,
    548                            struct gl_sampler_object *samp, GLfloat param)
    549 {
    550    if (!ctx->Extensions.EXT_texture_filter_anisotropic)
    551       return INVALID_PNAME;
    552 
    553    if (samp->MaxAnisotropy == param)
    554       return GL_FALSE;
    555 
    556    if (param < 1.0)
    557       return INVALID_VALUE;
    558 
    559    flush(ctx);
    560    /* clamp to max, that's what NVIDIA does */
    561    samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
    562    return GL_TRUE;
    563 }
    564 
    565 
    566 static GLuint
    567 set_sampler_cube_map_seamless(struct gl_context *ctx,
    568                               struct gl_sampler_object *samp, GLboolean param)
    569 {
    570    if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
    571       return INVALID_PNAME;
    572 
    573    if (samp->CubeMapSeamless == param)
    574       return GL_FALSE;
    575 
    576    if (param != GL_TRUE && param != GL_FALSE)
    577       return INVALID_VALUE;
    578 
    579    flush(ctx);
    580    samp->CubeMapSeamless = param;
    581    return GL_TRUE;
    582 }
    583 
    584 static GLuint
    585 set_sampler_srgb_decode(struct gl_context *ctx,
    586                               struct gl_sampler_object *samp, GLenum param)
    587 {
    588    if (!ctx->Extensions.EXT_texture_sRGB_decode)
    589       return INVALID_PNAME;
    590 
    591    if (samp->sRGBDecode == param)
    592       return GL_FALSE;
    593 
    594    if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
    595       return INVALID_VALUE;
    596 
    597    flush(ctx);
    598    samp->sRGBDecode = param;
    599    return GL_TRUE;
    600 }
    601 
    602 void GLAPIENTRY
    603 _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
    604 {
    605    struct gl_sampler_object *sampObj;
    606    GLuint res;
    607    GET_CURRENT_CONTEXT(ctx);
    608 
    609    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
    610    if (!sampObj) {
    611       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)",
    612                   sampler);
    613       return;
    614    }
    615 
    616    switch (pname) {
    617    case GL_TEXTURE_WRAP_S:
    618       res = set_sampler_wrap_s(ctx, sampObj, param);
    619       break;
    620    case GL_TEXTURE_WRAP_T:
    621       res = set_sampler_wrap_t(ctx, sampObj, param);
    622       break;
    623    case GL_TEXTURE_WRAP_R:
    624       res = set_sampler_wrap_r(ctx, sampObj, param);
    625       break;
    626    case GL_TEXTURE_MIN_FILTER:
    627       res = set_sampler_min_filter(ctx, sampObj, param);
    628       break;
    629    case GL_TEXTURE_MAG_FILTER:
    630       res = set_sampler_mag_filter(ctx, sampObj, param);
    631       break;
    632    case GL_TEXTURE_MIN_LOD:
    633       res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
    634       break;
    635    case GL_TEXTURE_MAX_LOD:
    636       res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
    637       break;
    638    case GL_TEXTURE_LOD_BIAS:
    639       res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
    640       break;
    641    case GL_TEXTURE_COMPARE_MODE:
    642       res = set_sampler_compare_mode(ctx, sampObj, param);
    643       break;
    644    case GL_TEXTURE_COMPARE_FUNC:
    645       res = set_sampler_compare_func(ctx, sampObj, param);
    646       break;
    647    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    648       res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
    649       break;
    650    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
    651       res = set_sampler_cube_map_seamless(ctx, sampObj, param);
    652       break;
    653    case GL_TEXTURE_SRGB_DECODE_EXT:
    654       res = set_sampler_srgb_decode(ctx, sampObj, param);
    655       break;
    656    case GL_TEXTURE_BORDER_COLOR:
    657       /* fall-through */
    658    default:
    659       res = INVALID_PNAME;
    660    }
    661 
    662    switch (res) {
    663    case GL_FALSE:
    664       /* no change */
    665       break;
    666    case GL_TRUE:
    667       /* state change - we do nothing special at this time */
    668       break;
    669    case INVALID_PNAME:
    670       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
    671                   _mesa_lookup_enum_by_nr(pname));
    672       break;
    673    case INVALID_PARAM:
    674       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
    675                   param);
    676       break;
    677    case INVALID_VALUE:
    678       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
    679                   param);
    680       break;
    681    default:
    682       ;
    683    }
    684 }
    685 
    686 
    687 static void GLAPIENTRY
    688 _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
    689 {
    690    struct gl_sampler_object *sampObj;
    691    GLuint res;
    692    GET_CURRENT_CONTEXT(ctx);
    693 
    694    ASSERT_OUTSIDE_BEGIN_END(ctx);
    695 
    696    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
    697    if (!sampObj) {
    698       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(sampler %u)",
    699                   sampler);
    700       return;
    701    }
    702 
    703    switch (pname) {
    704    case GL_TEXTURE_WRAP_S:
    705       res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
    706       break;
    707    case GL_TEXTURE_WRAP_T:
    708       res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
    709       break;
    710    case GL_TEXTURE_WRAP_R:
    711       res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
    712       break;
    713    case GL_TEXTURE_MIN_FILTER:
    714       res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
    715       break;
    716    case GL_TEXTURE_MAG_FILTER:
    717       res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
    718       break;
    719    case GL_TEXTURE_MIN_LOD:
    720       res = set_sampler_min_lod(ctx, sampObj, param);
    721       break;
    722    case GL_TEXTURE_MAX_LOD:
    723       res = set_sampler_max_lod(ctx, sampObj, param);
    724       break;
    725    case GL_TEXTURE_LOD_BIAS:
    726       res = set_sampler_lod_bias(ctx, sampObj, param);
    727       break;
    728    case GL_TEXTURE_COMPARE_MODE:
    729       res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
    730       break;
    731    case GL_TEXTURE_COMPARE_FUNC:
    732       res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
    733       break;
    734    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    735       res = set_sampler_max_anisotropy(ctx, sampObj, param);
    736       break;
    737    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
    738       res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) param);
    739       break;
    740    case GL_TEXTURE_SRGB_DECODE_EXT:
    741       res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) param);
    742       break;
    743    case GL_TEXTURE_BORDER_COLOR:
    744       /* fall-through */
    745    default:
    746       res = INVALID_PNAME;
    747    }
    748 
    749    switch (res) {
    750    case GL_FALSE:
    751       /* no change */
    752       break;
    753    case GL_TRUE:
    754       /* state change - we do nothing special at this time */
    755       break;
    756    case INVALID_PNAME:
    757       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
    758                   _mesa_lookup_enum_by_nr(pname));
    759       break;
    760    case INVALID_PARAM:
    761       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
    762                   param);
    763       break;
    764    case INVALID_VALUE:
    765       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
    766                   param);
    767       break;
    768    default:
    769       ;
    770    }
    771 }
    772 
    773 static void GLAPIENTRY
    774 _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
    775 {
    776    struct gl_sampler_object *sampObj;
    777    GLuint res;
    778    GET_CURRENT_CONTEXT(ctx);
    779 
    780    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
    781    if (!sampObj) {
    782       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(sampler %u)",
    783                   sampler);
    784       return;
    785    }
    786 
    787    switch (pname) {
    788    case GL_TEXTURE_WRAP_S:
    789       res = set_sampler_wrap_s(ctx, sampObj, params[0]);
    790       break;
    791    case GL_TEXTURE_WRAP_T:
    792       res = set_sampler_wrap_t(ctx, sampObj, params[0]);
    793       break;
    794    case GL_TEXTURE_WRAP_R:
    795       res = set_sampler_wrap_r(ctx, sampObj, params[0]);
    796       break;
    797    case GL_TEXTURE_MIN_FILTER:
    798       res = set_sampler_min_filter(ctx, sampObj, params[0]);
    799       break;
    800    case GL_TEXTURE_MAG_FILTER:
    801       res = set_sampler_mag_filter(ctx, sampObj, params[0]);
    802       break;
    803    case GL_TEXTURE_MIN_LOD:
    804       res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
    805       break;
    806    case GL_TEXTURE_MAX_LOD:
    807       res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
    808       break;
    809    case GL_TEXTURE_LOD_BIAS:
    810       res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
    811       break;
    812    case GL_TEXTURE_COMPARE_MODE:
    813       res = set_sampler_compare_mode(ctx, sampObj, params[0]);
    814       break;
    815    case GL_TEXTURE_COMPARE_FUNC:
    816       res = set_sampler_compare_func(ctx, sampObj, params[0]);
    817       break;
    818    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    819       res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
    820       break;
    821    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
    822       res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
    823       break;
    824    case GL_TEXTURE_SRGB_DECODE_EXT:
    825       res = set_sampler_srgb_decode(ctx, sampObj, params[0]);
    826       break;
    827    case GL_TEXTURE_BORDER_COLOR:
    828       {
    829          GLfloat c[4];
    830          c[0] = INT_TO_FLOAT(params[0]);
    831          c[1] = INT_TO_FLOAT(params[1]);
    832          c[2] = INT_TO_FLOAT(params[2]);
    833          c[3] = INT_TO_FLOAT(params[3]);
    834          res = set_sampler_border_colorf(ctx, sampObj, c);
    835       }
    836       break;
    837    default:
    838       res = INVALID_PNAME;
    839    }
    840 
    841    switch (res) {
    842    case GL_FALSE:
    843       /* no change */
    844       break;
    845    case GL_TRUE:
    846       /* state change - we do nothing special at this time */
    847       break;
    848    case INVALID_PNAME:
    849       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
    850                   _mesa_lookup_enum_by_nr(pname));
    851       break;
    852    case INVALID_PARAM:
    853       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
    854                   params[0]);
    855       break;
    856    case INVALID_VALUE:
    857       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
    858                   params[0]);
    859       break;
    860    default:
    861       ;
    862    }
    863 }
    864 
    865 static void GLAPIENTRY
    866 _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
    867 {
    868    struct gl_sampler_object *sampObj;
    869    GLuint res;
    870    GET_CURRENT_CONTEXT(ctx);
    871 
    872    ASSERT_OUTSIDE_BEGIN_END(ctx);
    873 
    874    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
    875    if (!sampObj) {
    876       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(sampler %u)",
    877                   sampler);
    878       return;
    879    }
    880 
    881    switch (pname) {
    882    case GL_TEXTURE_WRAP_S:
    883       res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
    884       break;
    885    case GL_TEXTURE_WRAP_T:
    886       res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
    887       break;
    888    case GL_TEXTURE_WRAP_R:
    889       res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
    890       break;
    891    case GL_TEXTURE_MIN_FILTER:
    892       res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
    893       break;
    894    case GL_TEXTURE_MAG_FILTER:
    895       res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
    896       break;
    897    case GL_TEXTURE_MIN_LOD:
    898       res = set_sampler_min_lod(ctx, sampObj, params[0]);
    899       break;
    900    case GL_TEXTURE_MAX_LOD:
    901       res = set_sampler_max_lod(ctx, sampObj, params[0]);
    902       break;
    903    case GL_TEXTURE_LOD_BIAS:
    904       res = set_sampler_lod_bias(ctx, sampObj, params[0]);
    905       break;
    906    case GL_TEXTURE_COMPARE_MODE:
    907       res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
    908       break;
    909    case GL_TEXTURE_COMPARE_FUNC:
    910       res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
    911       break;
    912    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    913       res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
    914       break;
    915    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
    916       res = set_sampler_cube_map_seamless(ctx, sampObj, (GLboolean) params[0]);
    917       break;
    918    case GL_TEXTURE_SRGB_DECODE_EXT:
    919       res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
    920       break;
    921    case GL_TEXTURE_BORDER_COLOR:
    922       res = set_sampler_border_colorf(ctx, sampObj, params);
    923       break;
    924    default:
    925       res = INVALID_PNAME;
    926    }
    927 
    928    switch (res) {
    929    case GL_FALSE:
    930       /* no change */
    931       break;
    932    case GL_TRUE:
    933       /* state change - we do nothing special at this time */
    934       break;
    935    case INVALID_PNAME:
    936       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
    937                   _mesa_lookup_enum_by_nr(pname));
    938       break;
    939    case INVALID_PARAM:
    940       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
    941                   params[0]);
    942       break;
    943    case INVALID_VALUE:
    944       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
    945                   params[0]);
    946       break;
    947    default:
    948       ;
    949    }
    950 }
    951 
    952 static void GLAPIENTRY
    953 _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
    954 {
    955    struct gl_sampler_object *sampObj;
    956    GLuint res;
    957    GET_CURRENT_CONTEXT(ctx);
    958 
    959    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
    960    if (!sampObj) {
    961       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(sampler %u)",
    962                   sampler);
    963       return;
    964    }
    965 
    966    switch (pname) {
    967    case GL_TEXTURE_WRAP_S:
    968       res = set_sampler_wrap_s(ctx, sampObj, params[0]);
    969       break;
    970    case GL_TEXTURE_WRAP_T:
    971       res = set_sampler_wrap_t(ctx, sampObj, params[0]);
    972       break;
    973    case GL_TEXTURE_WRAP_R:
    974       res = set_sampler_wrap_r(ctx, sampObj, params[0]);
    975       break;
    976    case GL_TEXTURE_MIN_FILTER:
    977       res = set_sampler_min_filter(ctx, sampObj, params[0]);
    978       break;
    979    case GL_TEXTURE_MAG_FILTER:
    980       res = set_sampler_mag_filter(ctx, sampObj, params[0]);
    981       break;
    982    case GL_TEXTURE_MIN_LOD:
    983       res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
    984       break;
    985    case GL_TEXTURE_MAX_LOD:
    986       res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
    987       break;
    988    case GL_TEXTURE_LOD_BIAS:
    989       res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
    990       break;
    991    case GL_TEXTURE_COMPARE_MODE:
    992       res = set_sampler_compare_mode(ctx, sampObj, params[0]);
    993       break;
    994    case GL_TEXTURE_COMPARE_FUNC:
    995       res = set_sampler_compare_func(ctx, sampObj, params[0]);
    996       break;
    997    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    998       res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
    999       break;
   1000    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
   1001       res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
   1002       break;
   1003    case GL_TEXTURE_SRGB_DECODE_EXT:
   1004       res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
   1005       break;
   1006    case GL_TEXTURE_BORDER_COLOR:
   1007       res = set_sampler_border_colori(ctx, sampObj, params);
   1008       break;
   1009    default:
   1010       res = INVALID_PNAME;
   1011    }
   1012 
   1013    switch (res) {
   1014    case GL_FALSE:
   1015       /* no change */
   1016       break;
   1017    case GL_TRUE:
   1018       /* state change - we do nothing special at this time */
   1019       break;
   1020    case INVALID_PNAME:
   1021       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
   1022                   _mesa_lookup_enum_by_nr(pname));
   1023       break;
   1024    case INVALID_PARAM:
   1025       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
   1026                   params[0]);
   1027       break;
   1028    case INVALID_VALUE:
   1029       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
   1030                   params[0]);
   1031       break;
   1032    default:
   1033       ;
   1034    }
   1035 }
   1036 
   1037 
   1038 static void GLAPIENTRY
   1039 _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
   1040 {
   1041    struct gl_sampler_object *sampObj;
   1042    GLuint res;
   1043    GET_CURRENT_CONTEXT(ctx);
   1044 
   1045    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
   1046    if (!sampObj) {
   1047       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(sampler %u)",
   1048                   sampler);
   1049       return;
   1050    }
   1051 
   1052    switch (pname) {
   1053    case GL_TEXTURE_WRAP_S:
   1054       res = set_sampler_wrap_s(ctx, sampObj, params[0]);
   1055       break;
   1056    case GL_TEXTURE_WRAP_T:
   1057       res = set_sampler_wrap_t(ctx, sampObj, params[0]);
   1058       break;
   1059    case GL_TEXTURE_WRAP_R:
   1060       res = set_sampler_wrap_r(ctx, sampObj, params[0]);
   1061       break;
   1062    case GL_TEXTURE_MIN_FILTER:
   1063       res = set_sampler_min_filter(ctx, sampObj, params[0]);
   1064       break;
   1065    case GL_TEXTURE_MAG_FILTER:
   1066       res = set_sampler_mag_filter(ctx, sampObj, params[0]);
   1067       break;
   1068    case GL_TEXTURE_MIN_LOD:
   1069       res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
   1070       break;
   1071    case GL_TEXTURE_MAX_LOD:
   1072       res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
   1073       break;
   1074    case GL_TEXTURE_LOD_BIAS:
   1075       res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
   1076       break;
   1077    case GL_TEXTURE_COMPARE_MODE:
   1078       res = set_sampler_compare_mode(ctx, sampObj, params[0]);
   1079       break;
   1080    case GL_TEXTURE_COMPARE_FUNC:
   1081       res = set_sampler_compare_func(ctx, sampObj, params[0]);
   1082       break;
   1083    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   1084       res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
   1085       break;
   1086    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
   1087       res = set_sampler_cube_map_seamless(ctx, sampObj, params[0]);
   1088       break;
   1089    case GL_TEXTURE_SRGB_DECODE_EXT:
   1090       res = set_sampler_srgb_decode(ctx, sampObj, (GLenum) params[0]);
   1091       break;
   1092    case GL_TEXTURE_BORDER_COLOR:
   1093       res = set_sampler_border_colorui(ctx, sampObj, params);
   1094       break;
   1095    default:
   1096       res = INVALID_PNAME;
   1097    }
   1098 
   1099    switch (res) {
   1100    case GL_FALSE:
   1101       /* no change */
   1102       break;
   1103    case GL_TRUE:
   1104       /* state change - we do nothing special at this time */
   1105       break;
   1106    case INVALID_PNAME:
   1107       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
   1108                   _mesa_lookup_enum_by_nr(pname));
   1109       break;
   1110    case INVALID_PARAM:
   1111       _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
   1112                   params[0]);
   1113       break;
   1114    case INVALID_VALUE:
   1115       _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
   1116                   params[0]);
   1117       break;
   1118    default:
   1119       ;
   1120    }
   1121 }
   1122 
   1123 
   1124 static void GLAPIENTRY
   1125 _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
   1126 {
   1127    struct gl_sampler_object *sampObj;
   1128    GET_CURRENT_CONTEXT(ctx);
   1129 
   1130    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
   1131    if (!sampObj) {
   1132       _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameteriv(sampler %u)",
   1133                   sampler);
   1134       return;
   1135    }
   1136 
   1137    switch (pname) {
   1138    case GL_TEXTURE_WRAP_S:
   1139       *params = sampObj->WrapS;
   1140       break;
   1141    case GL_TEXTURE_WRAP_T:
   1142       *params = sampObj->WrapT;
   1143       break;
   1144    case GL_TEXTURE_WRAP_R:
   1145       *params = sampObj->WrapR;
   1146       break;
   1147    case GL_TEXTURE_MIN_FILTER:
   1148       *params = sampObj->MinFilter;
   1149       break;
   1150    case GL_TEXTURE_MAG_FILTER:
   1151       *params = sampObj->MagFilter;
   1152       break;
   1153    case GL_TEXTURE_MIN_LOD:
   1154       *params = (GLint) sampObj->MinLod;
   1155       break;
   1156    case GL_TEXTURE_MAX_LOD:
   1157       *params = (GLint) sampObj->MaxLod;
   1158       break;
   1159    case GL_TEXTURE_LOD_BIAS:
   1160       *params = (GLint) sampObj->LodBias;
   1161       break;
   1162    case GL_TEXTURE_COMPARE_MODE:
   1163       if (!ctx->Extensions.ARB_shadow)
   1164          goto invalid_pname;
   1165       *params = sampObj->CompareMode;
   1166       break;
   1167    case GL_TEXTURE_COMPARE_FUNC:
   1168       if (!ctx->Extensions.ARB_shadow)
   1169          goto invalid_pname;
   1170       *params = sampObj->CompareFunc;
   1171       break;
   1172    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   1173       *params = (GLint) sampObj->MaxAnisotropy;
   1174       break;
   1175    case GL_TEXTURE_BORDER_COLOR:
   1176       params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
   1177       params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
   1178       params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
   1179       params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
   1180       break;
   1181    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
   1182       if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
   1183          goto invalid_pname;
   1184       *params = sampObj->CubeMapSeamless;
   1185       break;
   1186    case GL_TEXTURE_SRGB_DECODE_EXT:
   1187       if (!ctx->Extensions.EXT_texture_sRGB_decode)
   1188          goto invalid_pname;
   1189       *params = (GLenum) sampObj->sRGBDecode;
   1190       break;
   1191    default:
   1192       goto invalid_pname;
   1193    }
   1194    return;
   1195 
   1196 invalid_pname:
   1197    _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
   1198                _mesa_lookup_enum_by_nr(pname));
   1199 }
   1200 
   1201 
   1202 static void GLAPIENTRY
   1203 _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
   1204 {
   1205    struct gl_sampler_object *sampObj;
   1206    GET_CURRENT_CONTEXT(ctx);
   1207 
   1208    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
   1209    if (!sampObj) {
   1210       _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameterfv(sampler %u)",
   1211                   sampler);
   1212       return;
   1213    }
   1214 
   1215    switch (pname) {
   1216    case GL_TEXTURE_WRAP_S:
   1217       *params = (GLfloat) sampObj->WrapS;
   1218       break;
   1219    case GL_TEXTURE_WRAP_T:
   1220       *params = (GLfloat) sampObj->WrapT;
   1221       break;
   1222    case GL_TEXTURE_WRAP_R:
   1223       *params = (GLfloat) sampObj->WrapR;
   1224       break;
   1225    case GL_TEXTURE_MIN_FILTER:
   1226       *params = (GLfloat) sampObj->MinFilter;
   1227       break;
   1228    case GL_TEXTURE_MAG_FILTER:
   1229       *params = (GLfloat) sampObj->MagFilter;
   1230       break;
   1231    case GL_TEXTURE_MIN_LOD:
   1232       *params = sampObj->MinLod;
   1233       break;
   1234    case GL_TEXTURE_MAX_LOD:
   1235       *params = sampObj->MaxLod;
   1236       break;
   1237    case GL_TEXTURE_LOD_BIAS:
   1238       *params = sampObj->LodBias;
   1239       break;
   1240    case GL_TEXTURE_COMPARE_MODE:
   1241       if (!ctx->Extensions.ARB_shadow)
   1242          goto invalid_pname;
   1243       *params = (GLfloat) sampObj->CompareMode;
   1244       break;
   1245    case GL_TEXTURE_COMPARE_FUNC:
   1246       if (!ctx->Extensions.ARB_shadow)
   1247          goto invalid_pname;
   1248       *params = (GLfloat) sampObj->CompareFunc;
   1249       break;
   1250    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   1251       *params = sampObj->MaxAnisotropy;
   1252       break;
   1253    case GL_TEXTURE_BORDER_COLOR:
   1254       params[0] = sampObj->BorderColor.f[0];
   1255       params[1] = sampObj->BorderColor.f[1];
   1256       params[2] = sampObj->BorderColor.f[2];
   1257       params[3] = sampObj->BorderColor.f[3];
   1258       break;
   1259    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
   1260       if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
   1261          goto invalid_pname;
   1262       *params = (GLfloat) sampObj->CubeMapSeamless;
   1263       break;
   1264    case GL_TEXTURE_SRGB_DECODE_EXT:
   1265       if (!ctx->Extensions.EXT_texture_sRGB_decode)
   1266          goto invalid_pname;
   1267       *params = (GLfloat) sampObj->sRGBDecode;
   1268       break;
   1269    default:
   1270       goto invalid_pname;
   1271    }
   1272    return;
   1273 
   1274 invalid_pname:
   1275    _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
   1276                _mesa_lookup_enum_by_nr(pname));
   1277 }
   1278 
   1279 
   1280 static void GLAPIENTRY
   1281 _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
   1282 {
   1283    struct gl_sampler_object *sampObj;
   1284    GET_CURRENT_CONTEXT(ctx);
   1285 
   1286    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
   1287    if (!sampObj) {
   1288       _mesa_error(ctx, GL_INVALID_VALUE,
   1289                   "glGetSamplerParameterIiv(sampler %u)",
   1290                   sampler);
   1291       return;
   1292    }
   1293 
   1294    switch (pname) {
   1295    case GL_TEXTURE_WRAP_S:
   1296       *params = sampObj->WrapS;
   1297       break;
   1298    case GL_TEXTURE_WRAP_T:
   1299       *params = sampObj->WrapT;
   1300       break;
   1301    case GL_TEXTURE_WRAP_R:
   1302       *params = sampObj->WrapR;
   1303       break;
   1304    case GL_TEXTURE_MIN_FILTER:
   1305       *params = sampObj->MinFilter;
   1306       break;
   1307    case GL_TEXTURE_MAG_FILTER:
   1308       *params = sampObj->MagFilter;
   1309       break;
   1310    case GL_TEXTURE_MIN_LOD:
   1311       *params = (GLint) sampObj->MinLod;
   1312       break;
   1313    case GL_TEXTURE_MAX_LOD:
   1314       *params = (GLint) sampObj->MaxLod;
   1315       break;
   1316    case GL_TEXTURE_LOD_BIAS:
   1317       *params = (GLint) sampObj->LodBias;
   1318       break;
   1319    case GL_TEXTURE_COMPARE_MODE:
   1320       if (!ctx->Extensions.ARB_shadow)
   1321          goto invalid_pname;
   1322       *params = sampObj->CompareMode;
   1323       break;
   1324    case GL_TEXTURE_COMPARE_FUNC:
   1325       if (!ctx->Extensions.ARB_shadow)
   1326          goto invalid_pname;
   1327       *params = sampObj->CompareFunc;
   1328       break;
   1329    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   1330       *params = (GLint) sampObj->MaxAnisotropy;
   1331       break;
   1332    case GL_TEXTURE_BORDER_COLOR:
   1333       params[0] = sampObj->BorderColor.i[0];
   1334       params[1] = sampObj->BorderColor.i[1];
   1335       params[2] = sampObj->BorderColor.i[2];
   1336       params[3] = sampObj->BorderColor.i[3];
   1337       break;
   1338    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
   1339       if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
   1340          goto invalid_pname;
   1341       *params = sampObj->CubeMapSeamless;
   1342       break;
   1343    case GL_TEXTURE_SRGB_DECODE_EXT:
   1344       if (!ctx->Extensions.EXT_texture_sRGB_decode)
   1345          goto invalid_pname;
   1346       *params = (GLenum) sampObj->sRGBDecode;
   1347       break;
   1348    default:
   1349       goto invalid_pname;
   1350    }
   1351    return;
   1352 
   1353 invalid_pname:
   1354    _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
   1355                _mesa_lookup_enum_by_nr(pname));
   1356 }
   1357 
   1358 
   1359 static void GLAPIENTRY
   1360 _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
   1361 {
   1362    struct gl_sampler_object *sampObj;
   1363    GET_CURRENT_CONTEXT(ctx);
   1364 
   1365    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
   1366    if (!sampObj) {
   1367       _mesa_error(ctx, GL_INVALID_VALUE,
   1368                   "glGetSamplerParameterIuiv(sampler %u)",
   1369                   sampler);
   1370       return;
   1371    }
   1372 
   1373    switch (pname) {
   1374    case GL_TEXTURE_WRAP_S:
   1375       *params = sampObj->WrapS;
   1376       break;
   1377    case GL_TEXTURE_WRAP_T:
   1378       *params = sampObj->WrapT;
   1379       break;
   1380    case GL_TEXTURE_WRAP_R:
   1381       *params = sampObj->WrapR;
   1382       break;
   1383    case GL_TEXTURE_MIN_FILTER:
   1384       *params = sampObj->MinFilter;
   1385       break;
   1386    case GL_TEXTURE_MAG_FILTER:
   1387       *params = sampObj->MagFilter;
   1388       break;
   1389    case GL_TEXTURE_MIN_LOD:
   1390       *params = (GLuint) sampObj->MinLod;
   1391       break;
   1392    case GL_TEXTURE_MAX_LOD:
   1393       *params = (GLuint) sampObj->MaxLod;
   1394       break;
   1395    case GL_TEXTURE_LOD_BIAS:
   1396       *params = (GLuint) sampObj->LodBias;
   1397       break;
   1398    case GL_TEXTURE_COMPARE_MODE:
   1399       if (!ctx->Extensions.ARB_shadow)
   1400          goto invalid_pname;
   1401       *params = sampObj->CompareMode;
   1402       break;
   1403    case GL_TEXTURE_COMPARE_FUNC:
   1404       if (!ctx->Extensions.ARB_shadow)
   1405          goto invalid_pname;
   1406       *params = sampObj->CompareFunc;
   1407       break;
   1408    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   1409       *params = (GLuint) sampObj->MaxAnisotropy;
   1410       break;
   1411    case GL_TEXTURE_BORDER_COLOR:
   1412       params[0] = sampObj->BorderColor.ui[0];
   1413       params[1] = sampObj->BorderColor.ui[1];
   1414       params[2] = sampObj->BorderColor.ui[2];
   1415       params[3] = sampObj->BorderColor.ui[3];
   1416       break;
   1417    case GL_TEXTURE_CUBE_MAP_SEAMLESS:
   1418       if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
   1419          goto invalid_pname;
   1420       *params = sampObj->CubeMapSeamless;
   1421       break;
   1422    case GL_TEXTURE_SRGB_DECODE_EXT:
   1423       if (!ctx->Extensions.EXT_texture_sRGB_decode)
   1424          goto invalid_pname;
   1425       *params = (GLenum) sampObj->sRGBDecode;
   1426       break;
   1427    default:
   1428       goto invalid_pname;
   1429    }
   1430    return;
   1431 
   1432 invalid_pname:
   1433    _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
   1434                _mesa_lookup_enum_by_nr(pname));
   1435 }
   1436 
   1437 
   1438 void
   1439 _mesa_init_sampler_object_functions(struct dd_function_table *driver)
   1440 {
   1441    driver->NewSamplerObject = _mesa_new_sampler_object;
   1442    driver->DeleteSamplerObject = _mesa_delete_sampler_object;
   1443 }
   1444 
   1445 
   1446 void
   1447 _mesa_init_sampler_object_dispatch(struct _glapi_table *disp)
   1448 {
   1449    SET_GenSamplers(disp, _mesa_GenSamplers);
   1450    SET_DeleteSamplers(disp, _mesa_DeleteSamplers);
   1451    SET_IsSampler(disp, _mesa_IsSampler);
   1452    SET_BindSampler(disp, _mesa_BindSampler);
   1453    SET_SamplerParameteri(disp, _mesa_SamplerParameteri);
   1454    SET_SamplerParameterf(disp, _mesa_SamplerParameterf);
   1455    SET_SamplerParameteriv(disp, _mesa_SamplerParameteriv);
   1456    SET_SamplerParameterfv(disp, _mesa_SamplerParameterfv);
   1457    SET_SamplerParameterIiv(disp, _mesa_SamplerParameterIiv);
   1458    SET_SamplerParameterIuiv(disp, _mesa_SamplerParameterIuiv);
   1459    SET_GetSamplerParameteriv(disp, _mesa_GetSamplerParameteriv);
   1460    SET_GetSamplerParameterfv(disp, _mesa_GetSamplerParameterfv);
   1461    SET_GetSamplerParameterIiv(disp, _mesa_GetSamplerParameterIiv);
   1462    SET_GetSamplerParameterIuiv(disp, _mesa_GetSamplerParameterIuiv);
   1463 }
   1464