Merge branch '7.8' into master
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_texture.c
index 607ce7864e8ec9d9e294a6d2099e6c050b69d3f6..2b655fbd953f8ebcc73c57d0fe18b7845f48fa36 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.
  *
 #include "main/imports.h"
 #include "main/context.h"
 #include "main/convolve.h"
+#include "main/enums.h"
 #include "main/mipmap.h"
 #include "main/texcompress.h"
 #include "main/texstore.h"
 #include "main/teximage.h"
 #include "main/texobj.h"
-#include "main/texgetimage.h"
 
 #include "xmlpool.h"           /* for symbolic values of enum-type options */
 
 #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);
        assert(rowsize <= srcstride);
 
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+               "%s dst %p, stride %u, src %p, stride %u, "
+               "numrows %u, rowsize %u.\n",
+               __func__, dst, dststride,
+               src, srcstride,
+               numrows, rowsize);
+
        if (rowsize == srcstride && rowsize == dststride) {
                memcpy(dst, src, numrows*rowsize);
        } else {
@@ -101,13 +109,17 @@ static void teximage_set_map_data(radeon_texture_image *image)
 {
        radeon_mipmap_level *lvl;
 
-       if (!image->mt)
+       if (!image->mt) {
+               radeon_warning("%s(%p) Trying to set map data without miptree.\n",
+                               __func__, image);
+
                return;
+       }
 
        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);
 }
 
 
@@ -116,6 +128,10 @@ static void teximage_set_map_data(radeon_texture_image *image)
  */
 void radeon_teximage_map(radeon_texture_image *image, GLboolean write_enable)
 {
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(img %p), write_enable %s.\n",
+                       __func__, image,
+                       write_enable ? "true": "false");
        if (image->mt) {
                assert(!image->base.Data);
 
@@ -127,6 +143,9 @@ void radeon_teximage_map(radeon_texture_image *image, GLboolean write_enable)
 
 void radeon_teximage_unmap(radeon_texture_image *image)
 {
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(img %p)\n",
+                       __func__, image);
        if (image->mt) {
                assert(image->base.Data);
 
@@ -161,19 +180,35 @@ void radeonMapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
        radeonTexObj* t = radeon_tex_obj(texObj);
        int face, level;
 
-       if (!radeon_validate_texture_miptree(ctx, texObj))
-         return;
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(%p, tex %p)\n",
+                       __func__, ctx, texObj);
+
+       if (!radeon_validate_texture_miptree(ctx, texObj)) {
+               radeon_error("%s(%p, tex %p) Failed to validate miptree for "
+                       "sw fallback.\n",
+                       __func__, ctx, texObj);
+               return;
+       }
+
+       if (t->image_override && t->bo) {
+               radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(%p, tex %p) Work around for missing miptree in r100.\n",
+                       __func__, ctx, texObj);
 
-       /* for r100 3D sw fallbacks don't have mt */
-       if (t->image_override && t->bo)
                map_override(ctx, t);
+       }
 
-       if (!t->mt)
+       /* for r100 3D sw fallbacks don't have mt */
+       if (!t->mt) {
+               radeon_warning("%s(%p, tex %p) No miptree in texture.\n",
+                       __func__, ctx, texObj);
                return;
+       }
 
        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]));
        }
 }
@@ -183,6 +218,10 @@ void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
        radeonTexObj* t = radeon_tex_obj(texObj);
        int face, level;
 
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(%p, tex %p)\n",
+                       __func__, ctx, texObj);
+
        if (t->image_override && t->bo)
                unmap_override(ctx, t);
        /* for r100 3D sw fallbacks don't have mt */
@@ -190,27 +229,12 @@ 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);
 }
 
