mesa: add glTextureParameteri/iv/f/fvEXT
[mesa.git] / src / mesa / main / samplerobj.c
index 14f2b45fe1d5aa79e40008a17d08852f8909002a..6656cf5022ac9249ab8e643804801e9a54be305d 100644 (file)
 
 #include "main/glheader.h"
 #include "main/context.h"
-#include "main/dispatch.h"
 #include "main/enums.h"
 #include "main/hash.h"
 #include "main/macros.h"
 #include "main/mtypes.h"
 #include "main/samplerobj.h"
+#include "main/texturebindless.h"
 
 
 struct gl_sampler_object *
@@ -50,30 +50,6 @@ _mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name)
          _mesa_HashLookup(ctx->Shared->SamplerObjects, name);
 }
 
-static struct gl_sampler_object *
-_mesa_lookup_samplerobj_locked(struct gl_context *ctx, GLuint name)
-{
-   if (name == 0)
-      return NULL;
-   else
-      return (struct gl_sampler_object *)
-         _mesa_HashLookupLocked(ctx->Shared->SamplerObjects, name);
-}
-
-static inline void
-begin_samplerobj_lookups(struct gl_context *ctx)
-{
-   _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
-}
-
-
-static inline void
-end_samplerobj_lookups(struct gl_context *ctx)
-{
-   _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
-}
-
-
 static inline struct gl_sampler_object *
 lookup_samplerobj_locked(struct gl_context *ctx, GLuint name)
 {
@@ -85,7 +61,8 @@ static void
 delete_sampler_object(struct gl_context *ctx,
                       struct gl_sampler_object *sampObj)
 {
-   mtx_destroy(&sampObj->Mutex);
+   _mesa_delete_sampler_handles(ctx, sampObj);
+   simple_mtx_destroy(&sampObj->Mutex);
    free(sampObj->Label);
    free(sampObj);
 }
@@ -105,11 +82,11 @@ _mesa_reference_sampler_object_(struct gl_context *ctx,
       GLboolean deleteFlag = GL_FALSE;
       struct gl_sampler_object *oldSamp = *ptr;
 
-      mtx_lock(&oldSamp->Mutex);
+      simple_mtx_lock(&oldSamp->Mutex);
       assert(oldSamp->RefCount > 0);
       oldSamp->RefCount--;
       deleteFlag = (oldSamp->RefCount == 0);
-      mtx_unlock(&oldSamp->Mutex);
+      simple_mtx_unlock(&oldSamp->Mutex);
 
       if (deleteFlag)
          delete_sampler_object(ctx, oldSamp);
@@ -120,18 +97,12 @@ _mesa_reference_sampler_object_(struct gl_context *ctx,
 
    if (samp) {
       /* reference new sampler */
-      mtx_lock(&samp->Mutex);
-      if (samp->RefCount == 0) {
-         /* this sampler's being deleted (look just above) */
-         /* Not sure this can every really happen.  Warn if it does. */
-         _mesa_problem(NULL, "referencing deleted sampler object");
-         *ptr = NULL;
-      }
-      else {
-         samp->RefCount++;
-         *ptr = samp;
-      }
-      mtx_unlock(&samp->Mutex);
+      simple_mtx_lock(&samp->Mutex);
+      assert(samp->RefCount > 0);
+
+      samp->RefCount++;
+      *ptr = samp;
+      simple_mtx_unlock(&samp->Mutex);
    }
 }
 
@@ -142,7 +113,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx,
 static void
 _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
 {
-   mtx_init(&sampObj->Mutex, mtx_plain);
+   simple_mtx_init(&sampObj->Mutex, mtx_plain);
    sampObj->Name = name;
    sampObj->RefCount = 1;
    sampObj->WrapS = GL_REPEAT;
@@ -162,6 +133,10 @@ _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
    sampObj->CompareFunc = GL_LEQUAL;
    sampObj->sRGBDecode = GL_DECODE_EXT;
    sampObj->CubeMapSeamless = GL_FALSE;
+   sampObj->HandleAllocated = GL_FALSE;
+
+   /* GL_ARB_bindless_texture */
+   _mesa_init_sampler_handles(sampObj);
 }
 
 /**
@@ -184,14 +159,6 @@ create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers,
    GLuint first;
    GLint i;
 
-   if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "%s(%d)\n", caller, count);
-
-   if (count < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller);
-      return;
-   }
-
    if (!samplers)
       return;
 
@@ -201,56 +168,86 @@ create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers,
 
    /* Insert the ID and pointer to new sampler object into hash table */
    for (i = 0; i < count; i++) {
-      struct gl_sampler_object *sampObj =
-         ctx->Driver.NewSamplerObject(ctx, first + i);
-      _mesa_HashInsertLocked(ctx->Shared->SamplerObjects, first + i, sampObj);
-      samplers[i] = first + i;
+      struct gl_sampler_object *sampObj;
+      GLuint name = first + i;
+
+      sampObj = ctx->Driver.NewSamplerObject(ctx, name);
+      if (!sampObj) {
+         _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
+         return;
+      }
+
+      _mesa_HashInsertLocked(ctx->Shared->SamplerObjects, name, sampObj);
+      samplers[i] = name;
    }
 
    _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
 }
 
+static void
+create_samplers_err(struct gl_context *ctx, GLsizei count, GLuint *samplers,
+                    const char *caller)
+{
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "%s(%d)\n", caller, count);
+
+   if (count < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller);
+      return;
+   }
+
+   create_samplers(ctx, count, samplers, caller);
+}
+
 void GLAPIENTRY
