r300: Make sure to drop current hardware state reference to texture objects.
[mesa.git] / src / mesa / drivers / dri / r300 / r300_texstate.c
index 4bc0ea14f811ea97ce701dd0a57faf4b5d3766b4..f6ae4b675b860f3fc474a30b63f10d7d07dbfb3e 100644 (file)
@@ -27,17 +27,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
 
-/*
- * Authors:
- *   Keith Whitwell <keith@tungstengraphics.com>
+/**
+ * \file
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * \todo Enable R300 texture tiling code?
  */
 
-#include "glheader.h"
-#include "imports.h"
-#include "context.h"
-#include "macros.h"
-#include "texformat.h"
-#include "enums.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "main/teximage.h"
+#include "main/texobj.h"
+#include "main/enums.h"
 
 #include "r300_context.h"
 #include "r300_state.h"
@@ -46,108 +51,249 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_tex.h"
 #include "r300_reg.h"
 
-
 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5                        \
                           || ((f) >= MESA_FORMAT_RGBA_FLOAT32 &&       \
                               (f) <= MESA_FORMAT_INTENSITY_FLOAT16))   \
-                         && tx_table_le[f].flag )
+                         && tx_table[f].flag )
 
 #define _ASSIGN(entry, format)                         \
        [ MESA_FORMAT_ ## entry ] = { format, 0, 1}
 
-static const struct {
-       GLuint format, filter, flag;
-} tx_table_be[] = {
-       /*
-        * Note that the _REV formats are the same as the non-REV formats.
-        * This is because the REV and non-REV formats are identical as a
-        * byte string, but differ when accessed as 16-bit or 32-bit words
-        * depending on the endianness of the host.  Since the textures are
-        * transferred to the R300 as a byte string (i.e. without any
-        * byte-swapping), the R300 sees the REV and non-REV formats
-        * identically.  -- paulus
-        */
-           _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)),
-           _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)),
-           _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
-           _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
-           _ASSIGN(RGB888, 0xffffffff),
-           _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
-           _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
-           _ASSIGN(ARGB4444, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
-           _ASSIGN(ARGB4444_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
-           _ASSIGN(ARGB1555, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
-           _ASSIGN(ARGB1555_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
-           _ASSIGN(AL88, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
-           _ASSIGN(AL88_REV, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
-           _ASSIGN(RGB332, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z3Y3X2)),
-           _ASSIGN(A8, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8)),
-           _ASSIGN(L8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8)),
-           _ASSIGN(I8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
-           _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
-           _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE ),
-           _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE),
-           _ASSIGN(RGB_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1)),
-           _ASSIGN(RGBA_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1)),
-           _ASSIGN(RGBA_DXT3, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3)),
-           _ASSIGN(RGBA_DXT5, R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5)),
-           _ASSIGN(RGBA_FLOAT32, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R32G32B32A32)),
-           _ASSIGN(RGBA_FLOAT16, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R16G16B16A16)),
-           _ASSIGN(RGB_FLOAT32, 0xffffffff),
-           _ASSIGN(RGB_FLOAT16, 0xffffffff),
-           _ASSIGN(ALPHA_FLOAT32, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I32)),
-           _ASSIGN(ALPHA_FLOAT16, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I16)),
-           _ASSIGN(LUMINANCE_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I32)),
-           _ASSIGN(LUMINANCE_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I16)),
-           _ASSIGN(LUMINANCE_ALPHA_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I32A32)),
-           _ASSIGN(LUMINANCE_ALPHA_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I16A16)),
-           _ASSIGN(INTENSITY_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, X, FL_I32)),
-           _ASSIGN(INTENSITY_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, X, FL_I16)),
-           };
-
-static const struct {
+/*
+ * Note that the _REV formats are the same as the non-REV formats.  This is
+ * because the REV and non-REV formats are identical as a byte string, but
+ * differ when accessed as 16-bit or 32-bit words depending on the endianness of
+ * the host.  Since the textures are transferred to the R300 as a byte string
+ * (i.e. without any byte-swapping), the R300 sees the REV and non-REV formats
+ * identically.  -- paulus
+ */
+
+static const struct tx_table {
        GLuint format, filter, flag;
-} tx_table_le[] = {
-           _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)),
-           _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)),
-           _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
-           _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
-           _ASSIGN(RGB888, 0xffffffff),
-           _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
-           _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
-           _ASSIGN(ARGB4444, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
-           _ASSIGN(ARGB4444_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
-           _ASSIGN(ARGB1555, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
-           _ASSIGN(ARGB1555_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
-           _ASSIGN(AL88, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
-           _ASSIGN(AL88_REV, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
-           _ASSIGN(RGB332, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z3Y3X2)),
-           _ASSIGN(A8, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8)),
-           _ASSIGN(L8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8)),
-           _ASSIGN(I8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
-           _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
-           _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE ),
-           _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE),
-           _ASSIGN(RGB_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1)),
-           _ASSIGN(RGBA_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1)),
-           _ASSIGN(RGBA_DXT3, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3)),
-           _ASSIGN(RGBA_DXT5, R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5)),
-           _ASSIGN(RGBA_FLOAT32, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R32G32B32A32)),
-           _ASSIGN(RGBA_FLOAT16, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R16G16B16A16)),
-           _ASSIGN(RGB_FLOAT32, 0xffffffff),
-           _ASSIGN(RGB_FLOAT16, 0xffffffff),
-           _ASSIGN(ALPHA_FLOAT32, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I32)),
-           _ASSIGN(ALPHA_FLOAT16, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I16)),
-           _ASSIGN(LUMINANCE_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I32)),
-           _ASSIGN(LUMINANCE_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I16)),
-           _ASSIGN(LUMINANCE_ALPHA_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I32A32)),
-           _ASSIGN(LUMINANCE_ALPHA_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I16A16)),
-           _ASSIGN(INTENSITY_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, X, FL_I32)),
-           _ASSIGN(INTENSITY_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, X, FL_I16)),
-           };
+} tx_table[] = {
+       /* *INDENT-OFF* */
+#ifdef MESA_LITTLE_ENDIAN
+       _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)),
+       _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)),
+       _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
+       _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
+#else
+       _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)),
+       _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)),
+       _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
+       _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
+#endif
+       _ASSIGN(RGB888, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)),
+       _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
+       _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
+       _ASSIGN(ARGB4444, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
+       _ASSIGN(ARGB4444_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
+       _ASSIGN(ARGB1555, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
+       _ASSIGN(ARGB1555_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
+       _ASSIGN(AL88, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
+       _ASSIGN(AL88_REV, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
+       _ASSIGN(RGB332, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z3Y3X2)),
+       _ASSIGN(A8, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8)),
+       _ASSIGN(L8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8)),
+       _ASSIGN(I8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
+       _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
+       _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8) | R300_TX_FORMAT_YUV_MODE),
+       _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8) | R300_TX_FORMAT_YUV_MODE),
+       _ASSIGN(RGB_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1)),
+       _ASSIGN(RGBA_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1)),
+       _ASSIGN(RGBA_DXT3, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3)),
+       _ASSIGN(RGBA_DXT5, R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5)),
+       _ASSIGN(RGBA_FLOAT32, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R32G32B32A32)),
+       _ASSIGN(RGBA_FLOAT16, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R16G16B16A16)),
+       _ASSIGN(RGB_FLOAT32, 0xffffffff),
+       _ASSIGN(RGB_FLOAT16, 0xffffffff),
+       _ASSIGN(ALPHA_FLOAT32, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I32)),
+       _ASSIGN(ALPHA_FLOAT16, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I16)),
+       _ASSIGN(LUMINANCE_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I32)),
+       _ASSIGN(LUMINANCE_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I16)),
+       _ASSIGN(LUMINANCE_ALPHA_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I32A32)),
+       _ASSIGN(LUMINANCE_ALPHA_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I16A16)),
+       _ASSIGN(INTENSITY_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, X, FL_I32)),
+       _ASSIGN(INTENSITY_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, X, FL_I16)),
+       _ASSIGN(Z16, R300_EASY_TX_FORMAT(X, X, X, X, X16)),
+       _ASSIGN(Z24_S8, R300_EASY_TX_FORMAT(X, X, X, X, X24_Y8)),
+       _ASSIGN(Z32, R300_EASY_TX_FORMAT(X, X, X, X, X32)),
+       /* *INDENT-ON* */
+};
 
 #undef _ASSIGN
 
