diff options
author | Brian Paul <[email protected]> | 2017-07-05 14:31:26 -0600 |
---|---|---|
committer | Brian Paul <[email protected]> | 2017-07-06 16:33:57 -0600 |
commit | ccdcce3638571e86bc2a799a0d8852d32074a10e (patch) | |
tree | 3fc539bcb876ee8322753d03ba1a093e7eadce04 | |
parent | 7e2669d02fa5e6e1d8fdfab67f3fcb43ce1b9111 (diff) |
st/mesa: find proper mipmap level in st_ClearTexSubImage()
The Piglit arb_clear_texture-error test creates a texture with only
a 1x1 image at level=1, then tries to clear level 0 (nonexistent)
and level 1 (exists). The test only checks that the former generates
an error but the later doesn't. The test passes, but when we try
to clear the level=1 image we're passing an invalid level to
pipe_context::clear_texture(). level=1, but since there's only one
mipmap level in the texture, it should be zero.
This fixes the code to search the gallium texture resource for the
correct mipmap level. Also, add an assertion to make sure we're not
passing an invalid level to pipe_context::clear_texture().
Fixes device errors with VMware driver. No Piglit regressions.
v2: don't do the level search when using immutable textures.
Reviewed-by: Charmaine Lee <[email protected]>
-rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 1847cc30df9..c6a5e634553 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -2836,6 +2836,42 @@ st_TextureView(struct gl_context *ctx, return GL_TRUE; } + +/** + * Find the mipmap level in 'pt' which matches the level described by + * 'texImage'. + */ +static unsigned +find_mipmap_level(const struct gl_texture_image *texImage, + const struct pipe_resource *pt) +{ + const GLenum target = texImage->TexObject->Target; + GLint texWidth = texImage->Width; + GLint texHeight = texImage->Height; + GLint texDepth = texImage->Depth; + unsigned level, w; + uint16_t h, d, layers; + + st_gl_texture_dims_to_pipe_dims(target, texWidth, texHeight, texDepth, + &w, &h, &d, &layers); + + for (level = 0; level <= pt->last_level; level++) { + if (u_minify(pt->width0, level) == w && + u_minify(pt->height0, level) == h && + u_minify(pt->depth0, level) == d) { + return level; + } + } + + /* If we get here, there must be some sort of inconsistency between + * the Mesa texture object/images and the gallium resource. + */ + debug_printf("Inconsistent textures in find_mipmap_level()\n"); + + return texImage->Level; +} + + static void st_ClearTexSubImage(struct gl_context *ctx, struct gl_texture_image *texImage, @@ -2844,11 +2880,12 @@ st_ClearTexSubImage(struct gl_context *ctx, const void *clearValue) { static const char zeros[16] = {0}; + struct gl_texture_object *texObj = texImage->TexObject; struct st_texture_image *stImage = st_texture_image(texImage); struct pipe_resource *pt = stImage->pt; struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - unsigned level = texImage->Level; + unsigned level; struct pipe_box box; if (!pt) @@ -2859,10 +2896,25 @@ st_ClearTexSubImage(struct gl_context *ctx, u_box_3d(xoffset, yoffset, zoffset + texImage->Face, width, height, depth, &box); - if (texImage->TexObject->Immutable) { - level += texImage->TexObject->MinLevel; - box.z += texImage->TexObject->MinLayer; + if (texObj->Immutable) { + /* The texture object has to be consistent (no "loose", per-image + * gallium resources). If this texture is a view into another + * texture, we have to apply the MinLevel/Layer offsets. If this is + * not a texture view, the offsets will be zero. + */ + assert(stImage->pt == st_texture_object(texObj)->pt); + level = texImage->Level + texObj->MinLevel; + box.z += texObj->MinLayer; } + else { + /* Texture level sizes may be inconsistent. We my have "loose", + * per-image gallium resources. The texImage->Level may not match + * the gallium resource texture level. + */ + level = find_mipmap_level(texImage, pt); + } + + assert(level <= pt->last_level); pipe->clear_texture(pipe, pt, level, &box, clearValue ? clearValue : zeros); } |