X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fsamplerobj.c;h=6656cf5022ac9249ab8e643804801e9a54be305d;hb=360ef827651bdc0da4b8ac251f3f048b1cab60d7;hp=773bebf264f16ba9477bf992a2354bcb9052dd49;hpb=7f962c5ef30f4710e18fc7e627822257a4c89cd9;p=mesa.git diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c index 773bebf264f..6656cf5022a 100644 --- a/src/mesa/main/samplerobj.c +++ b/src/mesa/main/samplerobj.c @@ -16,9 +16,10 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ @@ -31,16 +32,15 @@ #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/mfeatures.h" #include "main/mtypes.h" #include "main/samplerobj.h" +#include "main/texturebindless.h" -static struct gl_sampler_object * +struct gl_sampler_object * _mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name) { if (name == 0) @@ -50,6 +50,22 @@ _mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name) _mesa_HashLookup(ctx->Shared->SamplerObjects, name); } +static inline struct gl_sampler_object * +lookup_samplerobj_locked(struct gl_context *ctx, GLuint name) +{ + return (struct gl_sampler_object *) + _mesa_HashLookupLocked(ctx->Shared->SamplerObjects, name); +} + +static void +delete_sampler_object(struct gl_context *ctx, + struct gl_sampler_object *sampObj) +{ + _mesa_delete_sampler_handles(ctx, sampObj); + simple_mtx_destroy(&sampObj->Mutex); + free(sampObj->Label); + free(sampObj); +} /** * Handle reference counting. @@ -66,43 +82,27 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, GLboolean deleteFlag = GL_FALSE; struct gl_sampler_object *oldSamp = *ptr; - /*_glthread_LOCK_MUTEX(oldSamp->Mutex);*/ - ASSERT(oldSamp->RefCount > 0); + simple_mtx_lock(&oldSamp->Mutex); + assert(oldSamp->RefCount > 0); oldSamp->RefCount--; -#if 0 - printf("SamplerObj %p %d DECR to %d\n", - (void *) oldSamp, oldSamp->Name, oldSamp->RefCount); -#endif deleteFlag = (oldSamp->RefCount == 0); - /*_glthread_UNLOCK_MUTEX(oldSamp->Mutex);*/ + simple_mtx_unlock(&oldSamp->Mutex); - if (deleteFlag) { - ASSERT(ctx->Driver.DeleteSamplerObject); - ctx->Driver.DeleteSamplerObject(ctx, oldSamp); - } + if (deleteFlag) + delete_sampler_object(ctx, oldSamp); *ptr = NULL; } - ASSERT(!*ptr); + assert(!*ptr); if (samp) { /* reference new sampler */ - /*_glthread_LOCK_MUTEX(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++; -#if 0 - printf("SamplerObj %p %d INCR to %d\n", - (void *) samp, samp->Name, samp->RefCount); -#endif - *ptr = samp; - } - /*_glthread_UNLOCK_MUTEX(samp->Mutex);*/ + simple_mtx_lock(&samp->Mutex); + assert(samp->RefCount > 0); + + samp->RefCount++; + *ptr = samp; + simple_mtx_unlock(&samp->Mutex); } } @@ -113,6 +113,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, static void _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name) { + simple_mtx_init(&sampObj->Mutex, mtx_plain); sampObj->Name = name; sampObj->RefCount = 1; sampObj->WrapS = GL_REPEAT; @@ -132,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); } /** @@ -147,133 +152,319 @@ _mesa_new_sampler_object(struct gl_context *ctx, GLuint name) return sampObj; } - -/** - * Fallback for ctx->Driver.DeleteSamplerObject(); - */ static void -_mesa_delete_sampler_object(struct gl_context *ctx, - struct gl_sampler_object *sampObj) -{ - free(sampObj); -} - - -void GLAPIENTRY -_mesa_GenSamplers(GLsizei count, GLuint *samplers) +create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers, + const char *caller) { - GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; - ASSERT_OUTSIDE_BEGIN_END(ctx); + if (!samplers) + return; + + _mesa_HashLockMutex(ctx->Shared->SamplerObjects); + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count); + + /* Insert the ID and pointer to new sampler object into hash table */ + for (i = 0; i < count; 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, "glGenSamplers(%d)\n", count); + _mesa_debug(ctx, "%s(%d)\n", caller, count); if (count < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller); return; } - if (!samplers) - return; + create_samplers(ctx, count, samplers, caller); +} - first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count); +void GLAPIENTRY +_mesa_GenSamplers_no_error(GLsizei count, GLuint *samplers) +{ + GET_CURRENT_CONTEXT(ctx); + create_samplers(ctx, count, samplers, "glGenSamplers"); +} - /* 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_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj); - samplers[i] = first + i; - } +void GLAPIENTRY +_mesa_GenSamplers(GLsizei count, GLuint *samplers) +{ + GET_CURRENT_CONTEXT(ctx); + 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"); +} - ASSERT_OUTSIDE_BEGIN_END(ctx); - 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); - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _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(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_OBJECT); + _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[j].Sampler, NULL); + } + } + /* The ID is immediately freed for re-use */ - _mesa_HashRemove(ctx->Shared->SamplerObjects, samplers[i]); + _mesa_HashRemoveLocked(ctx->Shared->SamplerObjects, samplers[i]); /* But the object exists until its reference count goes to zero */ _mesa_reference_sampler_object(ctx, &sampObj, NULL); } } } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); } -GLboolean GLAPIENTRY -_mesa_IsSampler(GLuint sampler) +void GLAPIENTRY +_mesa_DeleteSamplers_no_error(GLsizei count, const GLuint *samplers) { - struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + delete_samplers(ctx, count, samplers); +} - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - if (sampler == 0) - return GL_FALSE; +void GLAPIENTRY +_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers) +{ + GET_CURRENT_CONTEXT(ctx); - sampObj = _mesa_lookup_samplerobj(ctx, sampler); + if (count < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)"); + return; + } - return sampObj != NULL; + delete_samplers(ctx, count, samplers); } -void GLAPIENTRY -_mesa_BindSampler(GLuint unit, GLuint sampler) +GLboolean GLAPIENTRY +_mesa_IsSampler(GLuint sampler) { - 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; + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + return _mesa_lookup_samplerobj(ctx, sampler) != NULL; +} + +void +_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_OBJECT); } + _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler, + sampObj); +} + +static ALWAYS_INLINE void +bind_sampler(struct gl_context *ctx, GLuint unit, GLuint sampler, bool no_error) +{ + struct gl_sampler_object *sampObj; + 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; } } - if (ctx->Texture.Unit[unit].Sampler != sampObj) { - FLUSH_VERTICES(ctx, _NEW_TEXTURE); + /* bind new 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_BindSampler(GLuint unit, GLuint sampler) +{ + GET_CURRENT_CONTEXT(ctx); + + if (unit >= ctx->Const.MaxCombinedTextureImageUnits) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit); + return; } - /* bind new sampler */ - _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler, - sampObj); + 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) { + /* Note that the error semantics for multi-bind commands differ from + * those of other GL commands. + * + * The Issues section in the ARB_multi_bind spec says: + * + * "(11) Typically, OpenGL specifies that if an error is generated by + * a command, that command has no effect. This is somewhat + * unfortunate for multi-bind commands, because it would require + * a first pass to scan the entire list of bound objects for + * errors and then a second pass to actually perform the + * bindings. Should we have different error semantics? + * + * RESOLVED: Yes. In this specification, when the parameters for + * one of the binding points are invalid, that binding + * point is not updated and an error will be generated. However, + * other binding points in the same command will be updated if + * their parameters are valid and no other error occurs." + */ + + _mesa_HashLockMutex(ctx->Shared->SamplerObjects); + + for (i = 0; i < count; i++) { + const GLuint unit = first + i; + struct gl_sampler_object * const currentSampler = + ctx->Texture.Unit[unit].Sampler; + struct gl_sampler_object *sampObj; + + if (samplers[i] != 0) { + if (currentSampler && currentSampler->Name == samplers[i]) + sampObj = currentSampler; + else + sampObj = lookup_samplerobj_locked(ctx, samplers[i]); + + /* The ARB_multi_bind spec says: + * + * "An INVALID_OPERATION error is generated if any value + * in is not zero or the name of an existing + * sampler object (per binding)." + */ + 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)", + i, samplers[i]); + continue; + } + } else { + sampObj = NULL; + } + + /* Bind the new sampler */ + if (sampObj != currentSampler) { + _mesa_reference_sampler_object(ctx, + &ctx->Texture.Unit[unit].Sampler, + sampObj); + ctx->NewState |= _NEW_TEXTURE_OBJECT; + } + } + + _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); + } else { + /* Unbind all samplers in the range through +-1 */ + for (i = 0; i < count; i++) { + const GLuint unit = first + i; + + if (ctx->Texture.Unit[unit].Sampler) { + _mesa_reference_sampler_object(ctx, + &ctx->Texture.Unit[unit].Sampler, + NULL); + 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 + 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); } @@ -297,7 +488,7 @@ validate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap) case GL_MIRROR_CLAMP_EXT: return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp; case GL_MIRROR_CLAMP_TO_EDGE_EXT: - return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp; + return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp || e->ARB_texture_mirror_clamp_to_edge; case GL_MIRROR_CLAMP_TO_BORDER_EXT: return e->EXT_texture_mirror_clamp; default: @@ -312,9 +503,25 @@ 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 +_mesa_set_sampler_wrap(struct gl_context *ctx, struct gl_sampler_object *samp, + GLenum s, GLenum t, GLenum r) +{ + assert(validate_texture_wrap_mode(ctx, s)); + assert(validate_texture_wrap_mode(ctx, t)); + assert(validate_texture_wrap_mode(ctx, r)); + + if (samp->WrapS == s && samp->WrapT == t && samp->WrapR == r) + return; + + flush(ctx); + samp->WrapS = s; + samp->WrapT = t; + samp->WrapR = r; +} #define INVALID_PARAM 0x100 #define INVALID_PNAME 0x101 @@ -364,6 +571,27 @@ set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp, return INVALID_PARAM; } +void +_mesa_set_sampler_filters(struct gl_context *ctx, + struct gl_sampler_object *samp, + GLenum min_filter, GLenum mag_filter) +{ + assert(min_filter == GL_NEAREST || + min_filter == GL_LINEAR || + min_filter == GL_NEAREST_MIPMAP_NEAREST || + min_filter == GL_LINEAR_MIPMAP_NEAREST || + min_filter == GL_NEAREST_MIPMAP_LINEAR || + min_filter == GL_LINEAR_MIPMAP_LINEAR); + assert(mag_filter == GL_NEAREST || + mag_filter == GL_LINEAR); + + if (samp->MinFilter == min_filter && samp->MagFilter == mag_filter) + return; + + flush(ctx); + samp->MinFilter = min_filter; + samp->MagFilter = mag_filter; +} static GLuint set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp, @@ -492,8 +720,12 @@ static GLuint set_sampler_compare_mode(struct gl_context *ctx, struct gl_sampler_object *samp, GLint param) { + /* If GL_ARB_shadow is not supported, don't report an error. The + * sampler object extension spec isn't clear on this extension interaction. + * Silences errors with Wine on older GPUs such as R200. + */ if (!ctx->Extensions.ARB_shadow) - return INVALID_PNAME; + return GL_FALSE; if (samp->CompareMode == param) return GL_FALSE; @@ -513,8 +745,12 @@ static GLuint set_sampler_compare_func(struct gl_context *ctx, struct gl_sampler_object *samp, GLint param) { + /* If GL_ARB_shadow is not supported, don't report an error. The + * sampler object extension spec isn't clear on this extension interaction. + * Silences errors with Wine on older GPUs such as R200. + */ if (!ctx->Extensions.ARB_shadow) - return INVALID_PNAME; + return GL_FALSE; if (samp->CompareFunc == param) return GL_FALSE; @@ -522,21 +758,15 @@ set_sampler_compare_func(struct gl_context *ctx, switch (param) { case GL_LEQUAL: case GL_GEQUAL: - flush(ctx); - samp->CompareFunc = param; - return GL_TRUE; case GL_EQUAL: case GL_NOTEQUAL: case GL_LESS: case GL_GREATER: case GL_ALWAYS: case GL_NEVER: - if (ctx->Extensions.EXT_shadow_funcs) { - flush(ctx); - samp->CompareFunc = param; - return GL_TRUE; - } - /* fall-through */ + flush(ctx); + samp->CompareFunc = param; + return GL_TRUE; default: return INVALID_PARAM; } @@ -553,7 +783,7 @@ set_sampler_max_anisotropy(struct gl_context *ctx, if (samp->MaxAnisotropy == param) return GL_FALSE; - if (param < 1.0) + if (param < 1.0F) return INVALID_VALUE; flush(ctx); @@ -567,7 +797,8 @@ static GLuint set_sampler_cube_map_seamless(struct gl_context *ctx, struct gl_sampler_object *samp, GLboolean param) { - if (!ctx->Extensions.AMD_seamless_cubemap_per_texture) + if (!_mesa_is_desktop_gl(ctx) + || !ctx->Extensions.AMD_seamless_cubemap_per_texture) return INVALID_PNAME; if (samp->CubeMapSeamless == param) @@ -581,6 +812,16 @@ set_sampler_cube_map_seamless(struct gl_context *ctx, return GL_TRUE; } +void +_mesa_set_sampler_srgb_decode(struct gl_context *ctx, + struct gl_sampler_object *samp, GLenum param) +{ + assert(param == GL_DECODE_EXT || param == GL_SKIP_DECODE_EXT); + + flush(ctx); + samp->sRGBDecode = param; +} + static GLuint set_sampler_srgb_decode(struct gl_context *ctx, struct gl_sampler_object *samp, GLenum param) @@ -591,14 +832,58 @@ 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 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 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; } +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; + + sampObj = _mesa_lookup_samplerobj(ctx, sampler); + if (!sampObj) { + /* 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." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid sampler)", name); + return NULL; + } + + if (!get && sampObj->HandleAllocated) { + /* The ARB_bindless_texture spec says: + * + * "The error INVALID_OPERATION is generated by SamplerParameter* if + * identifies a sampler object referenced by one or more + * texture handles." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable sampler)", name); + return NULL; + } + + return sampObj; +} + void GLAPIENTRY _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) { @@ -606,14 +891,10 @@ _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) GLuint res; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)", - sampler); + sampObj = sampler_parameter_error_check(ctx, sampler, false, + "glSamplerParameteri"); + if (!sampObj) return; - } switch (pname) { case GL_TEXTURE_WRAP_S: @@ -670,7 +951,7 @@ _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n", @@ -693,14 +974,10 @@ _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) GLuint res; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -757,7 +1034,7 @@ _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n", @@ -779,14 +1056,10 @@ _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -851,7 +1124,7 @@ _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n", @@ -873,14 +1146,10 @@ _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params) GLuint res; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -938,7 +1207,7 @@ _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n", @@ -960,14 +1229,10 @@ _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -1025,7 +1290,7 @@ _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n", @@ -1048,14 +1313,10 @@ _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -1113,7 +1374,7 @@ _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params) break; case INVALID_PNAME: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); break; case INVALID_PARAM: _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n", @@ -1135,14 +1396,10 @@ _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -1161,26 +1418,34 @@ _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) *params = sampObj->MagFilter; break; case GL_TEXTURE_MIN_LOD: - *params = (GLint) sampObj->MinLod; + /* GL spec 'Data Conversions' section specifies that floating-point + * value in integer Get function is rounded to nearest integer + */ + *params = IROUND(sampObj->MinLod); break; case GL_TEXTURE_MAX_LOD: - *params = (GLint) sampObj->MaxLod; + /* GL spec 'Data Conversions' section specifies that floating-point + * value in integer Get function is rounded to nearest integer + */ + *params = IROUND(sampObj->MaxLod); break; case GL_TEXTURE_LOD_BIAS: - *params = (GLint) sampObj->LodBias; + /* GL spec 'Data Conversions' section specifies that floating-point + * value in integer Get function is rounded to nearest integer + */ + *params = IROUND(sampObj->LodBias); break; case GL_TEXTURE_COMPARE_MODE: - if (!ctx->Extensions.ARB_shadow) - goto invalid_pname; *params = sampObj->CompareMode; break; case GL_TEXTURE_COMPARE_FUNC: - if (!ctx->Extensions.ARB_shadow) - goto invalid_pname; *params = sampObj->CompareFunc; break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: - *params = (GLint) sampObj->MaxAnisotropy; + /* GL spec 'Data Conversions' section specifies that floating-point + * value in integer Get function is rounded to nearest integer + */ + *params = IROUND(sampObj->MaxAnisotropy); break; case GL_TEXTURE_BORDER_COLOR: params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]); @@ -1205,7 +1470,7 @@ _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1215,14 +1480,10 @@ _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -1250,13 +1511,9 @@ _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) *params = sampObj->LodBias; break; case GL_TEXTURE_COMPARE_MODE: - if (!ctx->Extensions.ARB_shadow) - goto invalid_pname; *params = (GLfloat) sampObj->CompareMode; break; case GL_TEXTURE_COMPARE_FUNC: - if (!ctx->Extensions.ARB_shadow) - goto invalid_pname; *params = (GLfloat) sampObj->CompareFunc; break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: @@ -1285,7 +1542,7 @@ _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1295,15 +1552,10 @@ _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -1331,13 +1583,9 @@ _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params) *params = (GLint) sampObj->LodBias; break; case GL_TEXTURE_COMPARE_MODE: - if (!ctx->Extensions.ARB_shadow) - goto invalid_pname; *params = sampObj->CompareMode; break; case GL_TEXTURE_COMPARE_FUNC: - if (!ctx->Extensions.ARB_shadow) - goto invalid_pname; *params = sampObj->CompareFunc; break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: @@ -1366,7 +1614,7 @@ _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params) invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1376,15 +1624,10 @@ _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - sampObj = _mesa_lookup_samplerobj(ctx, sampler); - if (!sampObj) { - _mesa_error(ctx, 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: @@ -1412,13 +1655,9 @@ _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params) *params = (GLuint) sampObj->LodBias; break; case GL_TEXTURE_COMPARE_MODE: - if (!ctx->Extensions.ARB_shadow) - goto invalid_pname; *params = sampObj->CompareMode; break; case GL_TEXTURE_COMPARE_FUNC: - if (!ctx->Extensions.ARB_shadow) - goto invalid_pname; *params = sampObj->CompareFunc; break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: @@ -1447,7 +1686,7 @@ _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params) invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + _mesa_enum_to_string(pname)); } @@ -1455,29 +1694,4 @@ void _mesa_init_sampler_object_functions(struct dd_function_table *driver) { driver->NewSamplerObject = _mesa_new_sampler_object; - driver->DeleteSamplerObject = _mesa_delete_sampler_object; -} - - -void -_mesa_init_sampler_object_dispatch(const struct gl_context *ctx, - struct _glapi_table *disp) -{ - SET_GenSamplers(disp, _mesa_GenSamplers); - SET_DeleteSamplers(disp, _mesa_DeleteSamplers); - SET_IsSampler(disp, _mesa_IsSampler); - SET_BindSampler(disp, _mesa_BindSampler); - SET_SamplerParameteri(disp, _mesa_SamplerParameteri); - SET_SamplerParameterf(disp, _mesa_SamplerParameterf); - SET_SamplerParameteriv(disp, _mesa_SamplerParameteriv); - SET_SamplerParameterfv(disp, _mesa_SamplerParameterfv); - SET_GetSamplerParameteriv(disp, _mesa_GetSamplerParameteriv); - SET_GetSamplerParameterfv(disp, _mesa_GetSamplerParameterfv); - - if (_mesa_is_desktop_gl(ctx)) { - SET_SamplerParameterIiv(disp, _mesa_SamplerParameterIiv); - SET_SamplerParameterIuiv(disp, _mesa_SamplerParameterIuiv); - SET_GetSamplerParameterIiv(disp, _mesa_GetSamplerParameterIiv); - SET_GetSamplerParameterIuiv(disp, _mesa_GetSamplerParameterIuiv); - } }