-GLuint radeon_face_for_target(GLenum target)
-{
-       switch (target) {
-       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-               return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
-       default:
-               return 0;
-       }
-}
-
 /**
  * Wraps Mesa's implementation to ensure that the base level image is mapped.
  *
@@ -224,6 +248,10 @@ static void radeon_generate_mipmap(GLcontext *ctx, GLenum target,
        GLuint nr_faces = (t->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
        int i, face;
 
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(%p, tex %p) Target type %s.\n",
+                       __func__, ctx, texObj,
+                       _mesa_lookup_enum_by_nr(target));
 
        _mesa_generate_mipmap(ctx, target, texObj);
 
@@ -247,8 +275,24 @@ static void radeon_generate_mipmap(GLcontext *ctx, GLenum target,
 
 void radeonGenerateMipmap(GLcontext* ctx, GLenum target, struct gl_texture_object *texObj)
 {
-       GLuint face = radeon_face_for_target(target);
+       radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+       struct radeon_bo *bo;
+       GLuint face = _mesa_tex_target_to_face(target);
        radeon_texture_image *baseimage = get_radeon_texture_image(texObj->Image[face][texObj->BaseLevel]);
+       bo = !baseimage->mt ? baseimage->bo : baseimage->mt->bo;
+
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+               "%s(%p, target %s, tex %p)\n",
+               __func__, ctx, _mesa_lookup_enum_by_nr(target),
+               texObj);
+
+       if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
+               radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+                       "%s(%p, tex %p) Trying to generate mipmap for texture "
+                       "in processing by GPU.\n",
+                       __func__, ctx, texObj);
+               radeon_firevertices(rmesa);
+       }
 
        radeon_teximage_map(baseimage, GL_FALSE);
        radeon_generate_mipmap(ctx, target, texObj);
@@ -311,12 +355,14 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
            (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
        (void)format;
 
-#if 0
-       fprintf(stderr, "InternalFormat=%s(%d) type=%s format=%s\n",
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+               "%s InternalFormat=%s(%d) type=%s format=%s\n",
+               __func__,
                _mesa_lookup_enum_by_nr(internalFormat), internalFormat,
                _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
-       fprintf(stderr, "do32bpt=%d force16bpt=%d\n", do32bpt, force16bpt);
-#endif
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+                       "%s do32bpt=%d force16bpt=%d\n",
+                       __func__, do32bpt, force16bpt);
 
        switch (internalFormat) {
        case 4:
@@ -471,6 +517,19 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
        case GL_RGBA32F_ARB:
                return MESA_FORMAT_RGBA_FLOAT32;
 
+#ifdef RADEON_R300
+       case GL_DEPTH_COMPONENT:
+       case GL_DEPTH_COMPONENT16:
+               return MESA_FORMAT_Z16;
+       case GL_DEPTH_COMPONENT24:
+       case GL_DEPTH_COMPONENT32:
+       case GL_DEPTH_STENCIL_EXT:
+       case GL_DEPTH24_STENCIL8_EXT:
+               if (rmesa->radeonScreen->chip_family >= CHIP_FAMILY_RV515)
+                       return MESA_FORMAT_S8_Z24;
+               else
+                       return MESA_FORMAT_Z16;
+#else
        case GL_DEPTH_COMPONENT:
        case GL_DEPTH_COMPONENT16:
        case GL_DEPTH_COMPONENT24:
@@ -478,6 +537,7 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
        case GL_DEPTH_STENCIL_EXT:
        case GL_DEPTH24_STENCIL8_EXT:
                return MESA_FORMAT_S8_Z24;
+#endif
 
        /* EXT_texture_sRGB */
        case GL_SRGB:
@@ -498,6 +558,15 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
        case GL_COMPRESSED_SLUMINANCE_ALPHA:
                return MESA_FORMAT_SLA8;
 
