[Mesa-dev] [PATCH 08/18] mesa: Implement glBindTextures()
Brian Paul
brianp at vmware.com
Wed Jan 22 09:01:08 PST 2014
On 01/21/2014 03:35 PM, Fredrik Höglund wrote:
> ---
> src/mesa/main/texobj.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 121 insertions(+)
>
> diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
> index c9fe11d..2ff3f9d 100644
> --- a/src/mesa/main/texobj.c
> +++ b/src/mesa/main/texobj.c
> @@ -1140,6 +1140,28 @@ unbind_texobj_from_imgunits(struct gl_context *ctx,
> }
> }
>
> +/**
> + * Unbinds all textures bound to the given texture image unit.
> + */
> +static void
> +unbind_textures_from_unit(struct gl_context *ctx, GLuint unit)
> +{
> + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
> +
> + while (texUnit->_BoundTextures) {
> + const GLuint index = ffs(texUnit->_BoundTextures) - 1;
> + struct gl_texture_object *texObj = ctx->Shared->DefaultTex[index];
> +
> + _mesa_reference_texobj(&texUnit->CurrentTex[index], texObj);
> +
> + /* Pass BindTexture call to device driver */
> + if (ctx->Driver.BindTexture)
> + ctx->Driver.BindTexture(ctx, 0, texObj);
> +
> + texUnit->_BoundTextures ^= (1 << index);
texUnit->_BoundTextures &= ~(1 << index);
> + ctx->NewState |= _NEW_TEXTURE;
> + }
> +}
>
> /**
> * Delete named textures.
> @@ -1384,6 +1406,105 @@ _mesa_BindTexture( GLenum target, GLuint texName )
> void GLAPIENTRY
> _mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures)
> {
> + GET_CURRENT_CONTEXT(ctx);
> + GLuint i;
GLint/GLsizei 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,
> + "glBindTextures(first=%u + count=%u > the value of "
> + "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
> + first, count, ctx->Const.MaxCombinedTextureImageUnits);
> + return;
> + }
> +
> + /* Flush before changing bindings */
> + FLUSH_VERTICES(ctx, 0);
> +
> + if (textures) {
> + /* 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_begin_texture_lookups(ctx);
> +
> + for (i = 0; i < count; i++) {
> + if (textures[i] != 0) {
> + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[first + i];
> + struct gl_texture_object *current = texUnit->_Current;
> + struct gl_texture_object *texObj;
> + GLenum target;
> + GLuint targetIndex;
gl_texture_index targetIndex;
> +
> + if (current && current->Name == textures[i])
> + texObj = current;
> + else
> + texObj = _mesa_lookup_texture_without_locking(ctx, textures[i]);
> +
> + /* The ARB_multi_bind spec says:
> + *
> + * "An INVALID_OPERATION error is generated if any value
> + * in <textures> is not zero or the name of an existing
> + * texture object (per binding)."
> + */
> + if (!texObj || texObj->Target == 0) {
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "glBindTextures(textures[%u]=%u is not zero "
> + "or the name of an existing texture object)",
> + i, textures[i]);
> + continue;
> + }
> +
> + target = texObj->Target;
> + targetIndex = texObj->TargetIndex;
> +
> + if (texUnit->CurrentTex[targetIndex] == texObj)
> + continue;
> +
> + /* Do the actual binding. The refcount on the previously bound
> + * texture object will be decremented. It will be deleted if the
> + * count hits zero.
> + */
> + _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], texObj);
> + ASSERT(texUnit->CurrentTex[targetIndex]);
> +
> + texUnit->_BoundTextures |= (1 << targetIndex);
> + ctx->NewState |= _NEW_TEXTURE;
> +
> + /* Pass BindTexture call to device driver */
> + if (ctx->Driver.BindTexture)
> + ctx->Driver.BindTexture(ctx, target, texObj);
Again, I'd probably restructure the chunk above to avoid using continue
(but not a big deal). I don't think the assertion is needed either
since texObj will be non-null.
> + } else {
> + unbind_textures_from_unit(ctx, first + i);
> + }
> + }
> +
> + _mesa_end_texture_lookups(ctx);
> + } else {
> + /* Unbind all textures in the range <first> through <first>+<count>-1 */
> + for (i = 0; i < count; i++)
> + unbind_textures_from_unit(ctx, first + i);
> + }
> }
>
>
>
More information about the mesa-dev
mailing list