+void r300SetDepthTexMode(struct gl_texture_object *tObj)
+{
+       static const GLuint formats[3][3] = {
+               {
+                       R300_EASY_TX_FORMAT(X, X, X, ONE, X16),
+                       R300_EASY_TX_FORMAT(X, X, X, X, X16),
+                       R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X16),
+               },
+               {
+                       R300_EASY_TX_FORMAT(X, X, X, ONE, X24_Y8),
+                       R300_EASY_TX_FORMAT(X, X, X, X, X24_Y8),
+                       R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X24_Y8),
+               },
+               {
+                       R300_EASY_TX_FORMAT(X, X, X, ONE, X32),
+                       R300_EASY_TX_FORMAT(X, X, X, X, X32),
+                       R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X32),
+               },
+       };
+       const GLuint *format;
+       r300TexObjPtr t;
+
+       if (!tObj)
+               return;
+
+       t = (r300TexObjPtr) tObj->DriverData;
+
+
+       switch (tObj->Image[0][tObj->BaseLevel]->TexFormat->MesaFormat) {
+       case MESA_FORMAT_Z16:
+               format = formats[0];
+               break;
+       case MESA_FORMAT_Z24_S8:
+               format = formats[1];
+               break;
+       case MESA_FORMAT_Z32:
+               format = formats[2];
+               break;
+       default:
+               /* Error...which should have already been caught by higher
+                * levels of Mesa.
+                */
+               ASSERT(0);
+               return;
+       }
+
+       switch (tObj->DepthMode) {
+       case GL_LUMINANCE:
+               t->format = format[0];
+               break;
+       case GL_INTENSITY:
+               t->format = format[1];
+               break;
+       case GL_ALPHA:
+               t->format = format[2];
+               break;
+       default:
+               /* Error...which should have already been caught by higher
+                * levels of Mesa.
+                */
+               ASSERT(0);
+               return;
+       }
+}
+
+
+/**
+ * Compute sizes and fill in offset and blit information for the given
+ * image (determined by \p face and \p level).
+ *
+ * \param curOffset points to the offset at which the image is to be stored
+ * and is updated by this function according to the size of the image.
+ */
+static void compute_tex_image_offset(
+       struct gl_texture_object *tObj,
+       GLuint face,
+       GLint level,
+       GLint* curOffset)
+{
+       r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+       const struct gl_texture_image* texImage;
+       GLuint blitWidth = R300_BLIT_WIDTH_BYTES;
+       GLuint texelBytes;
+       GLuint size;
+
+       texImage = tObj->Image[0][level + t->base.firstLevel];
+       if (!texImage)
+               return;
+
+       texelBytes = texImage->TexFormat->TexelBytes;
+
+       /* find image size in bytes */
+       if (texImage->IsCompressed) {
+               if ((t->format & R300_TX_FORMAT_DXT1) ==
+                       R300_TX_FORMAT_DXT1) {
+                       // fprintf(stderr,"DXT 1 %d %08X\n", texImage->Width, t->format);
+                       if ((texImage->Width + 3) < 8)  /* width one block */
+                               size = texImage->CompressedSize * 4;
+                       else if ((texImage->Width + 3) < 16)
+                               size = texImage->CompressedSize * 2;
+                       else
+                               size = texImage->CompressedSize;
+               } else {
+                       /* DXT3/5, 16 bytes per block */
+                       WARN_ONCE
+                               ("DXT 3/5 suffers from multitexturing problems!\n");
+                       // fprintf(stderr,"DXT 3/5 %d\n", texImage->Width);
+                       if ((texImage->Width + 3) < 8)
+                               size = texImage->CompressedSize * 2;
+                       else
+                               size = texImage->CompressedSize;
+               }
+       } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+               size =
+                       ((texImage->Width * texelBytes +
+                       63) & ~63) * texImage->Height;
+               blitWidth = 64 / texelBytes;
+       } else if (t->tile_bits & R300_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 */
+               int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
+               size =
+                       (w * ((texImage->Height + 1) / 2)) *
+                       texImage->Depth;
+               blitWidth = MAX2(texImage->Width, 64 / texelBytes);
+       } else {
+               int w = (texImage->Width * texelBytes + 31) & ~31;
+               size = w * texImage->Height * texImage->Depth;
+               blitWidth = MAX2(texImage->Width, 64 / texelBytes);
+       }
+       assert(size > 0);
+
+       if (RADEON_DEBUG & DEBUG_TEXTURE)
+               fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n",
+                       texImage->Width, texImage->Height,
+                       texImage->Depth,
+                       texImage->TexFormat->TexelBytes,
+                       texImage->InternalFormat);
+
+       /* All images are aligned to a 32-byte offset */
+       *curOffset = (*curOffset + 0x1f) & ~0x1f;
+
+       if (texelBytes) {
+               /* fix x and y coords up later together with offset */
+               t->image[face][level].x = *curOffset;
+               t->image[face][level].y = 0;
+               t->image[face][level].width =
+                       MIN2(size / texelBytes, blitWidth);
+               t->image[face][level].height =
+                       (size / texelBytes) / t->image[face][level].width;
+       } else {
+               t->image[face][level].x = *curOffset % R300_BLIT_WIDTH_BYTES;
+               t->image[face][level].y = *curOffset / R300_BLIT_WIDTH_BYTES;
+               t->image[face][level].width =
+                       MIN2(size, R300_BLIT_WIDTH_BYTES);
+               t->image[face][level].height = size / t->image[face][level].width;
+       }
+
+       if (RADEON_DEBUG & DEBUG_TEXTURE)
+               fprintf(stderr,
+                       "level %d, face %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
+                       level, face, texImage->Width, texImage->Height,
+                       t->image[face][level].x, t->image[face][level].y,
+                       t->image[face][level].width, t->image[face][level].height,
+                       size, *curOffset);
+
+       *curOffset += size;
+}
+
+
 
 /**
  * This function computes the number of bytes of storage needed for
@@ -166,26 +312,23 @@ static void r300SetTexImages(r300ContextPtr rmesa,
        r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
        const struct gl_texture_image *baseImage =
            tObj->Image[0][tObj->BaseLevel];
-       GLint curOffset, blitWidth;
+       GLint curOffset;
        GLint i, texelBytes;
        GLint numLevels;
        GLint log2Width, log2Height, log2Depth;
 
        /* Set the hardware texture format
         */
-       if (VALID_FORMAT(baseImage->TexFormat->MesaFormat)) {
-               if (_mesa_little_endian()) {
-                       t->format =
-                           tx_table_le[baseImage->TexFormat->MesaFormat].format;
-                       t->filter |=
-                           tx_table_le[baseImage->TexFormat->MesaFormat].filter;
+       if (!t->image_override
+           && VALID_FORMAT(baseImage->TexFormat->MesaFormat)) {
+               if (baseImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
+                       r300SetDepthTexMode(tObj);
                } else {
-                       t->format =
-                           tx_table_be[baseImage->TexFormat->MesaFormat].format;
-                       t->filter |=
-                           tx_table_be[baseImage->TexFormat->MesaFormat].filter;
+                       t->format = tx_table[baseImage->TexFormat->MesaFormat].format;
                }
-       } else {
+
+               t->filter |= tx_table[baseImage->TexFormat->MesaFormat].filter;
+       } else if (!t->image_override) {
                _mesa_problem(NULL, "unexpected texture format in %s",
                              __FUNCTION__);
                return;
@@ -202,33 +345,34 @@ static void r300SetTexImages(r300ContextPtr rmesa,
 
        numLevels = t->base.lastLevel - t->base.firstLevel + 1;
 
-       assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
+       assert(numLevels <= R300_MAX_TEXTURE_LEVELS);
 
        /* Calculate mipmap offsets and dimensions for blitting (uploading)
         * The idea is that we lay out the mipmap levels within a block of
         * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
         */
-       curOffset = 0;
-       blitWidth = R300_BLIT_WIDTH_BYTES;
        t->tile_bits = 0;
 
        /* figure out if this texture is suitable for tiling. */
-#if 0 /* Disabled for now */
+#if 0                          /* Disabled for now */
        if (texelBytes) {
-               if (rmesa->texmicrotile  && (tObj->Target != GL_TEXTURE_RECTANGLE_NV) &&
-                  /* texrect might be able to use micro tiling too in theory? */
-                  (baseImage->Height > 1)) {
-                       
+               if ((tObj->Target != GL_TEXTURE_RECTANGLE_NV) &&
+                   /* texrect might be able to use micro tiling too in theory? */
+                   (baseImage->Height > 1)) {
+
                        /* allow 32 (bytes) x 1 mip (which will use two times the space
                           the non-tiled version would use) max if base texture is large enough */
                        if ((numLevels == 1) ||
-                               (((baseImage->Width * texelBytes / baseImage->Height) <= 32) &&
-                               (baseImage->Width * texelBytes > 64)) ||
-                               ((baseImage->Width * texelBytes / baseImage->Height) <= 16)) {
+                           (((baseImage->Width * texelBytes /
+                              baseImage->Height) <= 32)
+                            && (baseImage->Width * texelBytes > 64))
+                           ||
+                           ((baseImage->Width * texelBytes /
+                             baseImage->Height) <= 16)) {
                                t->tile_bits |= R300_TXO_MICRO_TILE;
                        }
                }
-               
+
                if (tObj->Target != GL_TEXTURE_RECTANGLE_NV) {
                        /* we can set macro tiling even for small textures, they will be untiled anyway */
                        t->tile_bits |= R300_TXO_MACRO_TILE;
@@ -236,184 +380,76 @@ static void r300SetTexImages(r300ContextPtr rmesa,
        }
 #endif
 
-       for (i = 0; i < numLevels; i++) {
-         const struct gl_texture_image *texImage;
-         GLuint size;
-         
-         texImage = tObj->Image[0][i + t->base.firstLevel];
-         if (!texImage)
-           break;
-         
-         /* find image size in bytes */
-         if (texImage->IsCompressed) {
-           if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1) {
-             // fprintf(stderr,"DXT 1 %d %08X\n", texImage->Width, t->format);
-             if ((texImage->Width + 3) < 8) /* width one block */
-               size = texImage->CompressedSize * 4;
-             else if ((texImage->Width + 3) < 16)
-               size = texImage->CompressedSize * 2;
-             else size = texImage->CompressedSize;
-           }
-           else /* DXT3/5, 16 bytes per block */
-           {
-             WARN_ONCE("DXT 3/5 suffers from multitexturing problems!\n");
-             // fprintf(stderr,"DXT 3/5 %d\n", texImage->Width);
-             if ((texImage->Width + 3) < 8)
-               size = texImage->CompressedSize * 2;
-             else size = texImage->CompressedSize;
-           }
-           
-         } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
-           size = ((texImage->Width * texelBytes + 63) & ~63) * texImage->Height;
-           blitWidth = 64 / texelBytes;
-         } else if (t->tile_bits & R300_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 */
-               int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
-               size = (w * ((texImage->Height + 1) / 2)) * texImage->Depth;
-               blitWidth = MAX2(texImage->Width, 64 / texelBytes);
-         } else {
-           int w = (texImage->Width * texelBytes + 31) & ~31;
-           size = w * texImage->Height * texImage->Depth;
-           blitWidth = MAX2(texImage->Width, 64 / texelBytes);
-         }
-         assert(size > 0);
-         
-         if(0)
-           fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage->Width, texImage->Height,
-                   texImage->Depth, texImage->TexFormat->TexelBytes,
-                   texImage->InternalFormat);
-         
-         /* Align to 32-byte offset.  It is faster to do this unconditionally
-          * (no branch penalty).
-          */
-         
-         curOffset = (curOffset + 0x1f) & ~0x1f;
-         
-         if (texelBytes) {
-           t->image[0][i].x = curOffset; /* fix x and y coords up later together with offset */
-           t->image[0][i].y = 0;
-           t->image[0][i].width = MIN2(size / texelBytes, blitWidth);
-           t->image[0][i].height = (size / texelBytes) / t->image[0][i].width;
-         } else {
-           t->image[0][i].x = curOffset % R300_BLIT_WIDTH_BYTES;
-           t->image[0][i].y = curOffset / R300_BLIT_WIDTH_BYTES;
-           t->image[0][i].width = MIN2(size, R300_BLIT_WIDTH_BYTES);
-           t->image[0][i].height = size / t->image[0][i].width;
-         }
-#if 0
-         /* for debugging only and only  applicable to non-rectangle targets */
-         assert(size % t->image[0][i].width == 0);
-         assert(t->image[0][i].x == 0
-                || (size < R300_BLIT_WIDTH_BYTES
-                    && t->image[0][i].height == 1));
-#endif
-         
-         if (0)
-           fprintf(stderr,
-                   "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
-                   i, texImage->Width, texImage->Height,
-                   t->image[0][i].x, t->image[0][i].y,
-                   t->image[0][i].width, t->image[0][i].height,
-                   size, curOffset);
-         
-         curOffset += size;
-         
+       curOffset = 0;
+
+       if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
+               ASSERT(log2Width == log2Height);
+               t->format |= R300_TX_FORMAT_CUBIC_MAP;
+
+               for(i = 0; i < numLevels; i++) {
+                       GLuint face;
+                       for(face = 0; face < 6; face++)
+                               compute_tex_image_offset(tObj, face, i, &curOffset);
+               }
+       } else {
+               if (tObj->Target == GL_TEXTURE_3D)
+                       t->format |= R300_TX_FORMAT_3D;
+
+               for (i = 0; i < numLevels; i++)
+                       compute_tex_image_offset(tObj, 0, i, &curOffset);
        }
-       
+
        /* Align the total size of texture memory block.
         */
        t->base.totalSize =
            (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
 
-       /* Setup remaining cube face blits, if needed */
-       if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
-               GLuint face;
-               for (face = 1; face < 6; face++) {
-                       for (i = 0; i < numLevels; i++) {
-                               t->image[face][i].x = t->image[0][i].x;
-                               t->image[face][i].y = t->image[0][i].y;
-                               t->image[face][i].width = t->image[0][i].width;
-                               t->image[face][i].height =
-                                   t->image[0][i].height;
-                       }
-               }
-               t->base.totalSize *= 6; /* total texmem needed */
-       }
+       t->size =
+           (((tObj->Image[0][t->base.firstLevel]->Width -
+              1) << R300_TX_WIDTHMASK_SHIFT)
+            | ((tObj->Image[0][t->base.firstLevel]->Height - 1) <<
+               R300_TX_HEIGHTMASK_SHIFT)
+            | ((tObj->Image[0][t->base.firstLevel]->DepthLog2) <<
+               R300_TX_DEPTHMASK_SHIFT))
+           | ((numLevels - 1) << R300_TX_MAX_MIP_LEVEL_SHIFT);
 
-       /* Hardware state:
-        */
-#if 0
-       t->format &= ~(R200_TXFORMAT_WIDTH_MASK |
-                           R200_TXFORMAT_HEIGHT_MASK |
-                           R200_TXFORMAT_CUBIC_MAP_ENABLE |
-                           R200_TXFORMAT_F5_WIDTH_MASK |
-                           R200_TXFORMAT_F5_HEIGHT_MASK);
-       t->format |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) |
-                          (log2Height << R200_TXFORMAT_HEIGHT_SHIFT));
-#endif
-#if 0
-       t->format_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK);
-       if (tObj->Target == GL_TEXTURE_3D) {
-               t->format_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
-               t->format_x |= R200_TEXCOORD_VOLUME;
-       } else if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
-               ASSERT(log2Width == log2Height);
-               t->format |= R300_TX_FORMAT_CUBIC_MAP;
-               
-               t->format_x |= R200_TEXCOORD_CUBIC_ENV;
-               t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
-                                    (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
-                                    (log2Width << R200_FACE_WIDTH_2_SHIFT) |
-                                    (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
-                                    (log2Width << R200_FACE_WIDTH_3_SHIFT) |
-                                    (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
-                                    (log2Width << R200_FACE_WIDTH_4_SHIFT) |
-                                    (log2Height << R200_FACE_HEIGHT_4_SHIFT));
-       }
-#endif
-       if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
-               ASSERT(log2Width == log2Height);
-               t->format |= R300_TX_FORMAT_CUBIC_MAP;
-       }
-       
-       t->size = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
-                       |((tObj->Image[0][t->base.firstLevel]->Height - 1) << R300_TX_HEIGHTMASK_SHIFT))
-                       |((numLevels - 1) << R300_TX_MAX_MIP_LEVEL_SHIFT);
+       t->pitch = 0;
 
        /* Only need to round to nearest 32 for textures, but the blitter
         * requires 64-byte aligned pitches, and we may/may not need the
         * blitter.   NPOT only!
         */
        if (baseImage->IsCompressed) {
-               t->pitch =
+               t->pitch |=
                    (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
-       }
-       else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
-               unsigned int align = blitWidth - 1;
-               t->pitch = ((tObj->Image[0][t->base.firstLevel]->Width *
-                     texelBytes) + 63) & ~(63);
+       } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+               unsigned int align = (64 / texelBytes) - 1;
+               t->pitch |= ((tObj->Image[0][t->base.firstLevel]->Width *
+                            texelBytes) + 63) & ~(63);
                t->size |= R300_TX_SIZE_TXPITCH_EN;
-               t->pitch_reg = (((tObj->Image[0][t->base.firstLevel]->Width) + align) & ~align) - 1;
-       }
-       else {
-               t->pitch =
+               if (!t->image_override)
+                       t->pitch_reg =
+                           (((tObj->Image[0][t->base.firstLevel]->Width) +
+                             align) & ~align) - 1;
+       } else {
+               t->pitch |=
                    ((tObj->Image[0][t->base.firstLevel]->Width *
                      texelBytes) + 63) & ~(63);
        }
 
-       t->dirty_state = TEX_ALL;
-
-       /* FYI: r300UploadTexImages( rmesa, t ) used to be called here */
+       if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+           if (tObj->Image[0][t->base.firstLevel]->Width > 2048)
+               t->pitch_reg |= R500_TXWIDTH_BIT11;
+           if (tObj->Image[0][t->base.firstLevel]->Height > 2048)
+               t->pitch_reg |= R500_TXHEIGHT_BIT11;
+       }
 }
 
-
 /* ================================================================
  * Texture unit state management
  */
 
-static GLboolean enable_tex_2d(GLcontext * ctx, int unit)
+static GLboolean r300EnableTexture2D(GLcontext * ctx, int unit)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
@@ -424,35 +460,26 @@ static GLboolean enable_tex_2d(GLcontext * ctx, int unit)
 
        if (t->base.dirty_images[0]) {
                R300_FIREVERTICES(rmesa);
+
                r300SetTexImages(rmesa, tObj);
                r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
-               if (!t->base.memBlock)
+               if (!t->base.memBlock && !t->image_override)
                        return GL_FALSE;
        }
 
        return GL_TRUE;
 }
 
-#if ENABLE_HW_3D_TEXTURE
-static GLboolean enable_tex_3d(GLcontext * ctx, int unit)
+static GLboolean r300EnableTexture3D(GLcontext * ctx, int unit)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
        struct gl_texture_object *tObj = texUnit->_Current;
        r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
 
-       /* Need to load the 3d images associated with this unit.
-        */
-#if 0
-       if (t->format & R200_TXFORMAT_NON_POWER2) {
-               t->format &= ~R200_TXFORMAT_NON_POWER2;
-               t->base.dirty_images[0] = ~0;
-       }
-#endif
        ASSERT(tObj->Target == GL_TEXTURE_3D);
 
-       /* R100 & R200 do not support mipmaps for 3D textures.
-        */
+       /* r300 does not support mipmaps for 3D textures. */
        if ((tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) {
                return GL_FALSE;
        }
@@ -467,9 +494,8 @@ static GLboolean enable_tex_3d(GLcontext * ctx, int unit)
 
        return GL_TRUE;
 }
-#endif
 
-static GLboolean enable_tex_cube(GLcontext * ctx, int unit)
+static GLboolean r300EnableTextureCube(GLcontext * ctx, int unit)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
@@ -477,15 +503,6 @@ static GLboolean enable_tex_cube(GLcontext * ctx, int unit)
        r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
        GLuint face;
 
-       /* Need to load the 2d images associated with this unit.
-        */
-#if 0
-       if (t->format & R200_TXFORMAT_NON_POWER2) {
-               t->format &= ~R200_TXFORMAT_NON_POWER2;
-               for (face = 0; face < 6; face++)
-                       t->base.dirty_images[face] = ~0;
-       }
-#endif
        ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
 
        if (t->base.dirty_images[0] || t->base.dirty_images[1] ||
@@ -514,7 +531,7 @@ static GLboolean enable_tex_cube(GLcontext * ctx, int unit)
        return GL_TRUE;
 }
 
-static GLboolean enable_tex_rect(GLcontext * ctx, int unit)
+static GLboolean r300EnableTextureRect(GLcontext * ctx, int unit)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
@@ -525,46 +542,100 @@ static GLboolean enable_tex_rect(GLcontext * ctx, int unit)
 
        if (t->base.dirty_images[0]) {
                R300_FIREVERTICES(rmesa);
+
                r300SetTexImages(rmesa, tObj);
                r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
-               if (!t->base.memBlock && !rmesa->prefer_gart_client_texturing)
+               if (!t->base.memBlock && !t->image_override &&
+                   !rmesa->prefer_gart_client_texturing)
                        return GL_FALSE;
        }
 
        return GL_TRUE;
 }
 
