}
+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)
+{
+ return (struct gl_sampler_object *)
+ _mesa_HashLookupLocked(ctx->Shared->SamplerObjects, name);
+}
+
+
/**
* Handle reference counting.
*/
GLboolean deleteFlag = GL_FALSE;
struct gl_sampler_object *oldSamp = *ptr;
- /*_glthread_LOCK_MUTEX(oldSamp->Mutex);*/
- ASSERT(oldSamp->RefCount > 0);
+ /*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);*/
+ /*mtx_unlock(&oldSamp->Mutex);*/
if (deleteFlag) {
- ASSERT(ctx->Driver.DeleteSamplerObject);
+ assert(ctx->Driver.DeleteSamplerObject);
ctx->Driver.DeleteSamplerObject(ctx, oldSamp);
}
*ptr = NULL;
}
- ASSERT(!*ptr);
+ assert(!*ptr);
if (samp) {
/* reference new sampler */
- /*_glthread_LOCK_MUTEX(samp->Mutex);*/
+ /*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. */
#endif
*ptr = samp;
}
- /*_glthread_UNLOCK_MUTEX(samp->Mutex);*/
+ /*mtx_unlock(&samp->Mutex);*/
}
}
_mesa_delete_sampler_object(struct gl_context *ctx,
struct gl_sampler_object *sampObj)
{
+ free(sampObj->Label);
free(sampObj);
}
-
-void GLAPIENTRY
-_mesa_GenSamplers(GLsizei count, GLuint *samplers)
+static void
+create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers,
+ const char *caller)
{
- GET_CURRENT_CONTEXT(ctx);
GLuint first;
GLint i;
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;
}
}
}
+void GLAPIENTRY
+_mesa_GenSamplers(GLsizei count, GLuint *samplers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_samplers(ctx, count, samplers, "glGenSamplers");
+}
+
+void GLAPIENTRY
+_mesa_CreateSamplers(GLsizei count, GLuint *samplers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_samplers(ctx, count, samplers, "glCreateSamplers");
+}
+
void GLAPIENTRY
_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
return;
}
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ mtx_lock(&ctx->Shared->Mutex);
for (i = 0; i < count; i++) {
if (samplers[i]) {
}
}
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ mtx_unlock(&ctx->Shared->Mutex);
}
}
+void GLAPIENTRY
+_mesa_BindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
+{
+ 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);
+ return;
+ }
+
+ 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 <count> 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."
+ */
+
+ begin_samplerobj_lookups(ctx);
+
+ 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 <samplers> is not zero or the name of an existing
+ * sampler object (per binding)."
+ */
+ if (!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;
+ }
+ }
+
+ end_samplerobj_lookups(ctx);
+ } else {
+ /* Unbind all samplers in the range <first> through <first>+<count>-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;
+ }
+ }
+ }
+}
+
+
/**
* Check if a coordinate wrap mode is legal.
* \return GL_TRUE if legal, GL_FALSE otherwise
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:
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;
}
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)
sampObj = _mesa_lookup_samplerobj(ctx, sampler);
if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)",
- sampler);
+ /* '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),
+ "glSamplerParameteri(sampler %u)", sampler);
return;
}
sampObj = _mesa_lookup_samplerobj(ctx, sampler);
if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(sampler %u)",
- sampler);
+ /* '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);
return;
}
sampObj = _mesa_lookup_samplerobj(ctx, sampler);
if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(sampler %u)",
- sampler);
+ /* '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);
return;
}
sampObj = _mesa_lookup_samplerobj(ctx, sampler);
if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(sampler %u)",
- sampler);
+ /* '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);
return;
}
sampObj = _mesa_lookup_samplerobj(ctx, sampler);
if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameteriv(sampler %u)",
- sampler);
+ /* '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);
return;
}
*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)
*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]);
sampObj = _mesa_lookup_samplerobj(ctx, sampler);
if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameterfv(sampler %u)",
- sampler);
+ /* '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);
return;
}