[Mesa-dev] [PATCH] intel:i915:i965: enable mipmap layout right mode

Yuanhan Liu yuanhan.liu at linux.intel.com
Wed Mar 14 23:42:53 PDT 2012


There are two mipmap layout modes: below and right. And we currently just
use _below_ mode. And in some cases, like height is greater than width,
it would be better to use the _right_ mode for saving memory.

And it also fix some issues like the gl-max-texture-dimensions.html webglc
test case on pineview in a hardware way(no fallback). Since when
rendering with 1x2048 texture using below mode would make the draw
offset exceed the max allowed size, but will not when using right mode.

Signed-off-by: Yuanhan Liu <yuanhan.liu at linux.intel.com>
---
 src/mesa/drivers/dri/i915/i915_reg.h             |    1 +
 src/mesa/drivers/dri/i915/i915_tex_layout.c      |    4 +-
 src/mesa/drivers/dri/i915/i915_texstate.c        |    2 +
 src/mesa/drivers/dri/i965/brw_tex_layout.c       |    4 +-
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c |    2 +-
 src/mesa/drivers/dri/intel/intel_mipmap_tree.c   |    2 +-
 src/mesa/drivers/dri/intel/intel_mipmap_tree.h   |    7 ++-
 src/mesa/drivers/dri/intel/intel_tex_layout.c    |   70 +++++++++++++++-------
 src/mesa/drivers/dri/intel/intel_tex_layout.h    |    3 +-
 9 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/src/mesa/drivers/dri/i915/i915_reg.h b/src/mesa/drivers/dri/i915/i915_reg.h
index 766547a..0ca0acf 100644
--- a/src/mesa/drivers/dri/i915/i915_reg.h
+++ b/src/mesa/drivers/dri/i915/i915_reg.h
@@ -645,6 +645,7 @@
 #define MS4_CUBE_FACE_ENA_MASK          (0x3f<<15)
 #define MS4_MAX_LOD_SHIFT		9
 #define MS4_MAX_LOD_MASK		(0x3f<<9)
+#define MS4_MIP_LAYOUT_MODE_SHIFT       8
 #define MS4_MIP_LAYOUT_LEGACY           (0<<8)
 #define MS4_MIP_LAYOUT_BELOW_LPT        (0<<8)
 #define MS4_MIP_LAYOUT_RIGHT_LPT        (1<<8)
diff --git a/src/mesa/drivers/dri/i915/i915_tex_layout.c b/src/mesa/drivers/dri/i915/i915_tex_layout.c
index 1e3cfad..6600734 100644
--- a/src/mesa/drivers/dri/i915/i915_tex_layout.c
+++ b/src/mesa/drivers/dri/i915/i915_tex_layout.c
@@ -454,7 +454,7 @@ i945_miptree_layout_3d(struct intel_mipmap_tree * mt)
 }
 
 void
