}
+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.
*/
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;
+ }
+ }
+ }
}