Mesa (mesa_7_7_branch): radeon: rework mipmap tree

Maciej Cencora osiris at kemper.freedesktop.org
Wed Nov 18 21:23:03 UTC 2009


Module: Mesa
Branch: mesa_7_7_branch
Commit: 23ec7c457483aae1e0d399e9b570f1860c27c780
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=23ec7c457483aae1e0d399e9b570f1860c27c780

Author: Maciej Cencora <m.cencora at gmail.com>
Date:   Sat Nov 14 16:55:39 2009 +0100

radeon: rework mipmap tree

---

 src/mesa/drivers/dri/r300/r300_cmdbuf.c            |    2 +-
 src/mesa/drivers/dri/r300/r300_tex.c               |    6 -
 src/mesa/drivers/dri/r300/r300_texstate.c          |    8 +-
 .../drivers/dri/radeon/radeon_common_context.h     |    4 +
 src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c   |  474 +++++++++++++-------
 src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h   |   24 +-
 src/mesa/drivers/dri/radeon/radeon_texture.c       |  243 +++--------
 src/mesa/drivers/dri/radeon/radeon_texture.h       |    3 +-
 8 files changed, 400 insertions(+), 364 deletions(-)

diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
index 8a56b9e..4b5ed2d 100644
--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c
+++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
@@ -169,7 +169,7 @@ static void emit_tex_offsets(GLcontext *ctx, struct radeon_state_atom * atom)
 		if (t && !t->image_override) {
 			BEGIN_BATCH_NO_AUTOSTATE(4);
 			OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
-			OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
+			OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, get_base_teximage_offset(t),
 					RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
 			END_BATCH();
 		} else if (!t) {
diff --git a/src/mesa/drivers/dri/r300/r300_tex.c b/src/mesa/drivers/dri/r300/r300_tex.c
index 7e94e93..726b3ff 100644
--- a/src/mesa/drivers/dri/r300/r300_tex.c
+++ b/src/mesa/drivers/dri/r300/r300_tex.c
@@ -223,12 +223,6 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
 	case GL_TEXTURE_MAX_LEVEL:
 	case GL_TEXTURE_MIN_LOD:
 	case GL_TEXTURE_MAX_LOD:
-		/* This isn't the most efficient solution but there doesn't appear to
-		 * be a nice alternative.  Since there's no LOD clamping,
-		 * we just have to rely on loading the right subset of mipmap levels
-		 * to simulate a clamped LOD.
-		 */
-		radeon_miptree_unreference(&t->mt);
 		t->validated = GL_FALSE;
 		break;
 
diff --git a/src/mesa/drivers/dri/r300/r300_texstate.c b/src/mesa/drivers/dri/r300/r300_texstate.c
index 7b1adcf..e6f2c0c 100644
--- a/src/mesa/drivers/dri/r300/r300_texstate.c
+++ b/src/mesa/drivers/dri/r300/r300_texstate.c
@@ -203,9 +203,7 @@ void r300SetDepthTexMode(struct gl_texture_object *tObj)
 static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
 {
 	const struct gl_texture_image *firstImage;
-	int firstlevel = t->mt ? t->mt->firstLevel : 0;
-	    
-	firstImage = t->base.Image[0][firstlevel];
+	firstImage = t->base.Image[0][t->minLod];
 
 	if (!t->image_override
 	    && VALID_FORMAT(firstImage->TexFormat)) {
@@ -228,7 +226,7 @@ static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
 	t->pp_txsize = (((R300_TX_WIDTHMASK_MASK & ((firstImage->Width - 1) << R300_TX_WIDTHMASK_SHIFT)))
 			| ((R300_TX_HEIGHTMASK_MASK & ((firstImage->Height - 1) << R300_TX_HEIGHTMASK_SHIFT)))
 			| ((R300_TX_DEPTHMASK_MASK & ((firstImage->DepthLog2) << R300_TX_DEPTHMASK_SHIFT)))
-			| ((R300_TX_MAX_MIP_LEVEL_MASK & ((t->mt->lastLevel - t->mt->firstLevel) << R300_TX_MAX_MIP_LEVEL_SHIFT))));
+			| ((R300_TX_MAX_MIP_LEVEL_MASK & ((t->maxLod - t->minLod) << R300_TX_MAX_MIP_LEVEL_SHIFT))));
 
 	t->tile_bits = 0;
 
@@ -239,7 +237,7 @@ static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
 
 
 	if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
-		unsigned int align = (64 / t->mt->bpp) - 1;
+		unsigned int align = (64 / _mesa_get_format_bytes(firstImage->TexFormat)) - 1;
 		t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
 		if (!t->image_override)
 			t->pp_txpitch = ((firstImage->Width + align) & ~align) - 1;
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index 5a0678b..ded81ff 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -208,6 +208,10 @@ struct radeon_tex_obj {
 	 * and so on.
 	 */
 	GLboolean validated;
+	/* Minimum LOD to be used during rendering */
+	unsigned minLod;
+	/* Miximum LOD to be used during rendering */
+	unsigned maxLod;
 
 	GLuint override_offset;
 	GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
index f635f58..f01136b 100644
--- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2009 Maciej Cencora.
  * Copyright (C) 2008 Nicolai Haehnle.
  *
  * All Rights Reserved.
@@ -32,10 +33,14 @@
 
 #include "main/simple_list.h"
 #include "main/texcompress.h"
+#include "main/teximage.h"
+/* TODO: remove if texture completeness check is removed */
+#include "main/texobj.h"
+#include "radeon_texture.h"
 
 static GLuint radeon_compressed_texture_size(GLcontext *ctx,
 		GLsizei width, GLsizei height, GLsizei depth,
-		GLuint mesaFormat)
+		gl_format mesaFormat)
 {
 	GLuint size = _mesa_format_image_size(mesaFormat, width, height, depth);
 
@@ -55,29 +60,6 @@ static GLuint radeon_compressed_texture_size(GLcontext *ctx,
 	return size;
 }
 
-
-static int radeon_compressed_num_bytes(GLuint mesaFormat)
-{
-   int bytes = 0;
-   switch(mesaFormat) {
-     
-   case MESA_FORMAT_RGB_FXT1:
-   case MESA_FORMAT_RGBA_FXT1:
-   case MESA_FORMAT_RGB_DXT1:
-   case MESA_FORMAT_RGBA_DXT1:
-     bytes = 2;
-     break;
-     
-   case MESA_FORMAT_RGBA_DXT3:
-   case MESA_FORMAT_RGBA_DXT5:
-     bytes = 4;
-   default:
-     break;
-   }
-   
-   return bytes;
-}
-
 /**
  * Compute sizes and fill in offset and blit information for the given
  * image (determined by \p face and \p level).
@@ -92,25 +74,24 @@ static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree
 	uint32_t row_align;
 
 	/* Find image size in bytes */
-	if (mt->compressed) {
+	if (_mesa_is_format_compressed(mt->mesaFormat)) {
 		/* TODO: Is this correct? Need test cases for compressed textures! */
 		row_align = rmesa->texture_compressed_row_align - 1;
-		lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
-		lvl->size = radeon_compressed_texture_size(mt->radeon->glCtx,
-							   lvl->width, lvl->height, lvl->depth, mt->compressed);
+		lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) + row_align) & ~row_align;
+		lvl->size = radeon_compressed_texture_size(rmesa->glCtx, lvl->width, lvl->height, lvl->depth, mt->mesaFormat);
 	} else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
 		row_align = rmesa->texture_rect_row_align - 1;
-		lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
+		lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) + row_align) & ~row_align;
 		lvl->size = lvl->rowstride * lvl->height;
 	} else if (mt->tilebits & RADEON_TXO_MICRO_TILE) {
 		/* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
 		 * though the actual offset may be different (if texture is less than
 		 * 32 bytes width) to the untiled case */
-		lvl->rowstride = (lvl->width * mt->bpp * 2 + 31) & ~31;
+		lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) * 2 + 31) & ~31;
 		lvl->size = lvl->rowstride * ((lvl->height + 1) / 2) * lvl->depth;
 	} else {
 		row_align = rmesa->texture_row_align - 1;
-		lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
+		lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) + row_align) & ~row_align;
 		lvl->size = lvl->rowstride * lvl->height * lvl->depth;
 	}
 	assert(lvl->size > 0);
@@ -138,17 +119,15 @@ static GLuint minify(GLuint size, GLuint levels)
 static void calculate_miptree_layout_r100(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
 {
 	GLuint curOffset;
-	GLuint numLevels;
 	GLuint i;
 	GLuint face;
 
-	numLevels = mt->lastLevel - mt->firstLevel + 1;
-	assert(numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
+	assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
 
 	curOffset = 0;
 	for(face = 0; face < mt->faces; face++) {
 
-		for(i = 0; i < numLevels; i++) {
+		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);
@@ -163,14 +142,12 @@ 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 numLevels;
 	GLuint i;
 
-	numLevels = mt->lastLevel - mt->firstLevel + 1;
-	assert(numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
+	assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
 
 	curOffset = 0;
-	for(i = 0; i < numLevels; i++) {
+	for(i = 0; i < mt->numLevels; i++) {
 		GLuint face;
 
 		mt->levels[i].width = minify(mt->width0, i);
@@ -188,27 +165,22 @@ static void calculate_miptree_layout_r300(radeonContextPtr rmesa, radeon_mipmap_
 /**
  * Create a new mipmap tree, calculate its layout and allocate memory.
  */
-radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
-		GLenum target, GLenum internal_format, GLuint firstLevel, GLuint lastLevel,
-		GLuint width0, GLuint height0, GLuint depth0,
-		GLuint bpp, GLuint tilebits, GLuint compressed)
+static radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
+		GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels,
+		GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
 {
 	radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
 
-	mt->radeon = rmesa;
-	mt->internal_format = internal_format;
+	mt->mesaFormat = mesaFormat;
 	mt->refcount = 1;
-	mt->t = t;
 	mt->target = target;
 	mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
-	mt->firstLevel = firstLevel;
-	mt->lastLevel = lastLevel;
+	mt->baseLevel = baseLevel;
+	mt->numLevels = numLevels;
 	mt->width0 = width0;
 	mt->height0 = height0;
 	mt->depth0 = depth0;
-	mt->bpp = compressed ? radeon_compressed_num_bytes(compressed) : bpp;
 	mt->tilebits = tilebits;
-	mt->compressed = compressed;
 
 	if (rmesa->radeonScreen->chip_family >= CHIP_FAMILY_R300)
 		calculate_miptree_layout_r300(rmesa, mt);
@@ -250,34 +222,16 @@ void radeon_miptree_unreference(radeon_mipmap_tree **ptr)
 	*ptr = 0;
 }
 
-
 /**
- * Calculate first and last mip levels for the given texture object,
- * where the dimensions are taken from the given texture image at
- * the given level.
- *
- * Note: level is the OpenGL level number, which is not necessarily the same
- * as the first level that is actually present.
- *
- * The base level image of the given texture face must be non-null,
- * or this will fail.
+ * Calculate min and max LOD for the given texture object.
+ * @param[in] tObj texture object whose LOD values to calculate
+ * @param[out] pminLod minimal LOD
+ * @param[out] pmaxLod maximal LOD
  */
-static void calculate_first_last_level(struct gl_texture_object *tObj,
-				       GLuint *pfirstLevel, GLuint *plastLevel,
-				       GLuint face, GLuint level)
+static void calculate_min_max_lod(struct gl_texture_object *tObj,
+				       unsigned *pminLod, unsigned *pmaxLod)
 {
-	const struct gl_texture_image * const baseImage =
-		tObj->Image[face][level];
-
-	assert(baseImage);
-	
-	/* These must be signed values.  MinLod and MaxLod can be negative numbers,
-	* and having firstLevel and lastLevel as signed prevents the need for
-	* extra sign checks.
-	*/
-	int   firstLevel;
-	int   lastLevel;
-
+	int minLod, maxLod;
 	/* Yes, this looks overly complicated, but it's all needed.
 	*/
 	switch (tObj->Target) {
@@ -288,55 +242,46 @@ static void calculate_first_last_level(struct gl_texture_object *tObj,
 		if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
 			/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
 			*/
-			firstLevel = lastLevel = tObj->BaseLevel;
+			minLod = maxLod = tObj->BaseLevel;
 		} else {
-			firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
-			firstLevel = MAX2(firstLevel, tObj->BaseLevel);
-			firstLevel = MIN2(firstLevel, level + baseImage->MaxLog2);
-			lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
-			lastLevel = MAX2(lastLevel, tObj->BaseLevel);
-			lastLevel = MIN2(lastLevel, level + baseImage->MaxLog2);
-			lastLevel = MIN2(lastLevel, tObj->MaxLevel);
-			lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+			minLod = tObj->BaseLevel + (GLint)(tObj->MinLod);
+			minLod = MAX2(minLod, tObj->BaseLevel);
+			minLod = MIN2(minLod, tObj->MaxLevel);
+			maxLod = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+			maxLod = MIN2(maxLod, tObj->MaxLevel);
+			maxLod = MIN2(maxLod, tObj->Image[0][minLod]->MaxLog2 + minLod);
+			maxLod = MAX2(maxLod, minLod); /* need at least one level */
 		}
 		break;
 	case GL_TEXTURE_RECTANGLE_NV:
 	case GL_TEXTURE_4D_SGIS:
-		firstLevel = lastLevel = 0;
+		minLod = maxLod = 0;
 		break;
 	default:
 		return;
 	}
 
 	/* save these values */
-	*pfirstLevel = firstLevel;
-	*plastLevel = lastLevel;
+	*pminLod = minLod;
+	*pmaxLod = maxLod;
 }
 
-
 /**
  * Checks whether the given miptree can hold the given texture image at the
  * given face and level.
  */
 GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
-		struct gl_texture_image *texImage, GLuint face, GLuint level)
+		struct gl_texture_image *texImage, GLuint face, GLuint mtLevel)
 {
-	GLboolean isCompressed = _mesa_is_format_compressed(texImage->TexFormat);
 	radeon_mipmap_level *lvl;
 
-	if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel)
-		return GL_FALSE;
-
-	if (texImage->InternalFormat != mt->internal_format ||
-	    isCompressed != mt->compressed)
+	if (face >= mt->faces || mtLevel > mt->numLevels)
 		return GL_FALSE;
 
-	if (!isCompressed &&
-	    !mt->compressed &&
-	    _mesa_get_format_bytes(texImage->TexFormat) != mt->bpp)
+	if (texImage->TexFormat != mt->mesaFormat)
 		return GL_FALSE;
 
-	lvl = &mt->levels[level - mt->firstLevel];
+	lvl = &mt->levels[mtLevel];
 	if (lvl->width != texImage->Width ||
 	    lvl->height != texImage->Height ||
 	    lvl->depth != texImage->Depth)
@@ -345,64 +290,72 @@ GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
 	return GL_TRUE;
 }
 
-
 /**
  * Checks whether the given miptree has the right format to store the given texture object.
  */
-GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj)
+static GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj)
 {
 	struct gl_texture_image *firstImage;
-	GLuint compressed;
-	GLuint numfaces = 1;
-	GLuint firstLevel, lastLevel;
-	GLuint texelBytes;
-
-	calculate_first_last_level(texObj, &firstLevel, &lastLevel, 0, texObj->BaseLevel);
-	if (texObj->Target == GL_TEXTURE_CUBE_MAP)
-		numfaces = 6;
-
-	firstImage = texObj->Image[0][firstLevel];
-	compressed = _mesa_is_format_compressed(firstImage->TexFormat) ? firstImage->TexFormat : 0;
-	texelBytes = _mesa_get_format_bytes(firstImage->TexFormat);
-
-	return (mt->firstLevel == firstLevel &&
-	        mt->lastLevel == lastLevel &&
-	        mt->width0 == firstImage->Width &&
-	        mt->height0 == firstImage->Height &&
-	        mt->depth0 == firstImage->Depth &&
-	        mt->compressed == compressed &&
-	        (!mt->compressed ? (mt->bpp == texelBytes) : 1));
-}
+	unsigned numLevels;
+	radeon_mipmap_level *mtBaseLevel;
 
+	if (texObj->BaseLevel < mt->baseLevel)
+		return GL_FALSE;
+
+	mtBaseLevel = &mt->levels[texObj->BaseLevel - mt->baseLevel];
+	firstImage = texObj->Image[0][texObj->BaseLevel];
+	numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, firstImage->MaxLog2 + 1);
+
+	if (RADEON_DEBUG & RADEON_TEXTURE) {
+		fprintf(stderr, "Checking if miptree %p matches texObj %p\n", mt, texObj);
+		fprintf(stderr, "target %d vs %d\n", mt->target, texObj->Target);
+		fprintf(stderr, "format %d vs %d\n", mt->mesaFormat, firstImage->TexFormat);
+		fprintf(stderr, "numLevels %d vs %d\n", mt->numLevels, numLevels);
+		fprintf(stderr, "width0 %d vs %d\n", mtBaseLevel->width, firstImage->Width);
+		fprintf(stderr, "height0 %d vs %d\n", mtBaseLevel->height, firstImage->Height);
+		fprintf(stderr, "depth0 %d vs %d\n", mtBaseLevel->depth, firstImage->Depth);
+		if (mt->target == texObj->Target &&
+	        mt->mesaFormat == firstImage->TexFormat &&
+	        mt->numLevels >= numLevels &&
+	        mtBaseLevel->width == firstImage->Width &&
+	        mtBaseLevel->height == firstImage->Height &&
+	        mtBaseLevel->depth == firstImage->Depth) {
+			fprintf(stderr, "MATCHED\n");
+		} else {
+			fprintf(stderr, "NOT MATCHED\n");
+		}
+	}
+
+	return (mt->target == texObj->Target &&
+	        mt->mesaFormat == firstImage->TexFormat &&
+	        mt->numLevels >= numLevels &&
+	        mtBaseLevel->width == firstImage->Width &&
+	        mtBaseLevel->height == firstImage->Height &&
+	        mtBaseLevel->depth == firstImage->Depth);
+}
 
 /**
- * Try to allocate a mipmap tree for the given texture that will fit the
- * given image in the given position.
+ * Try to allocate a mipmap tree for the given texture object.
+ * @param[in] rmesa radeon context
+ * @param[in] t radeon texture object
  */