-static GLboolean update_tex_common(GLcontext * ctx, int unit)
+static GLboolean r300UpdateTexture(GLcontext * ctx, int unit)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-       struct gl_texture_object *tObj = texUnit->_Current;
-       r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+       struct gl_texture_object *tObj = texUnit->_ReallyEnabled ?
+               texUnit->_Current : NULL;
+       r300TexObjPtr t = tObj ? (r300TexObjPtr) tObj->DriverData : NULL;
 
        /* Fallback if there's a texture border */
-       if (tObj->Image[0][tObj->BaseLevel]->Border > 0)
-               return GL_FALSE;
+       if (tObj && tObj->Image[0][tObj->BaseLevel]->Border > 0) {
+               tObj = NULL;
+               t = NULL;
+       }
 
        /* Update state if this is a different texture object to last
         * time.
         */
-       if (rmesa->state.texture.unit[unit].texobj != t) {
+       if (rmesa->state.texture.unit[unit].texobj != tObj) {
                if (rmesa->state.texture.unit[unit].texobj != NULL) {
+                       r300TexObjPtr t_old = (r300TexObjPtr) rmesa->state.texture.unit[unit].texobj->DriverData;
+
                        /* The old texture is no longer bound to this texture unit.
                         * Mark it as such.
                         */
 
-                       rmesa->state.texture.unit[unit].texobj->base.bound &=
-                           ~(1UL << unit);
+                       t_old->base.bound &= ~(1 << unit);
                }
 
-               rmesa->state.texture.unit[unit].texobj = t;
-               t->base.bound |= (1UL << unit);
-               t->dirty_state |= 1 << unit;
-               driUpdateTextureLRU((driTextureObject *) t);    /* XXX: should be locked! */
+               _mesa_reference_texobj(&rmesa->state.texture.unit[unit].texobj, tObj);
+
+               if (t) {
+                       t->base.bound |= (1 << unit);
+                       driUpdateTextureLRU(&t->base);  /* XXX: should be locked! */
+               }
        }
 
-       return !t->border_fallback;
+       return !t || !t->border_fallback;
+}
+
+void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
+                     unsigned long long offset, GLint depth, GLuint pitch)
+{
+       r300ContextPtr rmesa = pDRICtx->driverPrivate;
+       struct gl_texture_object *tObj =
+           _mesa_lookup_texture(rmesa->radeon.glCtx, texname);
+       r300TexObjPtr t;
+       uint32_t pitch_val;
+
+       if (!tObj)
+               return;
+
+       t = (r300TexObjPtr) tObj->DriverData;
+
+       t->image_override = GL_TRUE;
+
+       if (!offset)
+               return;
+
+       t->offset = offset;
+       t->pitch_reg &= (1 << 13) -1;
+       pitch_val = pitch;
+
+       switch (depth) {
+       case 32:
+               t->format = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
+               t->filter |= tx_table[2].filter;
+               pitch_val /= 4;
+               break;
+       case 24:
+       default:
+               t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
+               t->filter |= tx_table[4].filter;
+               pitch_val /= 4;
+               break;
+       case 16:
+               t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
+               t->filter |= tx_table[5].filter;
+               pitch_val /= 2;
+               break;
+       }
+       pitch_val--;
+
+       t->pitch_reg |= pitch_val;
 }
 
 static GLboolean r300UpdateTextureUnit(GLcontext * ctx, int unit)
