summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2011-01-05 17:02:08 -0800
committerEric Anholt <eric@anholt.net>2011-01-05 18:23:54 -0800
commit7ce6517f3ac41bf770ab39aba4509d4f535ef663 (patch)
tree3563dc5da10a71f71981a0ceb5fdbd00b37a1f79
parent01b70c06284f3a0ab2de61228b73c78ed00a1a14 (diff)
intel: Always allocate miptrees from level 0, not tObj->BaseLevel.
BaseLevel/MaxLevel are mostly used for two things: clamping texture access for FBO rendering, and limiting the used mipmap levels when incrementally loading textures. By restricting our mipmap trees to just the current BaseLevel/MaxLevel, we caused reallocation thrashing in the common case, for a theoretical win if someone really did want just levels 2..4 or whatever of their texture object. Bug #30366
-rw-r--r--src/mesa/drivers/dri/i965/brw_tex_layout.c4
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_sampler_state.c11
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c10
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.c17
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.h6
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.h6
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_image.c125
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_layout.c6
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_validate.c27
9 files changed, 71 insertions, 141 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index 9ac0713a1d..66adc49cc9 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -67,7 +67,7 @@ GLboolean brw_miptree_layout(struct intel_context *intel,
i945_miptree_layout_2d(intel, mt, tiling, 6);
- for (level = mt->first_level; level <= mt->last_level; level++) {
+ for (level = 0; level < mt->levels; level++) {
for (q = 0; q < 6; q++) {
intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch);
}
@@ -101,7 +101,7 @@ GLboolean brw_miptree_layout(struct intel_context *intel,
pack_x_pitch = width;
pack_x_nr = 1;
- for (level = mt->first_level ; level <= mt->last_level ; level++) {
+ for (level = 0; level < mt->levels; level++) {
GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6;
GLint x = 0;
GLint y = 0;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c b/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c
index 30672b4251..f830e25626 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c
@@ -115,6 +115,7 @@ struct wm_sampler_key {
struct wm_sampler_entry {
GLenum tex_target;
GLenum wrap_r, wrap_s, wrap_t;
+ uint32_t base_level;
float maxlod, minlod;
float lod_bias;
float max_aniso;
@@ -243,14 +244,7 @@ static void brw_update_sampler_state(struct brw_context *brw,
sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
- /* Set BaseMipLevel, MaxLOD, MinLOD:
- *
- * XXX: I don't think that using firstLevel, lastLevel works,
- * because we always setup the surface state as if firstLevel ==
- * level zero. Probably have to subtract firstLevel from each of
- * these:
- */
- sampler->ss0.base_level = U_FIXED(0, 1);
+ sampler->ss0.base_level = U_FIXED(key->base_level, 1);
sampler->ss1.max_lod = U_FIXED(CLAMP(key->maxlod, 0, 13), 6);
sampler->ss1.min_lod = U_FIXED(CLAMP(key->minlod, 0, 13), 6);
@@ -292,6 +286,7 @@ brw_wm_sampler_populate_key(struct brw_context *brw,
entry->wrap_s = texObj->WrapS;
entry->wrap_t = texObj->WrapT;
+ entry->base_level = texObj->BaseLevel;
entry->maxlod = texObj->MaxLod;
entry->minlod = texObj->MinLod;
entry->lod_bias = texUnit->LodBias + texObj->LodBias;
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 3b59b0b98e..1769991306 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -181,15 +181,15 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit )
/* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
surf.ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */
+ /* mip_count is #levels - 1 */
surf.ss2.mip_count = intelObj->_MaxLevel - tObj->BaseLevel;
- surf.ss2.width = firstImage->Width - 1;
- surf.ss2.height = firstImage->Height - 1;
+ surf.ss2.width = intelObj->mt->width0 - 1;
+ surf.ss2.height = intelObj->mt->height0 - 1;
brw_set_surface_tiling(&surf, intelObj->mt->region->tiling);
surf.ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1;
- surf.ss3.depth = firstImage->Depth - 1;
+ surf.ss3.depth = intelObj->mt->depth0 - 1;
+ surf.ss4.min_lod = tObj->BaseLevel;
- surf.ss4.min_lod = 0;
-
if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
surf.ss0.cube_pos_x = 1;
surf.ss0.cube_pos_y = 1;
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index a3409274fb..2ced6ac86b 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -56,8 +56,7 @@ static struct intel_mipmap_tree *
intel_miptree_create_internal(struct intel_context *intel,
GLenum target,
GLenum internal_format,
- GLuint first_level,
- GLuint last_level,
+ GLuint levels,
GLuint width0,
GLuint height0,
GLuint depth0, GLuint cpp, GLuint compress_byte,
@@ -66,15 +65,14 @@ intel_miptree_create_internal(struct intel_context *intel,
GLboolean ok;
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
- DBG("%s target %s format %s level %d..%d <-- %p\n", __FUNCTION__,
+ DBG("%s target %s format %s levels %d <-- %p\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
_mesa_lookup_enum_by_nr(internal_format),
- first_level, last_level, mt);
+ levels, mt);
mt->target = target_to_target(target);
mt->internal_format = internal_format;
- mt->first_level = first_level;
- mt->last_level = last_level;
+ mt->levels = levels;
mt->width0 = width0;
mt->height0 = height0;
mt->depth0 = depth0;
@@ -106,8 +104,7 @@ intel_miptree_create(struct intel_context *intel,
GLenum target,
GLenum base_format,
GLenum internal_format,
- GLuint first_level,
- GLuint last_level,
+ GLuint levels,
GLuint width0,
GLuint height0,
GLuint depth0, GLuint cpp, GLuint compress_byte,
@@ -126,7 +123,7 @@ intel_miptree_create(struct intel_context *intel,
}
mt = intel_miptree_create_internal(intel, target, internal_format,
- first_level, last_level, width0,
+ levels, width0,
height0, depth0, cpp, compress_byte,
tiling);
/*
@@ -164,7 +161,7 @@ intel_miptree_create_for_region(struct intel_context *intel,
struct intel_mipmap_tree *mt;
mt = intel_miptree_create_internal(intel, target, internal_format,
- 0, 0,
+ 1,
region->width, region->height, 1,
region->cpp, compress_byte,
I915_TILING_NONE);
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 760a8bce60..4bb90bf4ac 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -93,8 +93,7 @@ struct intel_mipmap_tree
GLenum target;
GLenum internal_format;
- GLuint first_level;
- GLuint last_level;
+ GLuint levels;
GLuint width0, height0, depth0; /**< Level zero image dimensions */
GLuint cpp;
@@ -124,8 +123,7 @@ struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel,
GLenum target,
GLenum base_format,
GLenum internal_format,
- GLuint first_level,
- GLuint last_level,
+ GLuint levels,
GLuint width0,
GLuint height0,
GLuint depth0,
diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h
index 6552ed0d33..7c76bd48c6 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.h
+++ b/src/mesa/drivers/dri/intel/intel_tex.h
@@ -65,4 +65,10 @@ void intel_tex_unmap_images(struct intel_context *intel,
int intel_compressed_num_bytes(GLuint mesaFormat);
+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);
+
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 918740a773..e0d4ca762f 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -44,24 +44,12 @@ logbase2(int n)
return log2;
}
-
-/* Otherwise, store it in memory if (Border != 0) or (any dimension ==
- * 1).
- *
- * Otherwise, if max_level >= level >= min_level, create tree with
- * space for textures from min_level down to max_level.
- *
- * Otherwise, create tree with space for textures from (level
- * 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)
+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;
GLuint width = intelImage->base.Width;
GLuint height = intelImage->base.Height;
@@ -72,28 +60,11 @@ guess_and_alloc_mipmap_tree(struct intel_context *intel,
DBG("%s\n", __FUNCTION__);
if (intelImage->base.Border)
- return;
-
- 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;
-
+ return NULL;
/* Figure out image dimensions at start level.
*/
- for (i = intelImage->level; i > firstLevel; i--) {
+ for (i = intelImage->level; i > 0; i--) {
width <<= 1;
if (height != 1)
height <<= 1;
@@ -108,34 +79,29 @@ guess_and_alloc_mipmap_tree(struct intel_context *intel,
*/
if ((intelObj->base.MinFilter == GL_NEAREST ||
intelObj->base.MinFilter == GL_LINEAR) &&
- intelImage->level == firstLevel &&
- (intel->gen < 4 || firstLevel == 0)) {
- lastLevel = firstLevel;
+ intelImage->level == 0) {
+ lastLevel = 0;
}
else {
- lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth));
+ lastLevel = 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,
+ lastLevel + 1,
+ width,
+ height,
+ depth,
+ texelBytes,
+ comp_byte,
+ expect_accelerated_upload);
}
@@ -343,41 +309,23 @@ 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)) {
-
+ if (intelObj->mt && intel_miptree_match_image(intelObj->mt,
+ &intelImage->base)) {
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);
+ } else {
+ intel_miptree_release(intel, &intelImage->mt);
+ intelImage->mt = intel_miptree_create_for_teximage(intel, intelObj,
+ intelImage,
+ pixels == NULL);
+ if (!intelImage->mt) {
+ DBG("guess_and_alloc_mipmap_tree: failed\n");
}
- /* 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.
+ /* Speculatively set up the object with this miptree so that the
+ * later levels can just load into the miptree we just made.
*/
- intelImage->mt = intel_miptree_create(intel, target,
- baseFormat,
- internalFormat,
- level, level,
- width, height, depth,
- texelBytes,
- comp_byte, pixels == NULL);
-
+ if (!intelObj->mt && intelImage->mt)
+ intel_miptree_reference(&intelObj->mt, intelImage->mt);
}
/* PBO fastpaths:
@@ -396,10 +344,7 @@ intelTexImage(struct gl_context * ctx,
* performance (in particular when intel_region_cow() is
* required).
*/
- if (intelObj->mt == intelImage->mt &&
- intelObj->mt->first_level == level &&
- intelObj->mt->last_level == level) {
-
+ if (intelImage->mt->levels == 1) {
if (try_pbo_zcopy(intel, intelImage, unpack,
internalFormat,
width, height, format, type, pixels)) {
diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c
index d39733b6c5..540ef36a41 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_layout.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c
@@ -86,7 +86,7 @@ void i945_miptree_layout_2d(struct intel_context *intel,
* constraints of mipmap placement push the right edge of the
* 2nd mipmap out past the width of its parent.
*/
- if (mt->first_level != mt->last_level) {
+ if (mt->levels > 1) {
GLuint mip1_width;
if (mt->compressed) {
@@ -104,7 +104,7 @@ void i945_miptree_layout_2d(struct intel_context *intel,
mt->total_height = 0;
- for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
+ for (level = 0; level < mt->levels; level++) {
GLuint img_height;
intel_miptree_set_level_info(mt, level, nr_images, x, y, width,
@@ -123,7 +123,7 @@ void i945_miptree_layout_2d(struct intel_context *intel,
/* Layout_below: step right after second mipmap.
*/
- if (level == mt->first_level + 1) {
+ if (level == 1) {
x += ALIGN(width, align_w);
}
else {
diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c
index 4d257cc71d..f1c6239d3d 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_validate.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c
@@ -104,8 +104,7 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
*/
if (firstImage->mt &&
firstImage->mt != intelObj->mt &&
- firstImage->mt->first_level <= tObj->BaseLevel &&
- firstImage->mt->last_level >= intelObj->_MaxLevel) {
+ firstImage->mt->levels >= intelObj->_MaxLevel) {
if (intelObj->mt)
intel_miptree_release(intel, &intelObj->mt);
@@ -132,11 +131,10 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
if (intelObj->mt &&
(intelObj->mt->target != intelObj->base.Target ||
intelObj->mt->internal_format != firstImage->base.InternalFormat ||
- intelObj->mt->first_level != tObj->BaseLevel ||
- intelObj->mt->last_level != intelObj->_MaxLevel ||
- intelObj->mt->width0 != firstImage->base.Width ||
- intelObj->mt->height0 != firstImage->base.Height ||
- intelObj->mt->depth0 != firstImage->base.Depth ||
+ intelObj->mt->levels <= intelObj->_MaxLevel ||
+ intelObj->mt->width0 != firstImage->mt->width0 ||
+ intelObj->mt->height0 != firstImage->mt->height0 ||
+ intelObj->mt->depth0 != firstImage->mt->depth0 ||
intelObj->mt->cpp != cpp ||
intelObj->mt->compressed != _mesa_is_format_compressed(firstImage->base.TexFormat))) {
intel_miptree_release(intel, &intelObj->mt);
@@ -146,18 +144,9 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
/* May need to create a new tree:
*/
if (!intelObj->mt) {
- intelObj->mt = intel_miptree_create(intel,
- intelObj->base.Target,
- firstImage->base._BaseFormat,
- firstImage->base.InternalFormat,
- tObj->BaseLevel,
- intelObj->_MaxLevel,
- firstImage->base.Width,
- firstImage->base.Height,
- firstImage->base.Depth,
- cpp,
- comp_byte,
- GL_TRUE);
+ intelObj->mt = intel_miptree_create_for_teximage(intel, intelObj,
+ firstImage,
+ GL_TRUE);
}
/* Pull in any images not in the object's tree: