radeon/r200/r300: another big merge upheavel.
[mesa.git] / src / mesa / drivers / dri / r300 / r300_texstate.c
index 49231d415f52becd399b48f6d8b891d5241bb041..50ecc570bd115f7867b1c694594b2797611158bd 100644 (file)
@@ -27,29 +27,36 @@ 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"
 #include "r300_ioctl.h"
-#include "radeon_ioctl.h"
+#include "radeon_mipmap_tree.h"
+#include "radeon_cs.h"
 #include "r300_tex.h"
 #include "r300_reg.h"
+#include "radeon_buffer.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}
@@ -63,58 +70,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * identically.  -- paulus
  */
 
-static const struct {
-       GLuint format, filter, flag;
-} tx_table_be[] = {
-       /* *INDENT-OFF* */
-       _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)),
-       /* *INDENT-ON* */
-};
-
-static const struct {
+static const struct tx_table {
        GLuint format, filter, flag;
-} tx_table_le[] = {
+} 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)),
-       _ASSIGN(RGB888, 0xffffffff),
+#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)),
@@ -128,8 +99,8 @@ static const struct {
        _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(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)),
@@ -146,429 +117,360 @@ static const struct {
        _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
 
-/**
- * This function computes the number of bytes of storage needed for
- * the given texture object (all mipmap levels, all cube faces).
- * The \c image[face][level].x/y/width/height parameters for upload/blitting
- * are computed here.  \c filter, \c format, etc. will be set here
- * too.
- *
- * \param rmesa Context pointer
- * \param tObj GL texture object whose images are to be posted to
- *                 hardware state.
- */
-static void r300SetTexImages(r300ContextPtr rmesa,
-                            struct gl_texture_object *tObj)
+void r300SetDepthTexMode(struct gl_texture_object *tObj)
 {
-       r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
-       const struct gl_texture_image *baseImage =
-           tObj->Image[0][tObj->BaseLevel];
-       GLint curOffset, blitWidth;
-       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;
-               } else {
-                       t->format =
-                           tx_table_be[baseImage->TexFormat->MesaFormat].
-                           format;
-                       t->filter |=
-                           tx_table_be[baseImage->TexFormat->MesaFormat].
-                           filter;
-               }
-       } else {
-               _mesa_problem(NULL, "unexpected texture format in %s",
-                             __FUNCTION__);
+       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;
+       radeonTexObjPtr t;
+
+       if (!tObj)
                return;
-       }
-
-       texelBytes = baseImage->TexFormat->TexelBytes;
-
-       /* Compute which mipmap levels we really want to send to the hardware.
-        */
-       driCalculateTextureFirstLastLevel((driTextureObject *) t);
-       log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
-       log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
-       log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
-
-       numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
-       assert(numLevels <= RADEON_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 (texelBytes) {
-               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)) {
-                               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;
-               }
+       t = radeon_tex_obj(tObj);
+
+       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;
        }
-#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 (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);
 
-               /* Align to 32-byte offset.  It is faster to do this unconditionally
-                * (no branch penalty).
+       switch (tObj->DepthMode) {
+       case GL_LUMINANCE:
+               t->pp_txformat = format[0];
+               break;
+       case GL_INTENSITY:
+               t->pp_txformat = format[1];
+               break;
+       case GL_ALPHA:
+               t->pp_txformat = format[2];
+               break;
+       default:
+               /* Error...which should have already been caught by higher
+                * levels of Mesa.
                 */
+               ASSERT(0);
+               return;
+       }
+}
 
-               curOffset = (curOffset + 0x1f) & ~0x1f;
 
