From b9f3f732aaec97aac2a725a4f0b1244ebac61c7f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Dec 2007 22:43:48 -0800 Subject: [PATCH] i915tex: Centralize mipmap pitch computations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. (cherry picked from commit a183efc132c8db1bb42525ac177ffff96f69a59b with manual changes for mesa_7_0_branch by Michel Dänzer. One side effect of this is that i965 also aligns the pitch of 2D textures to multiples of 64 bytes, hopefully that won't cause any issues) --- .../drivers/dri/i915tex/i915_tex_layout.c | 16 ++--- .../drivers/dri/i915tex/intel_mipmap_tree.c | 59 +++++++++++++------ .../drivers/dri/i915tex/intel_mipmap_tree.h | 10 +++- src/mesa/drivers/dri/i965/brw_tex_layout.c | 4 +- src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 2 +- src/mesa/drivers/dri/i965/intel_mipmap_tree.h | 3 +- src/mesa/drivers/dri/intel/intel_tex_layout.c | 4 +- src/mesa/drivers/dri/intel/intel_tex_layout.h | 2 +- 8 files changed, 64 insertions(+), 36 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/i915_tex_layout.c b/src/mesa/drivers/dri/i915tex/i915_tex_layout.c index 7b761a7b221..dfd02112bad 100644 --- a/src/mesa/drivers/dri/i915tex/i915_tex_layout.c +++ b/src/mesa/drivers/dri/i915tex/i915_tex_layout.c @@ -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()"); diff --git a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c index 564eb9e0197..d33a7d409b2 100644 --- a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c @@ -75,6 +75,7 @@ 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; switch (intel->intelScreen->deviceID) { case PCI_CHIP_I945_G: @@ -83,7 +84,7 @@ intel_miptree_create(struct intel_context *intel, case PCI_CHIP_G33_G: case PCI_CHIP_Q33_G: case PCI_CHIP_Q35_G: - ok = i945_miptree_layout(mt); + ok = i945_miptree_layout(intel, mt); break; case PCI_CHIP_I915_G: case PCI_CHIP_I915_GM: @@ -93,28 +94,12 @@ intel_miptree_create(struct intel_context *intel, default: /* All the i830 chips and the i915 use this layout: */ - ok = i915_miptree_layout(mt); + ok = i915_miptree_layout(intel, mt); break; } if (ok) { - if (!mt->compressed) { - /* 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. - */ - mt->pitch = (mt->pitch * cpp + 63) & ~63; - - /* 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 64 for now. - */ - if (!(mt->pitch & 511)) - mt->pitch += 64; - - mt->pitch /= cpp; - } + assert (mt->pitch); mt->region = intel_region_alloc(intel->intelScreen, mt->cpp, mt->pitch, mt->total_height); @@ -128,6 +113,42 @@ 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) { + /* 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 = (pitch * mt->cpp + 63) & ~63; + + /* 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 += 64; + + pitch /= mt->cpp; + } + return pitch; +} void intel_miptree_reference(struct intel_mipmap_tree **dst, diff --git a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.h b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.h index ecdb7be244f..0f068fb57ea 100644 --- a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.h @@ -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,10 @@ 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 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); diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index af1ad0f1ef1..d4888a42fbf 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -38,7 +38,7 @@ #include "macros.h" -GLboolean brw_miptree_layout( struct intel_mipmap_tree *mt ) +GLboolean brw_miptree_layout( struct intel_context *intel, struct intel_mipmap_tree *mt ) { /* XXX: these vary depending on image format: */ @@ -102,7 +102,7 @@ GLboolean brw_miptree_layout( struct intel_mipmap_tree *mt ) } default: - i945_miptree_layout_2d(mt); + i945_miptree_layout_2d(intel, mt); break; } DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__, diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c index 8486086b274..af8d56e015f 100644 --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c @@ -91,7 +91,7 @@ struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel, default: if (INTEL_DEBUG & DEBUG_TEXTURE) _mesa_printf("assuming BRW texture layouts\n"); - ok = brw_miptree_layout( mt ); + ok = brw_miptree_layout( intel, mt ); break; } diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h index dbd7167b778..2f99f6fc74d 100644 --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h @@ -159,7 +159,8 @@ GLboolean intel_miptree_image_data(struct intel_context *intel, */ 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 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 fcb5cc39068..39a443c4f9f 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.c +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -40,7 +40,7 @@ static int align(int value, int alignment) return (value + alignment - 1) & ~(alignment - 1); } -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; @@ -67,7 +67,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++ ) { diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.h b/src/mesa/drivers/dri/intel/intel_tex_layout.h index 1e37f8f525f..46151dbb7a6 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.h +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.h @@ -38,4 +38,4 @@ 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 );