@@ -572,39 +643,33 @@ static GLboolean r300UpdateTextureUnit(GLcontext * ctx, int unit)
        struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
 
        if (texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT)) {
-               return (enable_tex_rect(ctx, unit) &&
-                       update_tex_common(ctx, unit));
+               return (r300EnableTextureRect(ctx, unit) &&
+                       r300UpdateTexture(ctx, unit));
        } else if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
-               return (enable_tex_2d(ctx, unit) &&
-                       update_tex_common(ctx, unit));
-       }
-#if ENABLE_HW_3D_TEXTURE
-       else if (texUnit->_ReallyEnabled & (TEXTURE_3D_BIT)) {
-               return (enable_tex_3d(ctx, unit) &&
-                       update_tex_common(ctx, unit));
-       }
-#endif
-       else if (texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT)) {
-               return (enable_tex_cube(ctx, unit) &&
-                       update_tex_common(ctx, unit));
+               return (r300EnableTexture2D(ctx, unit) &&
+                       r300UpdateTexture(ctx, unit));
+       } else if (texUnit->_ReallyEnabled & (TEXTURE_3D_BIT)) {
+               return (r300EnableTexture3D(ctx, unit) &&
+                       r300UpdateTexture(ctx, unit));
+       } else if (texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT)) {
+               return (r300EnableTextureCube(ctx, unit) &&
+                       r300UpdateTexture(ctx, unit));
        } else if (texUnit->_ReallyEnabled) {
                return GL_FALSE;
        } else {
-               return GL_TRUE;
-       }
+               return r300UpdateTexture(ctx, unit);
+       }
 }
 
 void r300UpdateTextureState(GLcontext * ctx)
 {
-       GLboolean ok;
-
-       ok = (r300UpdateTextureUnit(ctx, 0) &&
-             r300UpdateTextureUnit(ctx, 1) &&
-             r300UpdateTextureUnit(ctx, 2) &&
-             r300UpdateTextureUnit(ctx, 3) &&
-             r300UpdateTextureUnit(ctx, 4) &&
-             r300UpdateTextureUnit(ctx, 5) &&
-             r300UpdateTextureUnit(ctx, 6) &&
-             r300UpdateTextureUnit(ctx, 7)
-             );
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               if (!r300UpdateTextureUnit(ctx, i)) {
+                       _mesa_warning(ctx,
+                                     "failed to update texture state for unit %d.\n",
+                                     i);
+               }
+       }
 }