intel: When making a new teximage miptree, make a full one.
If we hit this path, we're level 1+ and the base level got allocated as a single level instead of a full tree (so we don't match intelObj->mt). This tries to recover from that so that we end up with 2 allocations and 1 validation blit (old -> new) instead of allocations equal to number of levels and levels - 1 blits.
This commit is contained in:
parent
bd4a2e9209
commit
48024fb44c
|
@ -56,11 +56,11 @@ logbase2(int n)
|
|||
* 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)
|
||||
static 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;
|
||||
|
@ -73,70 +73,71 @@ guess_and_alloc_mipmap_tree(struct intel_context *intel,
|
|||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (intelImage->base.Border)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
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;
|
||||
intelImage->base.Depth == 1))) {
|
||||
/* For this combination, we're at some lower mipmap level and
|
||||
* some important dimension is 1. We can't extrapolate up to a
|
||||
* likely base level width/height/depth for a full mipmap stack
|
||||
* from this info, so just allocate this one level.
|
||||
*/
|
||||
firstLevel = intelImage->level;
|
||||
lastLevel = intelImage->level;
|
||||
} else {
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
/* Figure out image dimensions at start level. */
|
||||
for (i = intelImage->level; i > firstLevel; i--) {
|
||||
width <<= 1;
|
||||
if (height != 1)
|
||||
height <<= 1;
|
||||
if (depth != 1)
|
||||
depth <<= 1;
|
||||
}
|
||||
|
||||
|
||||
/* Figure out image dimensions at start level.
|
||||
*/
|
||||
for (i = intelImage->level; i > firstLevel; i--) {
|
||||
width <<= 1;
|
||||
if (height != 1)
|
||||
height <<= 1;
|
||||
if (depth != 1)
|
||||
depth <<= 1;
|
||||
/* Guess a reasonable value for lastLevel. This is probably going
|
||||
* to be wrong fairly often and might mean that we have to look at
|
||||
* resizable buffers, or require that buffers implement lazy
|
||||
* pagetable arrangements.
|
||||
*/
|
||||
if ((intelObj->base.MinFilter == GL_NEAREST ||
|
||||
intelObj->base.MinFilter == GL_LINEAR) &&
|
||||
intelImage->level == firstLevel &&
|
||||
(intel->gen < 4 || firstLevel == 0)) {
|
||||
lastLevel = firstLevel;
|
||||
} else {
|
||||
lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth));
|
||||
}
|
||||
}
|
||||
|
||||
/* Guess a reasonable value for lastLevel. This is probably going
|
||||
* to be wrong fairly often and might mean that we have to look at
|
||||
* resizable buffers, or require that buffers implement lazy
|
||||
* pagetable arrangements.
|
||||
*/
|
||||
if ((intelObj->base.MinFilter == GL_NEAREST ||
|
||||
intelObj->base.MinFilter == GL_LINEAR) &&
|
||||
intelImage->level == firstLevel &&
|
||||
(intel->gen < 4 || firstLevel == 0)) {
|
||||
lastLevel = firstLevel;
|
||||
}
|
||||
else {
|
||||
lastLevel = firstLevel + 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,
|
||||
firstLevel,
|
||||
lastLevel,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
texelBytes,
|
||||
comp_byte,
|
||||
expect_accelerated_upload);
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,41 +345,29 @@ 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)) {
|
||||
|
||||
/* Use an existing miptree when possible */
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
intelImage->mt = intel_miptree_create(intel, target,
|
||||
baseFormat,
|
||||
internalFormat,
|
||||
level, level,
|
||||
width, height, depth,
|
||||
texelBytes,
|
||||
comp_byte, pixels == NULL);
|
||||
intelImage->mt = intel_miptree_create_for_teximage(intel, intelObj,
|
||||
intelImage,
|
||||
pixels == NULL);
|
||||
|
||||
/* Even if the object currently has a mipmap tree associated
|
||||
* with it, this one is a more likely candidate to represent the
|
||||
* whole object since our level didn't fit what was there
|
||||
* before, and any lower levels would fit into our miptree.
|
||||
*/
|
||||
if (intelImage->mt)
|
||||
intel_miptree_reference(&intelObj->mt, intelImage->mt);
|
||||
}
|
||||
|
||||
/* PBO fastpaths:
|
||||
|
|
Loading…
Reference in New Issue