From a183efc132c8db1bb42525ac177ffff96f69a59b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Dec 2007 22:43:48 -0800 Subject: [PATCH] [Intel] Centralize mipmap pitch computations. 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 | 16 ++-- .../drivers/dri/intel/intel_mipmap_tree.c | 81 ++++++++++++------- .../drivers/dri/intel/intel_mipmap_tree.h | 13 ++- src/mesa/drivers/dri/intel/intel_tex_layout.c | 4 +- src/mesa/drivers/dri/intel/intel_tex_layout.h | 2 +- 5 files changed, 72 insertions(+), 44 deletions(-) diff --git a/src/mesa/drivers/dri/i915/i915_tex_layout.c b/src/mesa/drivers/dri/i915/i915_tex_layout.c index 7b761a7b221..dfd02112bad 100644 --- a/src/mesa/drivers/dri/i915/i915_tex_layout.c +++ b/src/mesa/drivers/dri/i915/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/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 3517939066f..6610771b6e2 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -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, diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 4a76717688f..968eec4fec3 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/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,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 diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c index 4da636021ba..edc3a2eaa47 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.c +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -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++ ) { diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.h b/src/mesa/drivers/dri/intel/intel_tex_layout.h index 99d41c3629e..193699d3f70 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.h +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.h @@ -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); -- 2.30.2