+       case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+               return MESA_FORMAT_SRGB_DXT1;
+       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+               return MESA_FORMAT_SRGBA_DXT1;
+       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+               return MESA_FORMAT_SRGBA_DXT3;
+       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+               return MESA_FORMAT_SRGBA_DXT5;
+
        default:
                _mesa_problem(ctx,
                              "unexpected internalFormat 0x%x in %s",
@@ -508,6 +577,179 @@ 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][texObj->BaseLevel];
+
+       if (!baseImage)
+               return 0;
+
+       if (level < texObj->BaseLevel || level > texObj->MaxLevel)
+               return 0;
+
+       const unsigned levelDiff = level - texObj->BaseLevel;
+       const unsigned refWidth = MAX2(baseImage->Width >> levelDiff, 1);
+       const unsigned refHeight = MAX2(baseImage->Height >> levelDiff, 1);
+       const unsigned refDepth = MAX2(baseImage->Depth >> levelDiff, 1);
+
+       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,
+       unsigned face,
+       unsigned level)
+{
+       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, level)) {
+               radeon_miptree_unreference(&t->mt);
+               radeon_try_alloc_miptree(rmesa, t);
+               radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+                               "%s: texObj %p, texImage %p, face %d, level %d, "
+                               "texObj miptree doesn't match, allocated new miptree %p\n",
+                               __FUNCTION__, texObj, texImage, face, level, t->mt);
+       }
+
+       /* Miptree alocation may have failed,
+        * when there was no image for baselevel specified */
+       if (t->mt) {
+               image->mtface = face;
+               image->mtlevel = level;
+               radeon_miptree_reference(t->mt, &image->mt);
+       } else
+               radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                               "%s Failed to allocate miptree.\n", __func__);
+}
+
+static GLuint * allocate_image_offsets(GLcontext *ctx,
+       unsigned alignedWidth,
+       unsigned height,
+       unsigned depth)
+{
+       int i;
+       GLuint *offsets;
+
+       offsets = malloc(depth * sizeof(GLuint)) ;
+       if (!offsets) {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex[Sub]Image");
+               return NULL;
+       }
+
+       for (i = 0; i < depth; ++i) {
+               offsets[i] = alignedWidth * height * i;
+       }
+
+       return offsets;
+}
+
+/**
+ * Update a subregion of the given texture image.
+ */
+static void radeon_store_teximage(GLcontext* ctx, int dims,
+               GLint xoffset, GLint yoffset, GLint zoffset,
+               GLsizei width, GLsizei height, GLsizei depth,
+               GLsizei imageSize,
+               GLenum format, GLenum type,
+               const GLvoid * pixels,
+               const struct gl_pixelstore_attrib *packing,
+               struct gl_texture_object *texObj,
+               struct gl_texture_image *texImage,
+               int compressed)
+{
+       radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+       radeonTexObj *t = radeon_tex_obj(texObj);
+       radeon_texture_image* image = get_radeon_texture_image(texImage);
+
+       GLuint dstRowStride;
+       GLuint *dstImageOffsets;
+
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+                       "%s(%p, tex %p, image %p) compressed %d\n",
+                       __func__, ctx, texObj, texImage, compressed);
+
+       if (image->mt) {
+               dstRowStride = image->mt->levels[image->mtlevel].rowstride;
+       } else if (t->bo) {
+               /* TFP case */
+               dstRowStride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0);
+       } else {
+               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);
+               if (!dstImageOffsets) {
+                       radeon_warning("%s Failed to allocate dstImaeOffset.\n", __func__);
+                       return;
+               }
+       } else {
+               dstImageOffsets = texImage->ImageOffsets;
+       }
+
+       radeon_teximage_map(image, GL_TRUE);
+
+       if (compressed) {
+               uint32_t srcRowStride, bytesPerRow, rows, block_width, block_height;
+               GLubyte *img_start;
+
+               _mesa_get_format_block_size(texImage->TexFormat, &block_width, &block_height);
+
+               if (!image->mt) {
+                       dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
+                       img_start = _mesa_compressed_image_address(xoffset, yoffset, 0,
+                                                                       texImage->TexFormat,
+                                                                       texImage->Width, texImage->Data);
+               }
+               else {
+                       uint32_t offset;
+                       offset = dstRowStride / _mesa_get_format_bytes(texImage->TexFormat) * yoffset / block_height + xoffset / block_width;
+                       offset *= _mesa_get_format_bytes(texImage->TexFormat);
+                       img_start = texImage->Data + offset;
+               }
+               srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
+               bytesPerRow = srcRowStride;
+               rows = (height + block_height - 1) / block_height;
+
+               copy_rows(img_start, dstRowStride, pixels, srcRowStride, rows, bytesPerRow);
+       }
+       else {
+               if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
+                                       texImage->TexFormat, texImage->Data,
+                                       xoffset, yoffset, zoffset,
+                                       dstRowStride,
+                                       dstImageOffsets,
+                                       width, height, depth,
+                                       format, type, pixels, packing)) {
+                       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+               }
+       }
+
+       if (dims == 3) {
+               free(dstImageOffsets);
+       }
+
+       radeon_teximage_unmap(image);
+}
+
 /**
  * All glTexImage calls go through this function.
  */
@@ -526,20 +768,26 @@ 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);
+       GLuint face = _mesa_tex_target_to_face(target);
 
