Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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