<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Nov 22, 2016 at 9:09 AM, Topi Pohjolainen <span dir="ltr"><<a href="mailto:topi.pohjolainen@gmail.com" target="_blank">topi.pohjolainen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This was detected when examining CCS_E failures with piglit test:<br>
"fbo-generatemipmap-formats". Test creates a 2D texture with<br>
dimensions 293x277. It manually loops over all levels and calls<br>
glTexImage2D(). Level one triggers creation of full miptree:<br>
intel_alloc_texture_image_<wbr>buffer() realizes that there is only one<br>
level in the miptree and calls intel_miptree_create_for_<wbr>teximage()<br>
to re-allocate the miptree with all 9 levels. However, the end result<br>
is a miptree with level zero dimensions of 292x276.<br></blockquote><div><br></div><div>Man... Who decided that you should be able to resize a texture by uploading something to miplevel 2... It was a bad idea...<br><br></div><div>Both are<br><br></div><div>Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Related, and possibly calling for treatment of its own is mip-map<br>
generation:<br>
After calling glTexImage2D() against every level test continues by<br>
replacing content for levels one to eight with data derived from level<br>
zero by calling glGenerateMipmapEXT(). This results into the miptree<br>
being allocated anew for every level:<br>
Mip-map generation goes thru meta which ends up validating the texture<br>
(brw_validate_textures()-><wbr>intel_finalize_mipmap_tree()-><br>
intel_miptree_match_image()) where one finds texture with base level<br>
size 292:276. This results into new miptree being created for the npot<br>
size 293:277. Only here intel_finalize_mipmap_tree() is asked for only<br>
one level, and therefore such is created. Generation for level one in<br>
turn finds right base level size but only one level when two is needed.<br>
And the same goes on for all eight levels.<br>
<br>
This patch prevents the shrink maintaining the NPOT size of 293x277.<br>
<br>
Signed-off-by: Topi Pohjolainen <<a href="mailto:topi.pohjolainen@intel.com">topi.pohjolainen@intel.com</a>><br>
CC: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
CC: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>><br>
---<br>
 src/mesa/drivers/dri/i965/<wbr>intel_tex_image.c | 29 +++++++++++++++++++++++++----<br>
 1 file changed, 25 insertions(+), 4 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>intel_tex_image.c b/src/mesa/drivers/dri/i965/<wbr>intel_tex_image.c<br>
index 4454e53..cbff58a 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>intel_tex_image.c<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>intel_tex_image.c<br>
@@ -29,6 +29,22 @@<br>
<br>
 #define FILE_DEBUG_FLAG DEBUG_TEXTURE<br>
<br>
+/* Make sure one doesn't end up shrinking base level zero unnecessarily.<br>
+ * Determining the base level dimension by shifting higher level dimension<br>
+ * ends up in off-by-one value in case base level has NPOT size (for example,<br>
+ * 293 != 146 << 1).<br>
+ * Choose the original base level dimension when shifted dimensions agree.<br>
+ * Otherwise assume real resize is intended and use the new shifted value.<br>
+ */<br>
+static unsigned<br>
+get_base_dim(unsigned old_base_dim, unsigned new_level_dim, unsigned level)<br>
+{<br>
+   const unsigned old_level_dim = old_base_dim >> level;<br>
+   const unsigned new_base_dim = new_level_dim << level;<br>
+<br>
+   return old_level_dim == new_level_dim ? old_base_dim : new_base_dim;<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+}<br>
+<br>
 /* Work back from the specified level of the image to the baselevel and create a<br>
  * miptree of that size.<br>
  */<br>
@@ -40,6 +56,8 @@ intel_miptree_create_for_<wbr>teximage(struct brw_context *brw,<br>
 {<br>
    GLuint lastLevel;<br>
    int width, height, depth;<br>
+   const struct intel_mipmap_tree *old_mt = intelObj->mt;<br>
+   const unsigned level = intelImage->base.Base.Level;<br>
<br>
    intel_get_image_dims(&<wbr>intelImage->base.Base, &width, &height, &depth);<br>
<br>
@@ -51,20 +69,23 @@ intel_miptree_create_for_<wbr>teximage(struct brw_context *brw,<br>
    case GL_TEXTURE_2D_MULTISAMPLE_<wbr>ARRAY:<br>
    case GL_TEXTURE_RECTANGLE:<br>
    case GL_TEXTURE_EXTERNAL_OES:<br>
-      assert(intelImage->base.Base.<wbr>Level == 0);<br>
+      assert(level == 0);<br>
       break;<br>
    case GL_TEXTURE_3D:<br>
-      depth <<= intelImage->base.Base.Level;<br>
+      depth = old_mt ? get_base_dim(old_mt->logical_<wbr>depth0, depth, level) :<br>
+                       depth << level;<br>
       /* Fall through */<br>
    case GL_TEXTURE_2D:<br>
    case GL_TEXTURE_2D_ARRAY:<br>
    case GL_TEXTURE_CUBE_MAP:<br>
    case GL_TEXTURE_CUBE_MAP_ARRAY:<br>
-      height <<= intelImage->base.Base.Level;<br>
+      height = old_mt ? get_base_dim(old_mt->logical_<wbr>height0, height, level) :<br>
+                        height << level;<br>
       /* Fall through */<br>
    case GL_TEXTURE_1D:<br>
    case GL_TEXTURE_1D_ARRAY:<br>
-      width <<= intelImage->base.Base.Level;<br>
+      width = old_mt ? get_base_dim(old_mt->logical_<wbr>width0, width, level) :<br>
+                       width << level;<br>
       break;<br>
    default:<br>
       unreachable("Unexpected target");<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.5.5<br>
<br>
</font></span></blockquote></div><br></div></div>