st/mesa: use base level size as "guess" when available

When an applications specifies mip levels _before_ setting a mipmap texture
filter, we will initially guess a single texture level. When the second level
image is created, we try to allocate the full texture -- however, we get the
base level size guess wrong if that size is odd. This leads to yet another
re-allocation of the texture later during st_finalize_texture.

Even worse, this re-allocation breaks a (reasonable) assumption made by
st_generate_mipmaps, because the re-allocation in the finalization call will
again allocate a single-level pipe texture (based on the non-mipmap texture
filter!). As a result, mipmap generation fails in interesting ways.

All of this can be avoided by just using the fact that we already know the
size of the base level.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=95529
Cc: 12.0 <mesa-stable@lists.freedesktop.org>
Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
Nicolai Hähnle
2016-06-06 23:15:10 +02:00
parent a1e69930e4
commit 42624ea837

View File

@@ -456,21 +456,42 @@ guess_and_alloc_texture(struct st_context *st,
struct st_texture_object *stObj,
const struct st_texture_image *stImage)
{
const struct gl_texture_image *firstImage;
GLuint lastLevel, width, height, depth;
GLuint bindings;
GLuint ptWidth, ptHeight, ptDepth, ptLayers;
enum pipe_format fmt;
bool guessed_box = false;
DBG("%s\n", __func__);
assert(!stObj->pt);
if (!guess_base_level_size(stObj->base.Target,
stImage->base.Width2,
stImage->base.Height2,
stImage->base.Depth2,
stImage->base.Level,
&width, &height, &depth)) {
/* If a base level image with compatible size exists, use that as our guess.
*/
firstImage = _mesa_base_tex_image(&stObj->base);
if (firstImage &&
guess_base_level_size(stObj->base.Target,
firstImage->Width2,
firstImage->Height2,
firstImage->Depth2,
firstImage->Level,
&width, &height, &depth)) {
if (stImage->base.Width2 == u_minify(width, stImage->base.Level) &&
stImage->base.Height2 == u_minify(height, stImage->base.Level) &&
stImage->base.Depth2 == u_minify(depth, stImage->base.Level))
guessed_box = true;
}
if (!guessed_box)
guessed_box = guess_base_level_size(stObj->base.Target,
stImage->base.Width2,
stImage->base.Height2,
stImage->base.Depth2,
stImage->base.Level,
&width, &height, &depth);
if (!guessed_box) {
/* we can't determine the image size at level=0 */
/* this is not an out of memory error */
return GL_TRUE;