+       radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+                       "%s %dd: texObj %p, texImage %p, face %d, level %d\n",
+                       __func__, dims, texObj, texImage, face, level);
        {
                struct radeon_bo *bo;
                bo = !image->mt ? image->bo : image->mt->bo;
                if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
+                       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                               "%s Calling teximage for texture that is "
+                               "queued for GPU processing.\n",
+                               __func__);
                        radeon_firevertices(rmesa);
                }
        }
 
+
        t->validated = GL_FALSE;
 
        if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
@@ -547,51 +795,34 @@ 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 */
-
-       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);
+       /* Mesa core only clears texImage->Data but not image->mt */
+       radeonFreeTexImageData(ctx, texImage);
+
+       if (!t->bo) {
+               teximage_assign_miptree(rmesa, texObj, texImage, face, level);
+               if (!image->mt) {
+                       int size = _mesa_format_image_size(texImage->TexFormat,
+                                                               texImage->Width,
+                                                               texImage->Height,
+                                                               texImage->Depth);
+                       texImage->Data = _mesa_alloc_texmemory(size);
+                       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                                       "%s %dd: texObj %p, texImage %p, "
+                                       " no miptree assigned, using local memory %p\n",
+                                       __func__, dims, texObj, texImage, texImage->Data);
                }
-               texImage->Data = _mesa_alloc_texmemory(size);
        }
 
        /* Upload texture image; note that the spec allows pixels to be NULL */
@@ -605,65 +836,16 @@ static void radeon_teximage(
        }
 
        if (pixels) {
-               radeon_teximage_map(image, GL_TRUE);
-               if (compressed) {
-                       if (image->mt) {
-                               uint32_t srcRowStride, bytesPerRow, rows;
-                               srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
-                               bytesPerRow = srcRowStride;
-                               rows = (height + 3) / 4;
-                               copy_rows(texImage->Data, image->mt->levels[level].rowstride,
-                                         pixels, srcRowStride, rows, bytesPerRow);
-                       } else {
-                               memcpy(texImage->Data, pixels, imageSize);
-                       }
-               } else {
-                       GLuint dstRowStride;
-                       GLuint *dstImageOffsets;
-
-                       if (image->mt) {
-                               radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
-                               dstRowStride = lvl->rowstride;
-                       } else {
-                               dstRowStride = texImage->Width * _mesa_get_format_bytes(texImage->TexFormat);
-                       }
-
-                       if (dims == 3) {
-                               int i;
-
-                               dstImageOffsets = _mesa_malloc(depth * sizeof(GLuint)) ;
-                               if (!dstImageOffsets)
-                                       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
-
-                               for (i = 0; i < depth; ++i) {
-                                       dstImageOffsets[i] = dstRowStride/_mesa_get_format_bytes(texImage->TexFormat) * height * i;
-                               }
-                       } else {
-                               dstImageOffsets = texImage->ImageOffsets;
-                       }
-
-                       if (!_mesa_texstore(ctx, dims,
-                                           texImage->_BaseFormat,
-                                           texImage->TexFormat,
-                                           texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */
-                                           dstRowStride,
-                                           dstImageOffsets,
-                                           width, height, depth,
-                                           format, type, pixels, packing)) {
-                               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
-                       }
-
-                       if (dims == 3)
-                               _mesa_free(dstImageOffsets);
-               }
+               radeon_store_teximage(ctx, dims,
+                       0, 0, 0,
+                       width, height, depth,
+                       imageSize, format, type,
+                       pixels, packing,
+                       texObj, texImage,
+                       compressed);
        }
 
        _mesa_unmap_teximage_pbo(ctx, packing);
-
-       if (pixels)
-         radeon_teximage_unmap(image);
-
-
 }
 
 void radeonTexImage1D(GLcontext * ctx, GLenum target, GLint level,
@@ -716,7 +898,7 @@ void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level,
 }
 
 /**
- * Update a subregion of the given texture image.
+ * All glTexSubImage calls go through this function.
  */
 static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int level,
                GLint xoffset, GLint yoffset, GLint zoffset,
@@ -733,72 +915,43 @@ static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int leve
        radeonTexObj* t = radeon_tex_obj(texObj);
        radeon_texture_image* image = get_radeon_texture_image(texImage);
 