-_mesa_GenSamplers(GLsizei count, GLuint *samplers)
+_mesa_GenSamplers_no_error(GLsizei count, GLuint *samplers)
 {
    GET_CURRENT_CONTEXT(ctx);
    create_samplers(ctx, count, samplers, "glGenSamplers");
 }
 
 void GLAPIENTRY
-_mesa_CreateSamplers(GLsizei count, GLuint *samplers)
+_mesa_GenSamplers(GLsizei count, GLuint *samplers)
 {
    GET_CURRENT_CONTEXT(ctx);
-   create_samplers(ctx, count, samplers, "glCreateSamplers");
+   create_samplers_err(ctx, count, samplers, "glGenSamplers");
 }
 
+void GLAPIENTRY
+_mesa_CreateSamplers_no_error(GLsizei count, GLuint *samplers)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   create_samplers(ctx, count, samplers, "glCreateSamplers");
+}
 
 void GLAPIENTRY
-_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
+_mesa_CreateSamplers(GLsizei count, GLuint *samplers)
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLsizei i;
+   create_samplers_err(ctx, count, samplers, "glCreateSamplers");
+}
 
-   FLUSH_VERTICES(ctx, 0);
 
-   if (count < 0) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
-      return;
-   }
+static void
+delete_samplers(struct gl_context *ctx, GLsizei count, const GLuint *samplers)
+{
+   FLUSH_VERTICES(ctx, 0);
 
    _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
 
-   for (i = 0; i < count; i++) {
+   for (GLsizei i = 0; i < count; i++) {
       if (samplers[i]) {
          GLuint j;
          struct gl_sampler_object *sampObj =
-            _mesa_lookup_samplerobj_locked(ctx, samplers[i]);
+            lookup_samplerobj_locked(ctx, samplers[i]);
    
          if (sampObj) {
             /* If the sampler is currently bound, unbind it. */
             for (j = 0; j < ctx->Const.MaxCombinedTextureImageUnits; j++) {
                if (ctx->Texture.Unit[j].Sampler == sampObj) {
-                  FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+                  FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
                   _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[j].Sampler, NULL);
                }
             }
@@ -267,20 +264,36 @@ _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
 }
 
 
+void GLAPIENTRY
+_mesa_DeleteSamplers_no_error(GLsizei count, const GLuint *samplers)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   delete_samplers(ctx, count, samplers);
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (count < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
+      return;
+   }
+
+   delete_samplers(ctx, count, samplers);
+}
+
+
 GLboolean GLAPIENTRY
 _mesa_IsSampler(GLuint sampler)
 {
-   struct gl_sampler_object *sampObj;
    GET_CURRENT_CONTEXT(ctx);
 
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
 
-   if (sampler == 0)
-      return GL_FALSE;
-
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-
-   return sampObj != NULL;
+   return _mesa_lookup_samplerobj(ctx, sampler) != NULL;
 }
 
 void
@@ -288,34 +301,27 @@ _mesa_bind_sampler(struct gl_context *ctx, GLuint unit,
                    struct gl_sampler_object *sampObj)
 {
    if (ctx->Texture.Unit[unit].Sampler != sampObj) {
-      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+      FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
    }
 
    _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler,
                                   sampObj);
 }
 
-void GLAPIENTRY
-_mesa_BindSampler(GLuint unit, GLuint sampler)
+static ALWAYS_INLINE void
+bind_sampler(struct gl_context *ctx, GLuint unit, GLuint sampler, bool no_error)
 {
    struct gl_sampler_object *sampObj;
-   GET_CURRENT_CONTEXT(ctx);
-
-   if (unit >= ctx->Const.MaxCombinedTextureImageUnits) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
-      return;
-   }
 
    if (sampler == 0) {
       /* Use the default sampler object, the one contained in the texture
        * object.
        */
       sampObj = NULL;
-   }
-   else {
+   } else {
       /* user-defined sampler object */
       sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-      if (!sampObj) {
+      if (!no_error && !sampObj) {
          _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)");
          return;
       }
@@ -325,27 +331,33 @@ _mesa_BindSampler(GLuint unit, GLuint sampler)
    _mesa_bind_sampler(ctx, unit, sampObj);
 }
 
+void GLAPIENTRY
+_mesa_BindSampler_no_error(GLuint unit, GLuint sampler)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   bind_sampler(ctx, unit, sampler, true);
+}
 
 void GLAPIENTRY
-_mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
+_mesa_BindSampler(GLuint unit, GLuint sampler)
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLint i;
 
-   /* The ARB_multi_bind spec says:
-    *
-    *   "An INVALID_OPERATION error is generated if <first> + <count> is
-    *    greater than the number of texture image units supported by
-    *    the implementation."
-    */
-   if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glBindSamplers(first=%u + count=%d > the value of "
-                  "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
-                  first, count, ctx->Const.MaxCombinedTextureImageUnits);
+   if (unit >= ctx->Const.MaxCombinedTextureImageUnits) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
       return;
    }
 
+   bind_sampler(ctx, unit, sampler, false);
+}
+
+
+static ALWAYS_INLINE void
+bind_samplers(struct gl_context *ctx, GLuint first, GLsizei count,
+              const GLuint *samplers, bool no_error)
+{
+   GLsizei i;
+
    FLUSH_VERTICES(ctx, 0);
 
    if (samplers) {
@@ -368,7 +380,7 @@ _mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
        *       their parameters are valid and no other error occurs."
        */
 
-      begin_samplerobj_lookups(ctx);
+      _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
 
       for (i = 0; i < count; i++) {
          const GLuint unit = first + i;
@@ -388,7 +400,7 @@ _mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
              *     in <samplers> is not zero or the name of an existing
              *     sampler object (per binding)."
              */
-            if (!sampObj) {
+            if (!no_error && !sampObj) {
                _mesa_error(ctx, GL_INVALID_OPERATION,
                            "glBindSamplers(samplers[%d]=%u is not zero or "
                            "the name of an existing sampler object)",
@@ -404,11 +416,11 @@ _mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
             _mesa_reference_sampler_object(ctx,
                                            &ctx->Texture.Unit[unit].Sampler,
                                            sampObj);
-            ctx->NewState |= _NEW_TEXTURE;
+            ctx->NewState |= _NEW_TEXTURE_OBJECT;
          }
       }
 
-      end_samplerobj_lookups(ctx);
+      _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
    } else {
       /* Unbind all samplers in the range <first> through <first>+<count>-1 */
       for (i = 0; i < count; i++) {
@@ -418,13 +430,44 @@ _mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
             _mesa_reference_sampler_object(ctx,
                                            &ctx->Texture.Unit[unit].Sampler,
                                            NULL);
-            ctx->NewState |= _NEW_TEXTURE;
+            ctx->NewState |= _NEW_TEXTURE_OBJECT;
          }
       }
    }
 }
 
 
+void GLAPIENTRY
+_mesa_BindSamplers_no_error(GLuint first, GLsizei count, const GLuint *samplers)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   bind_samplers(ctx, first, count, samplers, true);
+}
+
+
+void GLAPIENTRY
+_mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* The ARB_multi_bind spec says:
+    *
+    *   "An INVALID_OPERATION error is generated if <first> + <count> is
+    *    greater than the number of texture image units supported by
+    *    the implementation."
+    */
+   if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glBindSamplers(first=%u + count=%d > the value of "
+                  "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
+                  first, count, ctx->Const.MaxCombinedTextureImageUnits);
+      return;
+   }
+
+   bind_samplers(ctx, first, count, samplers, false);
+}
+
+
 /**
  * Check if a coordinate wrap mode is legal.
  * \return GL_TRUE if legal, GL_FALSE otherwise
@@ -460,7 +503,7 @@ validate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap)
 static inline void
 flush(struct gl_context *ctx)
 {
-   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+   FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
 }
 
 void
@@ -789,36 +832,70 @@ set_sampler_srgb_decode(struct gl_context *ctx,
    if (samp->sRGBDecode == param)
       return GL_FALSE;
 
+   /* The EXT_texture_sRGB_decode spec says:
+    *
+    *    "INVALID_ENUM is generated if the <pname> parameter of
+    *     TexParameter[i,f,Ii,Iui][v][EXT],
+    *     MultiTexParameter[i,f,Ii,Iui][v]EXT,
+    *     TextureParameter[i,f,Ii,Iui][v]EXT, SamplerParameter[i,f,Ii,Iui][v]
+    *     is TEXTURE_SRGB_DECODE_EXT when the <param> parameter is not one of
+    *     DECODE_EXT or SKIP_DECODE_EXT.
+    *
+    * Returning INVALID_PARAM makes that happen.
+    */
    if (param != GL_DECODE_EXT && param != GL_SKIP_DECODE_EXT)
