From: Nicolai Hähnle Date: Mon, 6 Jun 2016 21:15:10 +0000 (+0200) Subject: st/mesa: use base level size as "guess" when available X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=42624ea83;p=mesa.git 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 Reviewed-by: Brian Paul --- diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 22a58517fc7..3e504965fc0 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -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;