-               if (texelBytes) {
-                       /* fix x and y coords up later together with offset */
-                       t->image[0][i].x = curOffset;
-                       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;
+/**
+ * Compute the cached hardware register values for the given texture object.
+ *
+ * \param rmesa Context pointer
+ * \param t the r300 texture object
+ */
+static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
+{
+       const struct gl_texture_image *firstImage =
+           t->base.Image[0][t->mt->firstLevel];
+
+       if (!t->image_override
+           && VALID_FORMAT(firstImage->TexFormat->MesaFormat)) {
+               if (firstImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
+                       r300SetDepthTexMode(&t->base);
                } 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;
+                       t->pp_txformat = tx_table[firstImage->TexFormat->MesaFormat].format;
                }
 
-               if (RADEON_DEBUG & DEBUG_TEXTURE)
-                       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;
+               t->pp_txfilter |= tx_table[firstImage->TexFormat->MesaFormat].filter;
+       } else if (!t->image_override) {
+               _mesa_problem(NULL, "unexpected texture format in %s",
+                             __FUNCTION__);
+               return;
        }
 
-       /* 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->tile_bits = 0;
 
-       if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
-               ASSERT(log2Width == log2Height);
-               t->format |= R300_TX_FORMAT_CUBIC_MAP;
+       if (t->base.Target == GL_TEXTURE_CUBE_MAP)
+               t->pp_txformat |= R300_TX_FORMAT_CUBIC_MAP;
+       if (t->base.Target == GL_TEXTURE_3D)
+               t->pp_txformat |= R300_TX_FORMAT_3D;
+
+       t->pp_txsize = (((firstImage->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
+                       | ((firstImage->Height - 1) << R300_TX_HEIGHTMASK_SHIFT)
+                       | ((firstImage->DepthLog2) << R300_TX_DEPTHMASK_SHIFT)
+                       | ((t->mt->lastLevel - t->mt->firstLevel) << R300_TX_MAX_MIP_LEVEL_SHIFT));
+
+       if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
+               unsigned int align = (64 / t->mt->bpp) - 1;
+               t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
+               if (!t->image_override)
+                       t->pp_txpitch = ((firstImage->Width + align) & ~align) - 1;
        }
 
-       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);
-
-       /* 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 =
-                   (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);
-               t->size |= R300_TX_SIZE_TXPITCH_EN;
-               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);
+       if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+           if (firstImage->Width > 2048)
+               t->pp_txpitch |= R500_TXWIDTH_BIT11;
+           if (firstImage->Height > 2048)
+               t->pp_txpitch |= R500_TXHEIGHT_BIT11;
        }
-
-       t->dirty_state = TEX_ALL;
-
-       /* FYI: r300UploadTexImages( rmesa, t ) used to be called here */
 }
 
-/* ================================================================
- * Texture unit state management
+/**
+ * Ensure the given texture is ready for rendering.
+ *
+ * Mostly this means populating the texture object's mipmap tree.
  */
-
-static GLboolean enable_tex_2d(GLcontext * ctx, int unit)
+static GLboolean r300_validate_texture(GLcontext * ctx, struct gl_texture_object *texObj)
 {
        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;
+       radeonTexObj *t = radeon_tex_obj(texObj);
 
-       ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
+       if (!radeon_validate_texture_miptree(ctx, texObj))
+               return GL_FALSE;
 
-       if (t->base.dirty_images[0]) {
-               R300_FIREVERTICES(rmesa);
-               r300SetTexImages(rmesa, tObj);
-               r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
-               if (!t->base.memBlock)
-                       return GL_FALSE;
-       }
+       /* Configure the hardware registers (more precisely, the cached version
+        * of the hardware registers). */
+       setup_hardware_state(rmesa, t);
 
+       t->validated = GL_TRUE;
        return GL_TRUE;
 }
 