-      return INVALID_VALUE;
+      return INVALID_PARAM;
 
    flush(ctx);
    samp->sRGBDecode = param;
    return GL_TRUE;
 }
 
-void GLAPIENTRY
-_mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+static struct gl_sampler_object *
+sampler_parameter_error_check(struct gl_context *ctx, GLuint sampler,
+                              bool get, const char *name)
 {
    struct gl_sampler_object *sampObj;
-   GLuint res;
-   GET_CURRENT_CONTEXT(ctx);
 
    sampObj = _mesa_lookup_samplerobj(ctx, sampler);
    if (!sampObj) {
-      /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
+      /* OpenGL 4.5 spec, section "8.2 Sampler Objects", page 176 of the PDF
+       * states:
        *
-       *     "An INVALID_OPERATION error is generated if sampler is not the name
-       *     of a sampler object previously returned from a call to GenSamplers."
+       *    "An INVALID_OPERATION error is generated if sampler is not the name
+       *    of a sampler object previously returned from a call to
+       *    GenSamplers."
+       */
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid sampler)", name);
+      return NULL;
+   }
+
+   if (!get && sampObj->HandleAllocated) {
+      /* The ARB_bindless_texture spec says:
        *
-       * In desktop GL, an GL_INVALID_VALUE is returned instead.
+       * "The error INVALID_OPERATION is generated by SamplerParameter* if
+       *  <sampler> identifies a sampler object referenced by one or more
+       *  texture handles."
        */
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glSamplerParameteri(sampler %u)", sampler);
-      return;
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable sampler)", name);
+      return NULL;
    }
 
