summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c70
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h10
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texture.c36
3 files changed, 61 insertions, 55 deletions
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
index 39b6d50094e..a9d601a0b5f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
@@ -124,20 +124,19 @@ static GLuint minify(GLuint size, GLuint levels)
static void calculate_miptree_layout_r100(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
{
- GLuint curOffset;
- GLuint i;
- GLuint face;
+ GLuint curOffset, i, face, level;
assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
curOffset = 0;
for(face = 0; face < mt->faces; face++) {
- for(i = 0; i < mt->numLevels; i++) {
- mt->levels[i].width = minify(mt->width0, i);
- mt->levels[i].height = minify(mt->height0, i);
- mt->levels[i].depth = minify(mt->depth0, i);
- compute_tex_image_offset(rmesa, mt, face, i, &curOffset);
+ for(i = 0, level = mt->baseLevel; i < mt->numLevels; i++, level++) {
+ mt->levels[level].valid = 1;
+ mt->levels[level].width = minify(mt->width0, i);
+ mt->levels[level].height = minify(mt->height0, i);
+ mt->levels[level].depth = minify(mt->depth0, i);
+ compute_tex_image_offset(rmesa, mt, face, level, &curOffset);
}
}
@@ -147,21 +146,21 @@ static void calculate_miptree_layout_r100(radeonContextPtr rmesa, radeon_mipmap_
static void calculate_miptree_layout_r300(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
{
- GLuint curOffset;
- GLuint i;
+ GLuint curOffset, i, level;
assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
curOffset = 0;
- for(i = 0; i < mt->numLevels; i++) {
+ for(i = 0, level = mt->baseLevel; i < mt->numLevels; i++, level++) {
GLuint face;
- mt->levels[i].width = minify(mt->width0, i);
- mt->levels[i].height = minify(mt->height0, i);
- mt->levels[i].depth = minify(mt->depth0, i);
+ mt->levels[level].valid = 1;
+ mt->levels[level].width = minify(mt->width0, i);
+ mt->levels[level].height = minify(mt->height0, i);
+ mt->levels[level].depth = minify(mt->depth0, i);
for(face = 0; face < mt->faces; face++)
- compute_tex_image_offset(rmesa, mt, face, i, &curOffset);
+ compute_tex_image_offset(rmesa, mt, face, level, &curOffset);
}
/* Note the required size in memory */
@@ -277,18 +276,19 @@ static void calculate_min_max_lod(struct gl_texture_object *tObj,
* given face and level.
*/
GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
- struct gl_texture_image *texImage, GLuint face, GLuint mtLevel)
+ struct gl_texture_image *texImage, GLuint face, GLuint level)
{
radeon_mipmap_level *lvl;
- if (face >= mt->faces || mtLevel > mt->numLevels)
+ if (face >= mt->faces)
return GL_FALSE;
if (texImage->TexFormat != mt->mesaFormat)
return GL_FALSE;
- lvl = &mt->levels[mtLevel];
- if (lvl->width != texImage->Width ||
+ lvl = &mt->levels[level];
+ if (!lvl->valid ||
+ lvl->width != texImage->Width ||
lvl->height != texImage->Height ||
lvl->depth != texImage->Depth)
return GL_FALSE;
@@ -394,38 +394,17 @@ radeon_miptree_image_offset(radeon_mipmap_tree *mt,
}
/**
- * Convert radeon miptree texture level to GL texture level
- * @param[in] tObj texture object whom level is to be converted
- * @param[in] level radeon miptree texture level
- * @return GL texture level
- */
-unsigned radeon_miptree_level_to_gl_level(struct gl_texture_object *tObj, unsigned level)
-{
- return level + tObj->BaseLevel;
-}
-
-/**
- * Convert GL texture level to radeon miptree texture level
- * @param[in] tObj texture object whom level is to be converted
- * @param[in] level GL texture level
- * @return radeon miptree texture level
- */
-unsigned radeon_gl_level_to_miptree_level(struct gl_texture_object *tObj, unsigned level)
-{
- return level - tObj->BaseLevel;
-}
-
-/**
* Ensure that the given image is stored in the given miptree from now on.
*/
static void migrate_image_to_miptree(radeon_mipmap_tree *mt,
radeon_texture_image *image,
- int face, int mtLevel)
+ int face, int level)
{
- radeon_mipmap_level *dstlvl = &mt->levels[mtLevel];
+ radeon_mipmap_level *dstlvl = &mt->levels[level];
unsigned char *dest;
assert(image->mt != mt);
+ assert(dstlvl->valid);
assert(dstlvl->width == image->base.Width);
assert(dstlvl->height == image->base.Height);
assert(dstlvl->depth == image->base.Depth);
@@ -442,6 +421,7 @@ static void migrate_image_to_miptree(radeon_mipmap_tree *mt,
radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel];
+ assert(image->mtlevel == level);
assert(srclvl->size == dstlvl->size);
assert(srclvl->rowstride == dstlvl->rowstride);
@@ -479,7 +459,7 @@ static void migrate_image_to_miptree(radeon_mipmap_tree *mt,
radeon_miptree_reference(mt, &image->mt);
image->mtface = face;
- image->mtlevel = mtLevel;
+ image->mtlevel = level;
}
/**
@@ -603,7 +583,7 @@ int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *t
if (src_bo && radeon_bo_is_referenced_by_cs(src_bo, rmesa->cmdbuf.cs)) {
radeon_firevertices(rmesa);
}
- migrate_image_to_miptree(dst_miptree, img, face, radeon_gl_level_to_miptree_level(texObj, level));
+ migrate_image_to_miptree(dst_miptree, img, face, level);
} else if (RADEON_DEBUG & RADEON_TEXTURE) {
fprintf(stderr, "OK\n");
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
index 28b84850954..a10649b5aea 100644
--- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
@@ -44,6 +44,7 @@ struct _radeon_mipmap_level {
GLuint depth;
GLuint size; /** Size of each image, in bytes */
GLuint rowstride; /** in bytes */
+ GLuint valid;
radeon_mipmap_image faces[6];
};
@@ -70,9 +71,9 @@ struct _radeon_mipmap_tree {
GLuint baseLevel; /** gl_texture_object->baseLevel it was created for */
GLuint numLevels; /** Number of mip levels stored in this mipmap tree */
- GLuint width0; /** Width of firstLevel image */
- GLuint height0; /** Height of firstLevel image */
- GLuint depth0; /** Depth of firstLevel image */
+ GLuint width0; /** Width of baseLevel image */
+ GLuint height0; /** Height of baseLevel image */
+ GLuint depth0; /** Depth of baseLevel image */
GLuint tilebits; /** RADEON_TXO_xxx_TILE */
@@ -89,8 +90,5 @@ GLuint radeon_miptree_image_offset(radeon_mipmap_tree *mt,
GLuint face, GLuint level);
void radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets);
-unsigned radeon_miptree_level_to_gl_level(struct gl_texture_object *tObj, unsigned level);
-unsigned radeon_gl_level_to_miptree_level(struct gl_texture_object *tObj, unsigned level);
-
uint32_t get_base_teximage_offset(radeonTexObj *texObj);
#endif /* __RADEON_MIPMAP_TREE_H_ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c
index c715650d55f..0390d376ba2 100644
--- a/src/mesa/drivers/dri/radeon/radeon_texture.c
+++ b/src/mesa/drivers/dri/radeon/radeon_texture.c
@@ -509,6 +509,27 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
return MESA_FORMAT_NONE; /* never get here */
}
+/** Check if given image is valid within current texture object.
+ */
+static int image_matches_texture_obj(struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ unsigned level)
+{
+ const struct gl_texture_image *baseImage = texObj->Image[0][level];
+
+ if (level < texObj->BaseLevel || level > texObj->MaxLevel)
+ return 0;
+
+ const unsigned levelDiff = level - texObj->BaseLevel;
+ const unsigned refWidth = baseImage->Width >> levelDiff;
+ const unsigned refHeight = baseImage->Height >> levelDiff;
+ const unsigned refDepth = baseImage->Depth >> levelDiff;
+
+ return (texImage->Width == refWidth &&
+ texImage->Height == refHeight &&
+ texImage->Depth == refDepth);
+}
+
static void teximage_assign_miptree(radeonContextPtr rmesa,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
@@ -518,9 +539,14 @@ static void teximage_assign_miptree(radeonContextPtr rmesa,
radeonTexObj *t = radeon_tex_obj(texObj);
radeon_texture_image* image = get_radeon_texture_image(texImage);
+ /* Since miptree holds only images for levels <BaseLevel..MaxLevel>
+ * don't allocate the miptree if the teximage won't fit.
+ */
+ if (!image_matches_texture_obj(texObj, texImage, level))
+ return;
+
/* Try using current miptree, or create new if there isn't any */
- if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage, face,
- radeon_gl_level_to_miptree_level(texObj, level))) {
+ if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage, face, level)) {
radeon_miptree_unreference(&t->mt);
radeon_try_alloc_miptree(rmesa, t);
if (RADEON_DEBUG & RADEON_TEXTURE) {
@@ -534,7 +560,7 @@ static void teximage_assign_miptree(radeonContextPtr rmesa,
* when there was no image for baselevel specified */
if (t->mt) {
image->mtface = face;
- image->mtlevel = radeon_gl_level_to_miptree_level(texObj, level);
+ image->mtlevel = level;
radeon_miptree_reference(t->mt, &image->mt);
}
}
@@ -590,6 +616,8 @@ static void radeon_store_teximage(GLcontext* ctx, int dims,
dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
}
+ assert(dstRowStride);
+
if (dims == 3) {
unsigned alignedWidth = dstRowStride/_mesa_get_format_bytes(texImage->TexFormat);
dstImageOffsets = allocate_image_offsets(ctx, alignedWidth, texImage->Height, texImage->Depth);
@@ -704,7 +732,7 @@ static void radeon_teximage(
if (!t->bo) {
teximage_assign_miptree(rmesa, texObj, texImage, face, level);
- if (!t->mt) {
+ if (!image->mt) {
int size = _mesa_format_image_size(texImage->TexFormat,
texImage->Width,
texImage->Height,