-#if ENABLE_HW_3D_TEXTURE
-static GLboolean enable_tex_3d(GLcontext * ctx, int unit)
+
+/**
+ * Ensure all enabled and complete textures are uploaded along with any buffers being used.
+ */
+GLboolean r300ValidateBuffers(GLcontext * ctx)
 {
        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;
-
-       ASSERT(tObj->Target == GL_TEXTURE_3D);
-
-       /* r300 does not support mipmaps for 3D textures. */
-       if ((tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) {
-               return GL_FALSE;
+       struct radeon_cs_space_check bos[16];
+       struct radeon_renderbuffer *rrb;
+       int num_bo = 0;
+       int i;
+       int flushed = 0, ret;
+again:
+       num_bo = 0;
+
+       rrb = radeon_get_colorbuffer(&rmesa->radeon);
+       /* color buffer */
+       if (rrb && rrb->bo) {
+               bos[num_bo].bo = rrb->bo;
+               bos[num_bo].read_domains = 0;
+               bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
+               bos[num_bo].new_accounted = 0;
+               num_bo++;
        }
 
-       if (t->base.dirty_images[0]) {
-               R300_FIREVERTICES(rmesa);
-               r300SetTexImages(rmesa, tObj);
-               r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
-               if (!t->base.memBlock)
-                       return GL_FALSE;
+       /* depth buffer */
+       rrb = radeon_get_depthbuffer(&rmesa->radeon);
+       /* color buffer */
+       if (rrb && rrb->bo) {
+               bos[num_bo].bo = rrb->bo;
+               bos[num_bo].read_domains = 0;
+               bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
+               bos[num_bo].new_accounted = 0;
+               num_bo++;
        }
+       
+       for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
+               radeonTexObj *t;
 
-       return GL_TRUE;
-}
-#endif
-
-static GLboolean enable_tex_cube(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;
-       GLuint face;
-
-       ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
-
-       if (t->base.dirty_images[0] || t->base.dirty_images[1] ||
-           t->base.dirty_images[2] || t->base.dirty_images[3] ||
-           t->base.dirty_images[4] || t->base.dirty_images[5]) {
-               /* flush */
-               R300_FIREVERTICES(rmesa);
-               /* layout memory space, once for all faces */
-               r300SetTexImages(rmesa, tObj);
-       }
+               if (!ctx->Texture.Unit[i]._ReallyEnabled)
+                       continue;
 
-       /* upload (per face) */
-       for (face = 0; face < 6; face++) {
-               if (t->base.dirty_images[face]) {
-                       r300UploadTexImages(rmesa,
-                                           (r300TexObjPtr) tObj->DriverData,
-                                           face);
+               if (!r300_validate_texture(ctx, ctx->Texture.Unit[i]._Current)) {
+                       _mesa_warning(ctx,
+                                     "failed to validate texture for unit %d.\n",
+                                     i);
                }
+               t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
+               bos[num_bo].bo = t->mt->bo;
+               bos[num_bo].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+               bos[num_bo].write_domain = 0;
+               bos[num_bo].new_accounted = 0;
+               num_bo++;
        }
 
-       if (!t->base.memBlock) {
-               /* texmem alloc failed, use s/w fallback */
+       ret = radeon_cs_space_check(rmesa->radeon.cmdbuf.cs, bos, num_bo);
+       if (ret == RADEON_CS_SPACE_OP_TO_BIG)
                return GL_FALSE;
-       }
-
-       return GL_TRUE;
-}
-
-static GLboolean enable_tex_rect(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;
-
-       ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
-
-       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 (ret == RADEON_CS_SPACE_FLUSH) {
+               r300Flush(ctx);
+               if (flushed)
                        return GL_FALSE;
+               flushed = 1;
+               goto again;
        }
-
        return GL_TRUE;
 }
 
-static GLboolean update_tex_common(GLcontext * ctx, int unit)
+void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
+                     unsigned long long offset, GLint depth, GLuint pitch)
 {
-       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;
+       r300ContextPtr rmesa = pDRICtx->driverPrivate;
+       struct gl_texture_object *tObj =
+           _mesa_lookup_texture(rmesa->radeon.glCtx, texname);
+       radeonTexObjPtr t = radeon_tex_obj(tObj);
+       uint32_t pitch_val;
 
-       /* Fallback if there's a texture border */
-       if (tObj->Image[0][tObj->BaseLevel]->Border > 0)
-               return GL_FALSE;
+       if (!tObj)
+               return;
 
-       /* 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 != NULL) {
-                       /* 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->image_override = GL_TRUE;
+
+       if (!offset)
+               return;
 
-               rmesa->state.texture.unit[unit].texobj = t;
-               t->base.bound |= (1UL << unit);
-               t->dirty_state |= 1 << unit;
-               driUpdateTextureLRU((driTextureObject *) t);    /* XXX: should be locked! */
+       t->bo = NULL;
+       t->override_offset = offset;
+       t->pp_txpitch &= (1 << 13) -1;
+       pitch_val = pitch;
+
+       switch (depth) {
+       case 32:
+               t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
+               t->pp_txfilter |= tx_table[2].filter;
+               pitch_val /= 4;
+               break;
+       case 24:
+       default:
+               t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
+               t->pp_txfilter |= tx_table[4].filter;
+               pitch_val /= 4;
+               break;
+       case 16:
+               t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
+               t->pp_txfilter |= tx_table[5].filter;
+               pitch_val /= 2;
+               break;
        }
+       pitch_val--;
 
-       return !t->border_fallback;
+       t->pp_txpitch |= pitch_val;
 }
 
-static GLboolean r300UpdateTextureUnit(GLcontext * ctx, int unit)
+void r300SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
 {
-       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));
-       } else if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
-               return (enable_tex_2d(ctx, unit) &&
-                       update_tex_common(ctx, unit));
+       struct gl_texture_unit *texUnit;
+       struct gl_texture_object *texObj;
+       struct gl_texture_image *texImage;
+       struct radeon_renderbuffer *rb;
+       radeon_texture_image *rImage;
+       radeonContextPtr radeon;
+       r300ContextPtr rmesa;
+       GLframebuffer *fb;
+       radeonTexObjPtr t;
+       uint32_t pitch_val;
+
+       target = GL_TEXTURE_RECTANGLE_ARB;
+
+       radeon = pDRICtx->driverPrivate;
+       rmesa = pDRICtx->driverPrivate;
+
+       fb = dPriv->driverPrivate;
+        texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit];
+       texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target);
+        texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0);
+
+       rImage = get_radeon_texture_image(texImage);
+       t = radeon_tex_obj(texObj);
+        if (t == NULL) {
+           return;
+       }
+
+       radeon_update_renderbuffers(pDRICtx, dPriv);
+       /* back & depth buffer are useless free them right away */
+       rb = (void*)fb->Attachment[BUFFER_DEPTH].Renderbuffer;
+       if (rb && rb->bo) {
+               radeon_bo_unref(rb->bo);
+        rb->bo = NULL;
        }