-void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
-		radeon_texture_image *image, GLuint face, GLuint level)
+void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t)
 {
-	GLuint compressed = _mesa_is_format_compressed(image->base.TexFormat) ? image->base.TexFormat : 0;
-	GLuint numfaces = 1;
-	GLuint firstLevel, lastLevel;
-	GLuint texelBytes;
+	struct gl_texture_object *texObj = &t->base;
+	struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
+	GLuint numLevels;
 
 	assert(!t->mt);
 
-	calculate_first_last_level(&t->base, &firstLevel, &lastLevel, face, level);
-	if (t->base.Target == GL_TEXTURE_CUBE_MAP)
-		numfaces = 6;
-
-	if (level != firstLevel || face >= numfaces)
+	if (!texImg)
 		return;
 
-	texelBytes = _mesa_get_format_bytes(image->base.TexFormat);
+	numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, texImg->MaxLog2 + 1);
 
-	t->mt = radeon_miptree_create(rmesa, t, t->base.Target,
-		image->base.InternalFormat,
-		firstLevel, lastLevel,
-		image->base.Width, image->base.Height, image->base.Depth,
-		texelBytes, t->tile_bits, compressed);
+	t->mt = radeon_miptree_create(rmesa, t->base.Target,
+		texImg->TexFormat, texObj->BaseLevel,
+		numLevels, texImg->Width, texImg->Height,
+		texImg->Depth, t->tile_bits);
 }
 
 /* Although we use the image_offset[] array to store relative offsets
@@ -414,21 +367,238 @@ void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
 void
 radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets)
 {
-     if (mt->target != GL_TEXTURE_3D || mt->faces == 1)
-        offsets[0] = 0;
-     else {
-	int i;
-	for (i = 0; i < 6; i++)
-		offsets[i] = mt->levels[level].faces[i].offset;
-     }
+	if (mt->target != GL_TEXTURE_3D || mt->faces == 1) {
+		offsets[0] = 0;
+	} else {
+		int i;
+		for (i = 0; i < 6; i++) {
+			offsets[i] = mt->levels[level].faces[i].offset;
+		}
+	}
 }
 
 GLuint
 radeon_miptree_image_offset(radeon_mipmap_tree *mt,
 			    GLuint face, GLuint level)
 {
-   if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
-      return (mt->levels[level].faces[face].offset);
-   else
-      return mt->levels[level].faces[0].offset;
+	if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
+		return (mt->levels[level].faces[face].offset);
+	else
+		return mt->levels[level].faces[0].offset;
+}
+
+/**
+ * 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)
+{
+	radeon_mipmap_level *dstlvl = &mt->levels[mtLevel];
+	unsigned char *dest;
+
+	assert(image->mt != mt);
+	assert(dstlvl->width == image->base.Width);
+	assert(dstlvl->height == image->base.Height);
+	assert(dstlvl->depth == image->base.Depth);
+
+	radeon_bo_map(mt->bo, GL_TRUE);
+	dest = mt->bo->ptr + dstlvl->faces[face].offset;
+
+	if (image->mt) {
+		/* Format etc. should match, so we really just need a memcpy().
+		 * In fact, that memcpy() could be done by the hardware in many
+		 * cases, provided that we have a proper memory manager.
+		 */
+		assert(mt->mesaFormat == image->base.TexFormat);
+
+		radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel];
+
+		assert(srclvl->size == dstlvl->size);
+		assert(srclvl->rowstride == dstlvl->rowstride);
+
+		radeon_bo_map(image->mt->bo, GL_FALSE);
+
+		memcpy(dest,
+			image->mt->bo->ptr + srclvl->faces[face].offset,
+			dstlvl->size);
+		radeon_bo_unmap(image->mt->bo);
+
+		radeon_miptree_unreference(&image->mt);
+	} else {
+		/* need to confirm this value is correct */
+		if (_mesa_is_format_compressed(image->base.TexFormat)) {
+			unsigned size = _mesa_format_image_size(image->base.TexFormat,
+													image->base.Width,
+													image->base.Height,
+													image->base.Depth);
+			memcpy(dest, image->base.Data, size);
+		} else {
+			uint32_t srcrowstride;
+			uint32_t height;
+
+			height = image->base.Height * image->base.Depth;
+			srcrowstride = image->base.Width * _mesa_get_format_bytes(image->base.TexFormat);
+			copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride,
+					height, srcrowstride);
+		}
+
+		_mesa_free_texmemory(image->base.Data);
+		image->base.Data = 0;
+	}
+
+	radeon_bo_unmap(mt->bo);
+
+	radeon_miptree_reference(mt, &image->mt);
+	image->mtface = face;
+	image->mtlevel = mtLevel;
+}
+
+/**
+ * Filter matching miptrees, and select one with the most of data.
+ * @param[in] texObj radeon texture object
+ * @param[in] firstLevel first texture level to check
+ * @param[in] lastLevel last texture level to check
+ */
+static radeon_mipmap_tree * get_biggest_matching_miptree(radeonTexObj *texObj,
+														 unsigned firstLevel,
+														 unsigned lastLevel)
+{
+	const unsigned numLevels = lastLevel - firstLevel;
+	unsigned *mtSizes = calloc(numLevels, sizeof(unsigned));
+	radeon_mipmap_tree **mts = calloc(numLevels, sizeof(radeon_mipmap_tree *));
+	unsigned mtCount = 0;
+	unsigned maxMtIndex = 0;
+
+	for (unsigned level = firstLevel; level <= lastLevel; ++level) {
+		radeon_texture_image *img = get_radeon_texture_image(texObj->base.Image[0][level]);
+		unsigned found = 0;
+		// TODO: why this hack??
+		if (!img)
+			break;
+
+		if (!img->mt || !radeon_miptree_matches_texture(img->mt, &texObj->base))
+			continue;
+
+		for (int i = 0; i < mtCount; ++i) {
+			if (mts[i] == img->mt) {
+				found = 1;
+				mtSizes[i] += img->mt->levels[img->mtlevel].size;
+				break;
+			}
+		}
+
+		if (!found) {
+			mtSizes[mtCount] += img->mt->levels[img->mtlevel].size;
+			mts[mtCount++] = img->mt;
+			mtCount++;
+		}
+	}
+
+	if (mtCount == 0) {
+		return NULL;
+	}
+
+	for (int i = 1; i < mtCount; ++i) {
+		if (mtSizes[i] > mtSizes[maxMtIndex]) {
+			maxMtIndex = i;
+		}
+	}
+
+	return mts[maxMtIndex];
+}
+
+/**
+ * Validate texture mipmap tree.
+ * If individual images are stored in different mipmap trees
+ * use the mipmap tree that has the most of the correct data.
+ */
+int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *texObj)
+{
+	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+	radeonTexObj *t = radeon_tex_obj(texObj);
+
+	if (t->validated || t->image_override) {
+		return GL_TRUE;
+	}
+
+	if (texObj->Image[0][texObj->BaseLevel]->Border > 0)
+		return GL_FALSE;
+
+	/* TODO: is this really necessary? */
+	_mesa_test_texobj_completeness(rmesa->glCtx, texObj);
+	assert(texObj->_Complete);
+
+	calculate_min_max_lod(&t->base, &t->minLod, &t->maxLod);
+
+	if (RADEON_DEBUG & RADEON_TEXTURE)
+		fprintf(stderr, "%s: Validating texture %p now, minLod = %d, maxLod = %d\n",
+				__FUNCTION__, texObj ,t->minLod, t->maxLod);
+
+	radeon_mipmap_tree *dst_miptree;
+	dst_miptree = get_biggest_matching_miptree(t, t->minLod, t->maxLod);
+
+	if (!dst_miptree) {
+		radeon_miptree_unreference(&t->mt);
+		radeon_try_alloc_miptree(rmesa, t);
+		dst_miptree = t->mt;
+	}
+
+	const unsigned faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
+	unsigned face, level;
+	radeon_texture_image *img;
+	/* Validate only the levels that will actually be used during rendering */
+	for (face = 0; face < faces; ++face) {
+		for (level = t->minLod; level <= t->maxLod; ++level) {
+			img = get_radeon_texture_image(texObj->Image[face][level]);
+
+			if (RADEON_DEBUG & RADEON_TEXTURE) {
+				fprintf(stderr, "Checking image level %d, face %d, mt %p ... ", level, face, img->mt);
+			}
+			
+			if (img->mt != dst_miptree) {
+				if (RADEON_DEBUG & RADEON_TEXTURE) {
+					fprintf(stderr, "MIGRATING\n");
+				}
+				migrate_image_to_miptree(dst_miptree, img, face, radeon_gl_level_to_miptree_level(texObj, level));
+			} else if (RADEON_DEBUG & RADEON_TEXTURE) {
+				fprintf(stderr, "OK\n");
+			}
+		}
+	}
+
+	t->validated = GL_TRUE;
+
+	return GL_TRUE;
+}
+
+uint32_t get_base_teximage_offset(radeonTexObj *texObj)
+{
+	if (!texObj->mt) {
+		return 0;
+	} else {
+		return radeon_miptree_image_offset(texObj->mt, 0, texObj->minLod);
+	}
+}
\ No newline at end of file
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
index 57299ce..28b8485 100644
--- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
@@ -59,44 +59,38 @@ struct _radeon_mipmap_level {
  * changed.
  */
 struct _radeon_mipmap_tree {
-	radeonContextPtr radeon;
-	radeonTexObj *t;
 	struct radeon_bo *bo;
 	GLuint refcount;
 
 	GLuint totalsize; /** total size of the miptree, in bytes */
 
 	GLenum target; /** GL_TEXTURE_xxx */
-	GLenum internal_format;
+	GLenum mesaFormat; /** MESA_FORMAT_xxx */
 	GLuint faces; /** # of faces: 6 for cubemaps, 1 otherwise */
-	GLuint firstLevel; /** First mip level stored in this mipmap tree */
-	GLuint lastLevel; /** Last mip level stored in this 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 bpp; /** Bytes per texel */
 	GLuint tilebits; /** RADEON_TXO_xxx_TILE */
-	GLuint compressed; /** MESA_FORMAT_xxx indicating a compressed format, or 0 if uncompressed */
 
 	radeon_mipmap_level levels[RADEON_MIPTREE_MAX_TEXTURE_LEVELS];
 };
 
-radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
-		GLenum target, GLenum internal_format, GLuint firstLevel, GLuint lastLevel,
-		GLuint width0, GLuint height0, GLuint depth0,
-		GLuint bpp, GLuint tilebits, GLuint compressed);
-
 void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr);
 void radeon_miptree_unreference(radeon_mipmap_tree **ptr);
 
 GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
 		struct gl_texture_image *texImage, GLuint face, GLuint level);
-GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj);
-void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
-			      radeon_texture_image *texImage, GLuint face, GLuint level);
+void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t);
 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 c093d12..6f11f1f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_texture.c
+++ b/src/mesa/drivers/dri/radeon/radeon_texture.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2009 Maciej Cencora.
  * Copyright (C) 2008 Nicolai Haehnle.
  * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
  *
@@ -46,7 +47,7 @@
 #include "radeon_mipmap_tree.h"
 
 
-static void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
+void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
 	GLuint numrows, GLuint rowsize)
 {
 	assert(rowsize <= dststride);
@@ -107,7 +108,7 @@ static void teximage_set_map_data(radeon_texture_image *image)
 	lvl = &image->mt->levels[image->mtlevel];
 
 	image->base.Data = image->mt->bo->ptr + lvl->faces[image->mtface].offset;
-	image->base.RowStride = lvl->rowstride / image->mt->bpp;
+	image->base.RowStride = lvl->rowstride / _mesa_get_format_bytes(image->base.TexFormat);
 }
 
 
@@ -173,7 +174,7 @@ void radeonMapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
 
 	radeon_bo_map(t->mt->bo, GL_FALSE);
 	for(face = 0; face < t->mt->faces; ++face) {
-		for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level)
+		for(level = t->minLod; level <= t->maxLod; ++level)
 			teximage_set_map_data(get_radeon_texture_image(texObj->Image[face][level]));
 	}
 }