-i945_miptree_layout(struct intel_mipmap_tree * mt)
+i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
 {
    switch (mt->target) {
    case GL_TEXTURE_CUBE_MAP:
@@ -469,7 +469,7 @@ i945_miptree_layout(struct intel_mipmap_tree * mt)
    case GL_TEXTURE_1D:
    case GL_TEXTURE_2D:
    case GL_TEXTURE_RECTANGLE_ARB:
-      i945_miptree_layout_2d(mt);
+      i945_miptree_layout_2d(intel, mt);
       break;
    default:
       _mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()");
diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c
index 9022548..54f32a4 100644
--- a/src/mesa/drivers/dri/i915/i915_texstate.c
+++ b/src/mesa/drivers/dri/i915/i915_texstate.c
@@ -192,6 +192,8 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
        (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) |
        ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
 
+   if (intel->is_945)
+      state[I915_TEXREG_MS4] |= intelObj->mt->layout << MS4_MIP_LAYOUT_MODE_SHIFT;
 
    {
       GLuint minFilt, mipFilt, magFilt;
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index 7a1b91f..5a66f90 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -53,7 +53,7 @@ brw_miptree_layout_texture_array(struct intel_context *intel,
    if (mt->compressed)
       qpitch /= 4;
 
-   i945_miptree_layout_2d(mt);
+   i945_miptree_layout_2d(intel, mt);
 
    for (level = mt->first_level; level <= mt->last_level; level++) {
       for (q = 0; q < mt->depth0; q++) {
@@ -164,7 +164,7 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
       break;
 
    default:
-      i945_miptree_layout_2d(mt);
+      i945_miptree_layout_2d(intel, mt);
       break;
    }
    DBG("%s: %dx%dx%d\n", __FUNCTION__,
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index a3de2e3..b6565fe 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -654,7 +654,7 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit )
 			  6 * 4, 32, &brw->wm.surf_offset[surf_index]);
 
    surf[0] = (translate_tex_target(tObj->Target) << BRW_SURFACE_TYPE_SHIFT |
-	      BRW_SURFACE_MIPMAPLAYOUT_BELOW << BRW_SURFACE_MIPLAYOUT_SHIFT |
+	      mt->layout << BRW_SURFACE_MIPLAYOUT_SHIFT |
 	      BRW_SURFACE_CUBEFACE_ENABLES |
 	      (translate_tex_format(mt->format,
 				    firstImage->InternalFormat,
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 3601f5e..cb97ebe 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -151,7 +151,7 @@ intel_miptree_create_internal(struct intel_context *intel,
 #ifdef I915
    (void) intel;
    if (intel->is_945)
-      i945_miptree_layout(mt);
+      i945_miptree_layout(intel, mt);
    else
       i915_miptree_layout(mt);
 #else
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 9082864..d175f50 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -215,6 +215,10 @@ struct intel_mipmap_tree
    /* These are also refcounted:
     */
    GLuint refcount;
+
+#define INTEL_LAYOUT_BELOW	0
+#define INTEL_LAYOUT_RIGHT	1
+   int layout;
 };
 
 
@@ -390,7 +394,8 @@ intel_miptree_all_slices_resolve_depth(struct intel_context *intel,
 /* i915_mipmap_tree.c:
  */
 void i915_miptree_layout(struct intel_mipmap_tree *mt);
-void i945_miptree_layout(struct intel_mipmap_tree *mt);
+void i945_miptree_layout(struct intel_context *intel,
+                         struct intel_mipmap_tree *mt);
 void brw_miptree_layout(struct intel_context *intel,
 			struct intel_mipmap_tree *mt);
 
diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c
index 65645bc..4687dd3 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_layout.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c
@@ -138,7 +138,27 @@ intel_get_texture_alignment_unit(struct intel_context *intel,
    *h = intel_vertical_texture_alignment_unit(intel, format);
 }
 
-void i945_miptree_layout_2d(struct intel_mipmap_tree *mt)
+static int
+i945_miptree_choose_layout(struct intel_context *intel, GLenum target,
+                           GLuint width, GLuint height)
+{
+   int layout = INTEL_LAYOUT_BELOW; /* Use layout _below_ by default */
+
+   /*
+    * INTEL_LAYOUT_RIGHT is only for:
+    *   GL_TEXTURE_1D, GL_TEXTURE_2D [945+, aka all platforms here]
+    *   GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP [gen5+]
+    */
+   if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D ||
+       (intel->gen >= 5 && target == GL_TEXTURE_CUBE_MAP)) {
+      if ((height >> 1) >= width)
+         layout = INTEL_LAYOUT_RIGHT;
+   }
+
+   return layout;
+}
+
+void i945_miptree_layout_2d(struct intel_context *intel, struct intel_mipmap_tree *mt)
 {
    GLuint level;
    GLuint x = 0;
@@ -153,24 +173,32 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt)
        mt->total_width = ALIGN(mt->width0, mt->align_w);
    }
 
-   /* May need to adjust width to accomodate the placement of
-    * the 2nd mipmap.  This occurs when the alignment
-    * constraints of mipmap placement push the right edge of the
-    * 2nd mipmap out past the width of its parent.
-    */
+   mt->layout = i945_miptree_choose_layout(intel, mt->target, width, height);
+   /* Determine the max width */
    if (mt->first_level != mt->last_level) {
-       GLuint mip1_width;
-
-       if (mt->compressed) {
-           mip1_width = ALIGN(minify(mt->width0), mt->align_w)
-               + ALIGN(minify(minify(mt->width0)), mt->align_w);
+       GLuint tmp;
+
+       if (mt->layout == INTEL_LAYOUT_BELOW) {
+          if (mt->compressed) {
+              tmp = ALIGN(minify(mt->width0), mt->align_w) +
+                          ALIGN(minify(minify(mt->width0)), mt->align_w);
+          } else {
+              tmp = ALIGN(minify(mt->width0), mt->align_w) +
+                          minify(minify(mt->width0));
+          }
+       } else if (mt->layout == INTEL_LAYOUT_RIGHT) {
+          if (mt->compressed) {
+              tmp = ALIGN(mt->width0, mt->align_w) +
+                    ALIGN(minify(mt->width0), mt->align_w);
+          } else {
+              tmp = ALIGN(mt->width0, mt->align_w) + minify(mt->width0);
+          }
        } else {
-           mip1_width = ALIGN(minify(mt->width0), mt->align_w)
-               + minify(minify(mt->width0));
+          assert(!"mipmap: wrong layout!\n");
        }
 
-       if (mip1_width > mt->total_width) {
-           mt->total_width = mip1_width;
+       if (tmp > mt->total_width) {
+           mt->total_width = tmp;
        }
    }
 
@@ -191,13 +219,11 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt)
        */
       mt->total_height = MAX2(mt->total_height, y + img_height);
 
-      /* Layout_below: step right after second mipmap.
-       */
-      if (level == mt->first_level + 1) {
-	 x += ALIGN(width, mt->align_w);
-      }
-      else {
-	 y += img_height;
+      if ((mt->layout == INTEL_LAYOUT_BELOW && level == mt->first_level + 1) ||
+          (mt->layout == INTEL_LAYOUT_RIGHT && level == mt->first_level)) {
+            x += ALIGN(width, mt->align_w);
+      } else {
+            y += img_height;
       }
 
       width  = minify(width);
diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.h b/src/mesa/drivers/dri/intel/intel_tex_layout.h
index 12ed16d..87c708e 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_layout.h
+++ b/src/mesa/drivers/dri/intel/intel_tex_layout.h
@@ -38,7 +38,8 @@ static INLINE GLuint minify( GLuint d )
    return MAX2(1, d>>1);
 }
 
-extern void i945_miptree_layout_2d(struct intel_mipmap_tree *mt);
+extern void i945_miptree_layout_2d(struct intel_context *intel,
+                                   struct intel_mipmap_tree *mt);
 
 void
 intel_get_texture_alignment_unit(struct intel_context *intel,
-- 
1.7.4.4



More information about the mesa-dev mailing list