static void delete_samplers(struct gl_context *ctx, GLsizei count, const GLuint *samplers) { FLUSH_VERTICES(ctx, 0); _mesa_HashLockMutex(ctx->Shared->SamplerObjects); for (GLsizei i = 0; i < count; i++) { if (samplers[i]) { GLuint j; struct gl_sampler_object *sampObj = 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_HashRemoveLocked(ctx->Shared->SamplerObjects, samplers[i]); /* But the object exists until its reference count goes to zero */ _mesa_reference_sampler_object(ctx, &sampObj, NULL); } } } _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); }
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 <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." */ _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 <samplers> 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 <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_OBJECT; } } } }
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; } } } }