radeon: rework mipmap tree
authorMaciej Cencora <m.cencora@gmail.com>
Sat, 14 Nov 2009 15:55:39 +0000 (16:55 +0100)
committerMaciej Cencora <m.cencora@gmail.com>
Sat, 14 Nov 2009 15:55:39 +0000 (16:55 +0100)
src/mesa/drivers/dri/r300/r300_cmdbuf.c
src/mesa/drivers/dri/r300/r300_tex.c
src/mesa/drivers/dri/r300/r300_texstate.c
src/mesa/drivers/dri/radeon/radeon_common_context.h
src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
src/mesa/drivers/dri/radeon/radeon_texture.c
src/mesa/drivers/dri/radeon/radeon_texture.h

index 8a56b9e63cb6fbc980b9f8417819a79df395202d..4b5ed2d41022c2c0c8c5585491bba798334f0853 100644 (file)
@@ -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) {
index 7e94e93df2e657dc6df6aaa8758972956af5cec9..726b3ff98e176cc217c68d9b91dd640740a4b357 100644 (file)
@@ -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;
 
index 7b1adcf31dcfc4a2bc5d094d863b51a1c272606a..e6f2c0c1a7b874cf6cb936b0cac7bb1e0af0e150 100644 (file)
@@ -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;
index 5a0678b9d6c099cb43b9a71cb468802750162dee..ded81fff29f6294e84fc97e811a176d948b8c306 100644 (file)
@@ -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 */
index f635f58d6ae8fd4a521d8827199b270196485364..f01136b9d4189110262e77dd585dde5b667dfae7 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2009 Maciej Cencora.
  * Copyright (C) 2008 Nicolai Haehnle.
  *
  * All Rights Reserved.
 
 #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
index 57299ceafac8069bca806568445423204a91d9e5..28b848509547107d8f0975554f142da5ebe731c0 100644 (file)
@@ -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_ */
index c093d1283d1ecbd4ad7cb45ca21b22720e9f3a6f..6f11f1fa4ab070a657787ccdeca8fefb945b4003 100644 (file)
@@ -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.
index 8995546d7710556eae49a6dea4ecb6935dc3b54a..906daf12d0a62de963464d9307bf2dff15f9a9b1 100644 (file)
@@ -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);