Mesa (master): intel: When making a new teximage miptree, make a full one.

Eric Anholt anholt at kemper.freedesktop.org
Tue Jan 11 01:22:50 UTC 2011


Module: Mesa
Branch: master
Commit: 48024fb44cbbccd0c688949084ef249d3c1208ab
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=48024fb44cbbccd0c688949084ef249d3c1208ab

Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 10 12:05:14 2011 -0800

intel: When making a new teximage miptree, make a full one.

If we hit this path, we're level 1+ and the base level got allocated
as a single level instead of a full tree (so we don't match
intelObj->mt).  This tries to recover from that so that we end up with
2 allocations and 1 validation blit (old -> new) instead of
allocations equal to number of levels and levels - 1 blits.

---

 src/mesa/drivers/dri/intel/intel_tex_image.c |  147 ++++++++++++--------------
 1 files changed, 68 insertions(+), 79 deletions(-)

diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 450c3ce..cd8c4c2 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -56,11 +56,11 @@ logbase2(int n)
  * 0)..(1x1).  Consider pruning this tree at a validation if the
  * saving is worth it.
  */
-static void
-guess_and_alloc_mipmap_tree(struct intel_context *intel,
-                            struct intel_texture_object *intelObj,
-                            struct intel_texture_image *intelImage,
-			    GLboolean expect_accelerated_upload)
+static struct intel_mipmap_tree *
+intel_miptree_create_for_teximage(struct intel_context *intel,
+				  struct intel_texture_object *intelObj,
+				  struct intel_texture_image *intelImage,
+				  GLboolean expect_accelerated_upload)
 {
    GLuint firstLevel;
    GLuint lastLevel;
@@ -73,70 +73,71 @@ guess_and_alloc_mipmap_tree(struct intel_context *intel,
    DBG("%s\n", __FUNCTION__);
 
    if (intelImage->base.Border)
-      return;
+      return NULL;
 
    if (intelImage->level > intelObj->base.BaseLevel &&
        (intelImage->base.Width == 1 ||
         (intelObj->base.Target != GL_TEXTURE_1D &&
          intelImage->base.Height == 1) ||
         (intelObj->base.Target == GL_TEXTURE_3D &&
-         intelImage->base.Depth == 1)))
-      return;
-
-   /* If this image disrespects BaseLevel, allocate from level zero.
-    * Usually BaseLevel == 0, so it's unlikely to happen.
-    */
-   if (intelImage->level < intelObj->base.BaseLevel)
-      firstLevel = 0;
-   else
-      firstLevel = intelObj->base.BaseLevel;
-
-
-   /* Figure out image dimensions at start level. 
-    */
-   for (i = intelImage->level; i > firstLevel; i--) {
-      width <<= 1;
-      if (height != 1)
-         height <<= 1;
-      if (depth != 1)
-         depth <<= 1;
-   }
+         intelImage->base.Depth == 1))) {
+      /* For this combination, we're at some lower mipmap level and
+       * some important dimension is 1.  We can't extrapolate up to a
+       * likely base level width/height/depth for a full mipmap stack
+       * from this info, so just allocate this one level.
+       */
+      firstLevel = intelImage->level;
+      lastLevel = intelImage->level;
+   } else {
+      /* If this image disrespects BaseLevel, allocate from level zero.
+       * Usually BaseLevel == 0, so it's unlikely to happen.
+       */
+      if (intelImage->level < intelObj->base.BaseLevel)
+	 firstLevel = 0;
+      else
+	 firstLevel = intelObj->base.BaseLevel;
+
+      /* Figure out image dimensions at start level. */
+      for (i = intelImage->level; i > firstLevel; i--) {
+	 width <<= 1;
+	 if (height != 1)
+	    height <<= 1;
+	 if (depth != 1)
+	    depth <<= 1;
+      }
 
-   /* Guess a reasonable value for lastLevel.  This is probably going
-    * to be wrong fairly often and might mean that we have to look at
-    * resizable buffers, or require that buffers implement lazy
-    * pagetable arrangements.
-    */
-   if ((intelObj->base.MinFilter == GL_NEAREST ||
-        intelObj->base.MinFilter == GL_LINEAR) &&
-       intelImage->level == firstLevel &&
-       (intel->gen < 4 || firstLevel == 0)) {
-      lastLevel = firstLevel;
-   }
-   else {
-      lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth));
+      /* Guess a reasonable value for lastLevel.  This is probably going
+       * to be wrong fairly often and might mean that we have to look at
+       * resizable buffers, or require that buffers implement lazy
+       * pagetable arrangements.
+       */
+      if ((intelObj->base.MinFilter == GL_NEAREST ||
+	   intelObj->base.MinFilter == GL_LINEAR) &&
+	  intelImage->level == firstLevel &&
+	  (intel->gen < 4 || firstLevel == 0)) {
+	 lastLevel = firstLevel;
+      } else {
+	 lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth));
+      }
    }
 