@@ -190,7 +191,7 @@ void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
 	  return;
 
 	for(face = 0; face < t->mt->faces; ++face) {
-		for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level)
+		for(level = t->minLod; level <= t->maxLod; ++level)
 			texObj->Image[face][level]->Data = 0;
 	}
 	radeon_bo_unmap(t->mt->bo);
@@ -508,6 +509,31 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
 	return MESA_FORMAT_NONE;		/* never get here */
 }
 
+static void teximage_assign_miptree(radeonContextPtr rmesa,
+	struct gl_texture_object *texObj,
+	struct gl_texture_image *texImage,
+	unsigned face,
+	unsigned level)
+{
+	radeonTexObj *t = radeon_tex_obj(texObj);
+	radeon_texture_image* image = get_radeon_texture_image(texImage);
+
+	/* 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))) {
+		radeon_miptree_unreference(&t->mt);
+		radeon_try_alloc_miptree(rmesa, t);
+	}
+
+	/* Miptree alocation may have failed,
+	 * when there was no image for baselevel specified */
+	if (t->mt) {
+		image->mtface = face;
+		image->mtlevel = radeon_gl_level_to_miptree_level(texObj, level);
+		radeon_miptree_reference(t->mt, &image->mt);
+	}
+}
+
 static GLuint * allocate_image_offsets(GLcontext *ctx,
 	unsigned alignedWidth,
 	unsigned height,
@@ -543,16 +569,20 @@ static void radeon_store_teximage(GLcontext* ctx, int dims,
 		struct gl_texture_image *texImage,
 		int compressed)
 {
+	radeonTexObj *t = radeon_tex_obj(texObj);
 	radeon_texture_image* image = get_radeon_texture_image(texImage);
 
-	GLint dstRowStride;
+	GLuint dstRowStride;
 	GLuint *dstImageOffsets;
 
 	if (image->mt) {
-		radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
-		dstRowStride = lvl->rowstride;
+		dstRowStride = image->mt->levels[image->mtlevel].rowstride;
+	} else if (t->bo) {
+		/* TFP case */
+		/* TODO */
+		assert(0);
 	} else {
-		dstRowStride = texImage->RowStride * _mesa_get_format_bytes(texImage->TexFormat);
+		dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
 	}
 
 	if (dims == 3) {
@@ -577,8 +607,10 @@ static void radeon_store_teximage(GLcontext* ctx, int dims,
 									texImage->Width, texImage->Data);
 		}
 		else {
-			uint32_t blocks_x = dstRowStride / (image->mt->bpp * 4);
-			img_start = texImage->Data + image->mt->bpp * 4 * (blocks_x * (yoffset / 4) + xoffset / 4);
+			uint32_t blocks_x, block_width, block_height;
+			_mesa_get_format_block_size(image->mt->mesaFormat, &block_width, &block_height);
+			blocks_x = dstRowStride / block_width;
+			img_start = texImage->Data + _mesa_get_format_bytes(image->mt->mesaFormat) * 4 * (blocks_x * (yoffset / 4) + xoffset / 4);
 		}
 		srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
 		bytesPerRow = srcRowStride;
@@ -624,10 +656,8 @@ static void radeon_teximage(
 	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
 	radeonTexObj* t = radeon_tex_obj(texObj);
 	radeon_texture_image* image = get_radeon_texture_image(texImage);
-	GLuint dstRowStride;
 	GLint postConvWidth = width;
 	GLint postConvHeight = height;
-	GLuint texelBytes;
 	GLuint face = radeon_face_for_target(target);
 
 	{
@@ -645,51 +675,30 @@ static void radeon_teximage(
 						  &postConvHeight);
 	}
 
-	if (_mesa_is_format_compressed(texImage->TexFormat)) {
-		texelBytes = 0;
-	} else {
-		texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
+	if (!_mesa_is_format_compressed(texImage->TexFormat)) {
+		GLuint texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
 		/* Minimum pitch of 32 bytes */
 		if (postConvWidth * texelBytes < 32) {
-		  postConvWidth = 32 / texelBytes;
-		  texImage->RowStride = postConvWidth;
+			postConvWidth = 32 / texelBytes;
+			texImage->RowStride = postConvWidth;
 		}
-		if (!image->mt) {      
+		if (!image->mt) {
 			assert(texImage->RowStride == postConvWidth);
 		}
 	}
 
-	/* Allocate memory for image */
-	radeonFreeTexImageData(ctx, texImage); /* Mesa core only clears texImage->Data but not image->mt */
+	/* Mesa core only clears texImage->Data but not image->mt */
+	radeonFreeTexImageData(ctx, texImage);
 
-	if (t->mt &&
-	    t->mt->firstLevel == level &&
-	    t->mt->lastLevel == level &&
-	    t->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
-	    !radeon_miptree_matches_image(t->mt, texImage, face, level)) {
-	  radeon_miptree_unreference(&t->mt);
-	}
-
-	if (!t->mt)
-		radeon_try_alloc_miptree(rmesa, t, image, face, level);
-	if (t->mt && radeon_miptree_matches_image(t->mt, texImage, face, level)) {
-		radeon_mipmap_level *lvl;
-		image->mtlevel = level - t->mt->firstLevel;
-		image->mtface = face;
-		radeon_miptree_reference(t->mt, &image->mt);
-		lvl = &image->mt->levels[image->mtlevel];
-		dstRowStride = lvl->rowstride;
-	} else {
-		int size;
-		if (_mesa_is_format_compressed(texImage->TexFormat)) {
-			size = _mesa_format_image_size(texImage->TexFormat,
-						       texImage->Width,
-						       texImage->Height,
-						       texImage->Depth);
-		} else {
-			size = texImage->Width * texImage->Height * texImage->Depth * _mesa_get_format_bytes(texImage->TexFormat);
+	if (!t->bo) {
+		teximage_assign_miptree(rmesa, texObj, texImage, face, level);
+		if (!t->mt) {
+			int size = _mesa_format_image_size(texImage->TexFormat,
+								texImage->Width,
+								texImage->Height,
+								texImage->Depth);
+			texImage->Data = _mesa_alloc_texmemory(size);
 		}
-		texImage->Data = _mesa_alloc_texmemory(size);
 	}
 
 	/* Upload texture image; note that the spec allows pixels to be NULL */
@@ -793,10 +802,10 @@ static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int leve
 	t->validated = GL_FALSE;
 	if (compressed) {
 		pixels = _mesa_validate_pbo_compressed_teximage(
-			ctx, imageSize, pixels, packing, "glCompressedTexImage");
+			ctx, imageSize, pixels, packing, "glCompressedTexSubImage");
 	} else {
 		pixels = _mesa_validate_pbo_teximage(ctx, dims,
-			width, height, depth, format, type, pixels, packing, "glTexSubImage1D");
+			width, height, depth, format, type, pixels, packing, "glTexSubImage");
 	}
 
 	if (pixels) {
@@ -865,140 +874,6 @@ void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
 		format, type, pixels, packing, texObj, texImage, 0);
 }
 
-
-
-/**
- * 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 level)
-{
-	radeon_mipmap_level *dstlvl = &mt->levels[level - mt->firstLevel];
-	unsigned char *dest;
-
-	assert(image->mt != mt);
-	assert(dstlvl->width == image->base.Width);
-	assert(dstlvl->height == image->base.Height);
-	assert(dstlvl->depth == image->base.Depth);
-
-
-	radeon_bo_map(mt->bo, GL_TRUE);
-	dest = mt->bo->ptr + dstlvl->faces[face].offset;
-
-	if (image->mt) {
-		/* Format etc. should match, so we really just need a memcpy().
-		 * In fact, that memcpy() could be done by the hardware in many
-		 * cases, provided that we have a proper memory manager.
-		 */
-		radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel-image->mt->firstLevel];
-
-		assert(srclvl->size == dstlvl->size);
-		assert(srclvl->rowstride == dstlvl->rowstride);
-
-		radeon_bo_map(image->mt->bo, GL_FALSE);
-
-		memcpy(dest,
-			image->mt->bo->ptr + srclvl->faces[face].offset,
-			dstlvl->size);
-		radeon_bo_unmap(image->mt->bo);
-
-		radeon_miptree_unreference(&image->mt);
-	} else {
-		uint32_t srcrowstride;
-		uint32_t height;
-		/* need to confirm this value is correct */
-		if (mt->compressed) {
-			height = (image->base.Height + 3) / 4;
-			srcrowstride = _mesa_format_row_stride(image->base.TexFormat, image->base.Width);
-		} else {
-			height = image->base.Height * image->base.Depth;
-			srcrowstride = image->base.Width * _mesa_get_format_bytes(image->base.TexFormat);
-		}
-
-//		if (mt->tilebits)
-//			WARN_ONCE("%s: tiling not supported yet", __FUNCTION__);
-
-		copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride,
-			  height, srcrowstride);
-
-		_mesa_free_texmemory(image->base.Data);
-		image->base.Data = 0;
-	}
-
-	radeon_bo_unmap(mt->bo);
-
-	image->mtface = face;
-	image->mtlevel = level;
-	radeon_miptree_reference(mt, &image->mt);
-}
-
-int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *texObj)
-{
-	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-	radeonTexObj *t = radeon_tex_obj(texObj);
-	radeon_texture_image *baseimage = get_radeon_texture_image(texObj->Image[0][texObj->BaseLevel]);
-	int face, level;
-
-	if (t->validated || t->image_override)
-		return GL_TRUE;
-
-	if (RADEON_DEBUG & RADEON_TEXTURE)
-		fprintf(stderr, "%s: Validating texture %p now\n", __FUNCTION__, texObj);
-
-	if (baseimage->base.Border > 0)
-		return GL_FALSE;
-
-	/* Ensure a matching miptree exists.
-	 *
-	 * Differing mipmap trees can result when the app uses TexImage to
-	 * change texture dimensions.
-	 *
-	 * Prefer to use base image's miptree if it
-	 * exists, since that most likely contains more valid data (remember
-	 * that the base level is usually significantly larger than the rest
-	 * of the miptree, so cubemaps are the only possible exception).
-	 */
-	if (baseimage->mt &&
-	    baseimage->mt != t->mt &&
-	    radeon_miptree_matches_texture(baseimage->mt, &t->base)) {
-		radeon_miptree_unreference(&t->mt);
-		radeon_miptree_reference(baseimage->mt, &t->mt);
-	} else if (t->mt && !radeon_miptree_matches_texture(t->mt, &t->base)) {
-		radeon_miptree_unreference(&t->mt);
-	}
-
-	if (!t->mt) {
-		if (RADEON_DEBUG & RADEON_TEXTURE)
-			fprintf(stderr, " Allocate new miptree\n");
-		radeon_try_alloc_miptree(rmesa, t, baseimage, 0, texObj->BaseLevel);
-		if (!t->mt) {
-			_mesa_problem(ctx, "radeon_validate_texture failed to alloc miptree");
-			return GL_FALSE;
-		}
-	}
-
-	/* Ensure all images are stored in the single main miptree */
-	for(face = 0; face < t->mt->faces; ++face) {
-		for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level) {
-			radeon_texture_image *image = get_radeon_texture_image(texObj->Image[face][level]);
-			if (RADEON_DEBUG & RADEON_TEXTURE)
-				fprintf(stderr, " face %i, level %i... %p vs %p ", face, level, t->mt, image->mt);
-			if (t->mt == image->mt || (!image->mt && !image->base.Data)) {
-				if (RADEON_DEBUG & RADEON_TEXTURE)
-					fprintf(stderr, "OK\n");
-
-				continue;
-			}
-
-			if (RADEON_DEBUG & RADEON_TEXTURE)
-				fprintf(stderr, "migrating\n");
-			migrate_image_to_miptree(t->mt, image, face, level);
-		}
-	}
-
-	return GL_TRUE;
-}
-
-
 /**
  * Need to map texture image into memory before copying image data,
  * then unmap it.
diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.h b/src/mesa/drivers/dri/radeon/radeon_texture.h
index 8995546..906daf1 100644
--- a/src/mesa/drivers/dri/radeon/radeon_texture.h
+++ b/src/mesa/drivers/dri/radeon/radeon_texture.h
@@ -33,7 +33,8 @@
 
 #include "main/formats.h"
 
-
+void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
+	GLuint numrows, GLuint rowsize);
 struct gl_texture_image *radeonNewTextureImage(GLcontext *ctx);
 void radeonFreeTexImageData(GLcontext *ctx, struct gl_texture_image *timage);
 




More information about the mesa-commit mailing list