[Intel] Centralize mipmap pitch computations.
authorKeith Packard <keithp@keithp.com>
Tue, 18 Dec 2007 06:43:48 +0000 (22:43 -0800)
committerKeith Packard <keithp@keithp.com>
Tue, 18 Dec 2007 18:22:04 +0000 (10:22 -0800)
mipmap pitches must account for the device alignment requirements, which
used to be fairly simple; just align to a 4-byte boundary. However, to allow
textures to be drawn to under TTM, they now need to be aligned to a 64-byte
boundary. Placing all of the alignment constraints in a single function
allows this new constraint to be applied uniformly.

There was some pitch constraining code in intel_miptree_create, but that was
modifying the pitch long after the miptree had been layed out, so it only
served to wreck the mipmap and cause rendering errors.

src/mesa/drivers/dri/i915/i915_tex_layout.c
src/mesa/drivers/dri/intel/intel_mipmap_tree.c
src/mesa/drivers/dri/intel/intel_mipmap_tree.h
src/mesa/drivers/dri/intel/intel_tex_layout.c
src/mesa/drivers/dri/intel/intel_tex_layout.h

index 7b761a7b2214637721d23b7d36d078b32e6ff0fd..dfd02112badbba59d3bfc93ea2d4c71388ffc2d2 100644 (file)
@@ -54,7 +54,7 @@ static GLint step_offsets[6][2] = { {0, 2},
 };
 
 GLboolean