-#if ENABLE_HW_3D_TEXTURE
-       else if (texUnit->_ReallyEnabled & (TEXTURE_3D_BIT)) {
-               return (enable_tex_3d(ctx, unit) &&
-                       update_tex_common(ctx, unit));
+       rb = (void*)fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+       if (rb && rb->bo) {
+               radeon_bo_unref(rb->bo);
+               rb->bo = NULL;
        }
-#endif
-       else if (texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT)) {
-               return (enable_tex_cube(ctx, unit) &&
-                       update_tex_common(ctx, unit));
-       } else if (texUnit->_ReallyEnabled) {
-               return GL_FALSE;
-       } else {
-               return GL_TRUE;
+       rb = (void*)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+       if (rb->bo == NULL) {
+               /* Failed to BO for the buffer */
+               return;
        }
-}
-
-void r300UpdateTextureState(GLcontext * ctx)
-{
-       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);
-               }
+       
+       _mesa_lock_texture(radeon->glCtx, texObj);
+       if (t->bo) {
+               t->bo = NULL;
+       }
+       if (t->mt) {
+               t->mt = NULL;
+       }
+       if (rImage->mt) {
+               radeon_miptree_unreference(rImage->mt);
+               rImage->mt = NULL;
+       }
+       fprintf(stderr,"settexbuf %dx%d@%d\n", rb->width, rb->height, rb->cpp);
+       _mesa_init_teximage_fields(radeon->glCtx, target, texImage,
+                                  rb->width, rb->height, 1, 0, rb->cpp);
+       texImage->TexFormat = &_mesa_texformat_rgba8888_rev;
+       rImage->bo = rb->bo;
+       
+       t->bo = rb->bo;
+       t->tile_bits = 0;
+       t->image_override = GL_TRUE;
+       t->override_offset = 0;
+       t->pp_txpitch &= (1 << 13) -1;
+       pitch_val = rb->pitch;
+       switch (rb->cpp) {
+       case 4:
+               t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
+               t->pp_txfilter |= tx_table[2].filter;
+               pitch_val /= 4;
+               break;
+       case 3:
+       default:
+               t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
+               t->pp_txfilter |= tx_table[4].filter;
+               pitch_val /= 4;
+               break;
+       case 2:
+               t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
+               t->pp_txfilter |= tx_table[5].filter;
+               pitch_val /= 2;
+               break;
        }
+       pitch_val--;
+       t->pp_txsize = ((rb->width - 1) << R300_TX_WIDTHMASK_SHIFT) |
+              ((rb->height - 1) << R300_TX_HEIGHTMASK_SHIFT);
+       t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
+       t->pp_txpitch |= pitch_val;
+       t->validated = GL_TRUE;
+       _mesa_unlock_texture(radeon->glCtx, texObj);
+       return;
 }