diff options
Diffstat (limited to 'src/mesa/main')
-rw-r--r-- | src/mesa/main/shaderimage.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/mesa/main/shaderimage.c b/src/mesa/main/shaderimage.c index f77f2c6c2ba..9e62f4294b4 100644 --- a/src/mesa/main/shaderimage.c +++ b/src/mesa/main/shaderimage.c @@ -33,6 +33,7 @@ #include "context.h" #include "texobj.h" #include "teximage.h" +#include "enums.h" /* * Define endian-invariant aliases for some mesa formats that are @@ -481,6 +482,143 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, void GLAPIENTRY _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) { + GET_CURRENT_CONTEXT(ctx); + int i; + + if (!ctx->Extensions.ARB_shader_image_load_store) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTextures()"); + return; + } + + if (first + count > ctx->Const.MaxImageUnits) { + /* The ARB_multi_bind spec says: + * + * "An INVALID_OPERATION error is generated if <first> + <count> + * is greater than the number of image units supported by + * the implementation." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindImageTextures(first=%u + count=%d > the value of " + "GL_MAX_IMAGE_UNITS=%u)", + first, count, ctx->Const.MaxImageUnits); + return; + } + + /* Assume that at least one binding will be changed */ + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; + + /* 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++) { + struct gl_image_unit *u = &ctx->ImageUnits[first + i]; + const GLuint texture = textures ? textures[i] : 0; + + if (texture != 0) { + struct gl_texture_object *texObj; + struct gl_texture_image *image; + mesa_format actualFormat; + + if (!u->TexObj || u->TexObj->Name != texture) { + texObj = _mesa_lookup_texture_locked(ctx, texture); + if (!texObj) { + /* 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)." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindImageTextures(textures[%d]=%u " + "is not zero or the name of an existing texture " + "object)", i, texture); + continue; + } + } else { + texObj = u->TexObj; + } + + image = texObj->Image[0][0]; + + if (!image || image->Width == 0 || image->Height == 0 || image->Depth == 0) { + /* The ARB_multi_bind spec says: + * + * "An INVALID_OPERATION error is generated if the width, + * height, or depth of the level zero texture image of + * any texture in <textures> is zero (per binding)." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindImageTextures(the width, height or depth " + "of the level zero texture image of " + "textures[%d]=%u is zero)", i, texture); + continue; + } + + actualFormat = get_image_format(image->InternalFormat); + + if (actualFormat == MESA_FORMAT_NONE) { + /* The ARB_multi_bind spec says: + * + * "An INVALID_OPERATION error is generated if the internal + * format of the level zero texture image of any texture + * in <textures> is not found in table 8.33 (per binding)." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindImageTextures(the internal format %s of " + "the level zero texture image of textures[%d]=%u " + "is not supported)", + _mesa_lookup_enum_by_nr(image->InternalFormat), + i, texture); + continue; + } + + /* Update the texture binding */ + _mesa_reference_texobj(&u->TexObj, texObj); + u->Level = 0; + u->Layered = _mesa_tex_target_is_layered(texObj->Target); + u->Layer = 0; + u->Access = GL_READ_WRITE; + u->Format = image->InternalFormat; + u->_ActualFormat = actualFormat; + u->_Valid = validate_image_unit(ctx, u); + } else { + /* Unbind the texture from the unit */ + _mesa_reference_texobj(&u->TexObj, NULL); + u->Level = 0; + u->Layered = GL_FALSE; + u->Layer = 0; + u->Access = GL_READ_ONLY; + u->Format = GL_R8; + u->_ActualFormat = MESA_FORMAT_R_UNORM8; + u->_Valid = GL_FALSE; + } + + /* Pass the BindImageTexture call down to the device driver */ + if (ctx->Driver.BindImageTexture) + ctx->Driver.BindImageTexture(ctx, u, u->TexObj, u->Level, u->Layered, + u->Layer, u->Access, u->Format); + } + + _mesa_end_texture_lookups(ctx); } void GLAPIENTRY |