-i915_miptree_layout(struct intel_mipmap_tree * mt)
+i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
 {
    GLint level;
 
@@ -67,7 +67,7 @@ i915_miptree_layout(struct intel_mipmap_tree * mt)
          assert(lvlWidth == lvlHeight); /* cubemap images are square */
 
          /* double pitch for cube layouts */
-         mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
+         mt->pitch = intel_miptree_pitch_align (intel, mt, dim * 2);
          mt->total_height = dim * 4;
 
          for (level = mt->first_level; level <= mt->last_level; level++) {
@@ -107,7 +107,7 @@ i915_miptree_layout(struct intel_mipmap_tree * mt)
 
          /* Calculate the size of a single slice. 
           */
-         mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+         mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
 
          /* XXX: hardware expects/requires 9 levels at minimum.
           */
@@ -150,7 +150,7 @@ i915_miptree_layout(struct intel_mipmap_tree * mt)
          GLuint height = mt->height0;
         GLuint img_height;
 
-         mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+         mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
          mt->total_height = 0;
 
          for (level = mt->first_level; level <= mt->last_level; level++) {
@@ -180,7 +180,7 @@ i915_miptree_layout(struct intel_mipmap_tree * mt)
 
 
 GLboolean
-i945_miptree_layout(struct intel_mipmap_tree * mt)
+i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
 {
    GLint level;
 
@@ -197,7 +197,7 @@ i945_miptree_layout(struct intel_mipmap_tree * mt)
           * or the final row of 4x4, 2x2 and 1x1 faces below this. 
           */
          if (dim > 32)
-            mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
+            mt->pitch = intel_miptree_pitch_align (intel, mt, dim);
          else
             mt->pitch = 14 * 8;
 
@@ -279,7 +279,7 @@ i945_miptree_layout(struct intel_mipmap_tree * mt)
          GLuint pack_y_pitch;
          GLuint level;
 
-         mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+         mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
          mt->total_height = 0;
 
          pack_y_pitch = MAX2(mt->height0, 2);
@@ -329,7 +329,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()");
index 3517939066ff5e05ae716fe1ed999a53035703d4..6610771b6e29fa6808dbca6b95fcbe42f57078c1 100644 (file)
@@ -78,44 +78,19 @@ intel_miptree_create(struct intel_context *intel,
    mt->cpp = compress_byte ? compress_byte : cpp;
    mt->compressed = compress_byte ? 1 : 0;
    mt->refcount = 1; 
+   mt->pitch = 0;
 
 #ifdef I915
    if (IS_945(intel->intelScreen->deviceID))
-      ok = i945_miptree_layout(mt);
+      ok = i945_miptree_layout(intel, mt);
    else
-      ok = i915_miptree_layout(mt);
+      ok = i915_miptree_layout(intel, mt);
 #else
-   ok = brw_miptree_layout(mt);
+   ok = brw_miptree_layout(intel, mt);
 #endif
 
    if (ok) {
-#ifdef I915
-      if (!mt->compressed) {
-        int align;
-
-        if (intel->ttm) {
-           /* XXX: Align pitch to multiple of 64 bytes for now to allow
-            * render-to-texture to work in all cases. This should probably be
-            * replaced at some point by some scheme to only do this when really
-            * necessary.
-            */
-           align = 63;
-        } else {
-           align = 3;
-        }
-
-        mt->pitch = (mt->pitch * cpp + align) & ~align;
-
-        /* XXX: At least the i915 seems very upset when the pitch is a multiple
-         * of 1024 and sometimes 512 bytes - performance can drop by several
-         * times. Go to the next multiple of the required alignment for now.
-         */
-        if (!(mt->pitch & 511))
-           mt->pitch += align + 1;
-
-        mt->pitch /= cpp;
-      }
-#endif /* I915 */
+      assert (mt->pitch);
 
       mt->region = intel_region_alloc(intel,
                                       mt->cpp, mt->pitch, mt->total_height);
@@ -129,6 +104,52 @@ intel_miptree_create(struct intel_context *intel,
    return mt;
 }
 
+/**
+ * intel_miptree_pitch_align:
+ *
+ * @intel: intel context pointer
+ *
+ * @mt: the miptree to compute pitch alignment for
+ *
+ * @pitch: the natural pitch value
+ *
+ * Given @pitch, compute a larger value which accounts for
+ * any necessary alignment required by the device
+ */
+
+int intel_miptree_pitch_align (struct intel_context *intel,
+                              struct intel_mipmap_tree *mt,
+                              int pitch)
+{
+   if (!mt->compressed) {
+      int pitch_align;
+
+      if (intel->ttm) {
+        /* XXX: Align pitch to multiple of 64 bytes for now to allow
+         * render-to-texture to work in all cases. This should probably be
+         * replaced at some point by some scheme to only do this when really
+         * necessary.
+         */
+        pitch_align = 64;
+      } else {
+        pitch_align = 4;
+      }
+
+      pitch = ALIGN(pitch * mt->cpp, pitch_align);
+
+#ifdef I915
+      /* XXX: At least the i915 seems very upset when the pitch is a multiple
+       * of 1024 and sometimes 512 bytes - performance can drop by several
+       * times. Go to the next multiple of the required alignment for now.
+       */
+      if (!(pitch & 511))
+        pitch += pitch_align;
+#endif
+
+      pitch /= mt->cpp;
+   }
+   return pitch;
+}
 
 void
 intel_miptree_reference(struct intel_mipmap_tree **dst,
index 4a76717688f81152b3c4f72d75a8ce6fed07b0b9..968eec4fec3280032e69889452ff95b4cab76a77 100644 (file)
@@ -123,6 +123,10 @@ struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel,
                                                GLuint cpp,
                                                GLuint compress_byte);
 
+int intel_miptree_pitch_align (struct intel_context *intel,
+                              struct intel_mipmap_tree *mt,
+                              int pitch);
+
 void intel_miptree_reference(struct intel_mipmap_tree **dst,
                              struct intel_mipmap_tree *src);
 
@@ -190,8 +194,11 @@ void intel_miptree_image_copy(struct intel_context *intel,
 
 /* i915_mipmap_tree.c:
  */
-GLboolean i915_miptree_layout(struct intel_mipmap_tree *mt);
-GLboolean i945_miptree_layout(struct intel_mipmap_tree *mt);
-GLboolean brw_miptree_layout(struct intel_mipmap_tree *mt);
+GLboolean i915_miptree_layout(struct intel_context *intel,
+                             struct intel_mipmap_tree *mt);
+GLboolean i945_miptree_layout(struct intel_context *intel,
+                             struct intel_mipmap_tree *mt);
+GLboolean brw_miptree_layout(struct intel_context *intel,
+                            struct intel_mipmap_tree *mt);
 
 #endif
index 4da636021baa659e4b0e0b8a833e77cd5e18d2ae..edc3a2eaa47a575b32ef65246ba94fbabd5846aa 100644 (file)
@@ -52,7 +52,7 @@ GLuint intel_compressed_alignment(GLenum internalFormat)
     return alignment;
 }
 
-void i945_miptree_layout_2d( struct intel_mipmap_tree *mt )
+void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tree *mt )
 {
    GLint align_h = 2, align_w = 4;
    GLuint level;
@@ -92,7 +92,7 @@ void i945_miptree_layout_2d( struct intel_mipmap_tree *mt )
    /* Pitch must be a whole number of dwords, even though we
     * express it in texels.
     */
-   mt->pitch = ALIGN(mt->pitch * mt->cpp, 4) / mt->cpp;
+   mt->pitch = intel_miptree_pitch_align (intel, mt, mt->pitch);
    mt->total_height = 0;
 
    for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
index 99d41c3629e4444ae5246b62db8de5c7ca3b8222..193699d3f708f3a3da7f2773265915b29f17d1f4 100644 (file)
@@ -38,5 +38,5 @@ static 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 );
 extern GLuint intel_compressed_alignment(GLenum);