-   assert(!intelObj->mt);
    if (_mesa_is_format_compressed(intelImage->base.TexFormat))
       comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat);
 
    texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat);
 
-   intelObj->mt = intel_miptree_create(intel,
-                                       intelObj->base.Target,
-                                       intelImage->base._BaseFormat,
-                                       intelImage->base.InternalFormat,
-                                       firstLevel,
-                                       lastLevel,
-                                       width,
-                                       height,
-                                       depth,
-                                       texelBytes,
-                                       comp_byte,
-				       expect_accelerated_upload);
-
-   DBG("%s - success\n", __FUNCTION__);
+   return intel_miptree_create(intel,
+			       intelObj->base.Target,
+			       intelImage->base._BaseFormat,
+			       intelImage->base.InternalFormat,
+			       firstLevel,
+			       lastLevel,
+			       width,
+			       height,
+			       depth,
+			       texelBytes,
+			       comp_byte,
+			       expect_accelerated_upload);
 }
 
 
@@ -344,41 +345,29 @@ intelTexImage(struct gl_context * ctx,
       texImage->Data = NULL;
    }
 
-   if (!intelObj->mt) {
-      guess_and_alloc_mipmap_tree(intel, intelObj, intelImage, pixels == NULL);
-      if (!intelObj->mt) {
-	 DBG("guess_and_alloc_mipmap_tree: failed\n");
-      }
-   }
-
    assert(!intelImage->mt);
 
    if (intelObj->mt &&
        intel_miptree_match_image(intelObj->mt, &intelImage->base)) {
-
+      /* Use an existing miptree when possible */
       intel_miptree_reference(&intelImage->mt, intelObj->mt);
       assert(intelImage->mt);
    } else if (intelImage->base.Border == 0) {
-      int comp_byte = 0;
-      GLuint texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat);
-      GLenum baseFormat = _mesa_get_format_base_format(intelImage->base.TexFormat);
-      if (_mesa_is_format_compressed(intelImage->base.TexFormat)) {
-	 comp_byte =
-	    intel_compressed_num_bytes(intelImage->base.TexFormat);
-      }
-
       /* Didn't fit in the object miptree, but it's suitable for inclusion in
        * a miptree, so create one just for our level and store it in the image.
        * It'll get moved into the object miptree at validate time.
        */
-      intelImage->mt = intel_miptree_create(intel, target,
-					    baseFormat,
-					    internalFormat,
-					    level, level,
-					    width, height, depth,
-					    texelBytes,
-					    comp_byte, pixels == NULL);
-
+      intelImage->mt = intel_miptree_create_for_teximage(intel, intelObj,
+							 intelImage,
+							 pixels == NULL);
+
+      /* Even if the object currently has a mipmap tree associated
+       * with it, this one is a more likely candidate to represent the
+       * whole object since our level didn't fit what was there
+       * before, and any lower levels would fit into our miptree.
+       */
+      if (intelImage->mt)
+	 intel_miptree_reference(&intelObj->mt, intelImage->mt);
    }
 
    /* PBO fastpaths:




More information about the mesa-commit mailing list