+       radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+                       "%s %dd: texObj %p, texImage %p, face %d, level %d\n",
+                       __func__, dims, texObj, texImage,
+                       _mesa_tex_target_to_face(target), level);
        {
                struct radeon_bo *bo;
                bo = !image->mt ? image->bo : image->mt->bo;
                if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
+                       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                               "%s Calling texsubimage for texture that is "
+                               "queued for GPU processing.\n",
+                               __func__);
                        radeon_firevertices(rmesa);
                }
        }
 
+
        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) {
-               GLint dstRowStride;
-               radeon_teximage_map(image, GL_TRUE);
-
-               if (image->mt) {
-                       radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
-                       dstRowStride = lvl->rowstride;
-               } else {
-                       dstRowStride = texImage->RowStride * _mesa_get_format_bytes(texImage->TexFormat);
-               }
-
-               if (compressed) {
-                       uint32_t srcRowStride, bytesPerRow, rows;
-                       GLubyte *img_start;
-                       if (!image->mt) {
-                               dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
-                               img_start = _mesa_compressed_image_address(xoffset, yoffset, 0,
-                                                                          texImage->TexFormat,
-                                                                          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);
-                       }
-                       srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
-                       bytesPerRow = srcRowStride;
-                       rows = (height + 3) / 4;
-
-                       copy_rows(img_start, dstRowStride,  pixels, srcRowStride, rows,  bytesPerRow);
-                       
-               }
-               else {
-                       if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
-                                           texImage->TexFormat, texImage->Data,
-                                           xoffset, yoffset, zoffset,
-                                           dstRowStride,
-                                           texImage->ImageOffsets,
-                                           width, height, depth,
-                                           format, type, pixels, packing)) {
-                               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
-                       }
-               }
+               radeon_store_teximage(ctx, dims,
+                       xoffset, yoffset, zoffset,
+                       width, height, depth,
+                       imageSize, format, type,
+                       pixels, packing,
+                       texObj, texImage,
+                       compressed);
        }
 
-       radeon_teximage_unmap(image);
-
        _mesa_unmap_teximage_pbo(ctx, packing);
-
-
 }
 
 void radeonTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
@@ -854,191 +1007,18 @@ 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)
+unsigned radeonIsFormatRenderable(gl_format mesa_format)
 {
-       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 (mesa_format == _dri_texformat_argb8888 || mesa_format == _dri_texformat_rgb565 ||
+               mesa_format == _dri_texformat_argb1555 || mesa_format == _dri_texformat_argb4444)
+               return 1;
 
-       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.
- */
-static void
-radeon_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
-                    GLenum format, GLenum type, GLvoid * pixels,
-                    struct gl_texture_object *texObj,
-                    struct gl_texture_image *texImage, int compressed)
-{
-       radeon_texture_image *image = get_radeon_texture_image(texImage);
-
-       if (image->mt) {
-               /* Map the texture image read-only */
-               radeon_teximage_map(image, GL_FALSE);
-       } else {
-               /* Image hasn't been uploaded to a miptree yet */
-               assert(image->base.Data);
-       }
-
-       if (compressed) {
-               /* FIXME: this can't work for small textures (mips) which
-                        use different hw stride */
-               _mesa_get_compressed_teximage(ctx, target, level, pixels,
-                                             texObj, texImage);
-       } else {
-               _mesa_get_teximage(ctx, target, level, format, type, pixels,
-                                  texObj, texImage);
-       }
-     
-       if (image->mt) {
-               radeon_teximage_unmap(image);
+       switch (mesa_format)
+       {
+               case MESA_FORMAT_Z16:
+               case MESA_FORMAT_S8_Z24:
+                       return 1;
+               default:
+                       return 0;
        }
 }
-
-void
-radeonGetTexImage(GLcontext * ctx, GLenum target, GLint level,
-                 GLenum format, GLenum type, GLvoid * pixels,
-                 struct gl_texture_object *texObj,
-                 struct gl_texture_image *texImage)
-{
-       radeon_get_tex_image(ctx, target, level, format, type, pixels,
-                            texObj, texImage, 0);
-}
-
-void
-radeonGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
-                           GLvoid *pixels,
-                           struct gl_texture_object *texObj,
-                           struct gl_texture_image *texImage)
-{
-       radeon_get_tex_image(ctx, target, level, 0, 0, pixels,
-                            texObj, texImage, 1);
-}