+   return sampObj;
+}
+
+void GLAPIENTRY
+_mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+   struct gl_sampler_object *sampObj;
+   GLuint res;
+   GET_CURRENT_CONTEXT(ctx);
+
+   sampObj = sampler_parameter_error_check(ctx, sampler, false,
+                                           "glSamplerParameteri");
+   if (!sampObj)
+      return;
+
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
       res = set_sampler_wrap_s(ctx, sampObj, param);
@@ -897,20 +974,10 @@ _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
    GLuint res;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
-       *
-       *     "An INVALID_OPERATION error is generated if sampler is not the name
-       *     of a sampler object previously returned from a call to GenSamplers."
-       *
-       * In desktop GL, an GL_INVALID_VALUE is returned instead.
-       */
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glSamplerParameterf(sampler %u)", sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, false,
+                                           "glSamplerParameterf");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
@@ -989,20 +1056,10 @@ _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
    GLuint res;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
-       *
-       *     "An INVALID_OPERATION error is generated if sampler is not the name
-       *     of a sampler object previously returned from a call to GenSamplers."
-       *
-       * In desktop GL, an GL_INVALID_VALUE is returned instead.
-       */
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glSamplerParameteriv(sampler %u)", sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, false,
+                                           "glSamplerParameteriv");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
@@ -1089,20 +1146,10 @@ _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
    GLuint res;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
-       *
-       *     "An INVALID_OPERATION error is generated if sampler is not the name
-       *     of a sampler object previously returned from a call to GenSamplers."
-       *
-       * In desktop GL, an GL_INVALID_VALUE is returned instead.
-       */
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glSamplerParameterfv(sampler %u)", sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, false,
+                                           "glSamplerParameterfv");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
@@ -1182,13 +1229,10 @@ _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
    GLuint res;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glSamplerParameterIiv(sampler %u)", sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, false,
+                                           "glSamplerParameterIiv");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
@@ -1269,13 +1313,10 @@ _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
    GLuint res;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glSamplerParameterIuiv(sampler %u)", sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, false,
+                                           "glSamplerParameterIuiv");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
@@ -1355,20 +1396,10 @@ _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
    struct gl_sampler_object *sampObj;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
-       *
-       *     "An INVALID_OPERATION error is generated if sampler is not the name
-       *     of a sampler object previously returned from a call to GenSamplers."
-       *
-       * In desktop GL, an GL_INVALID_VALUE is returned instead.
-       */
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glGetSamplerParameteriv(sampler %u)", sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, true,
+                                           "glGetSamplerParameteriv");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
@@ -1449,20 +1480,10 @@ _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
    struct gl_sampler_object *sampObj;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states:
-       *
-       *     "An INVALID_OPERATION error is generated if sampler is not the name
-       *     of a sampler object previously returned from a call to GenSamplers."
-       *
-       * In desktop GL, an GL_INVALID_VALUE is returned instead.
-       */
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glGetSamplerParameterfv(sampler %u)", sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, true,
+                                           "glGetSamplerParameterfv");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
@@ -1531,14 +1552,10 @@ _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
    struct gl_sampler_object *sampObj;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glGetSamplerParameterIiv(sampler %u)",
-                  sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, true,
+                                           "glGetSamplerParameterIiv");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S:
@@ -1607,14 +1624,10 @@ _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
    struct gl_sampler_object *sampObj;
    GET_CURRENT_CONTEXT(ctx);
 
-   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-   if (!sampObj) {
-      _mesa_error(ctx, (_mesa_is_gles(ctx) ?
-                        GL_INVALID_OPERATION : GL_INVALID_VALUE),
-                  "glGetSamplerParameterIuiv(sampler %u)",
-                  sampler);
+   sampObj = sampler_parameter_error_check(ctx, sampler, true,
+                                           "glGetSamplerParameterIuiv");
+   if (!sampObj)
       return;
-   }
 
    switch (pname) {
    case GL_TEXTURE_WRAP_S: