Merge branch 'mesa_7_5_branch'
[mesa.git] / src / mesa / drivers / dri / i915 / i830_texstate.c
index ba452279baf2b695442c40ddf69cbfd8284916ba..6f998fa6f773826eae70dcba0f9f476370cb72e4 100644 (file)
  * 
  **************************************************************************/
 
-#include "glheader.h"
-#include "macros.h"
-#include "mtypes.h"
-#include "simple_list.h"
-#include "enums.h"
-#include "texformat.h"
-#include "texstore.h"
-
-#include "mm.h"
-
-#include "intel_screen.h"
-#include "intel_ioctl.h"
+#include "main/mtypes.h"
+#include "main/enums.h"
+#include "main/texformat.h"
+
+#include "intel_mipmap_tree.h"
 #include "intel_tex.h"
 
 #include "i830_context.h"
 #include "i830_reg.h"
 
-static const GLint initial_offsets[6][2] = { {0,0},
-                                      {0,2},
-                                      {1,0},
-                                      {1,2},
-                                      {1,1},
-                                      {1,3} };
-
-static const GLint step_offsets[6][2] = { {0,2},
-                                   {0,2},
-                                   {-1,2},
-                                   {-1,2},
-                                   {-1,1},
-                                   {-1,1} };
 
-#define I830_TEX_UNIT_ENABLED(unit)            (1<<unit)
 
-static GLboolean i830SetTexImages( i830ContextPtr i830, 
-                                 struct gl_texture_object *tObj )
+static GLuint
+translate_texture_format(GLuint mesa_format, GLuint internal_format)
 {
-   GLuint total_height, pitch, i, textureFormat;
-   i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
-   const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
-   GLint firstLevel, lastLevel, numLevels;
-
-   switch( baseImage->TexFormat->MesaFormat ) {
+   switch (mesa_format) {
    case MESA_FORMAT_L8:
-      t->intel.texelBytes = 1;
-      textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
-      break;
-
+      return MAPSURF_8BIT | MT_8BIT_L8;
    case MESA_FORMAT_I8:
-      t->intel.texelBytes = 1;
-      textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
-      break;
-
+      return MAPSURF_8BIT | MT_8BIT_I8;
    case MESA_FORMAT_A8:
-      t->intel.texelBytes = 1;
-      textureFormat = MAPSURF_8BIT | MT_8BIT_I8; /* Kludge -- check with conform, glean */
-      break;
-
+      return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */
    case MESA_FORMAT_AL88:
-      t->intel.texelBytes = 2;
-      textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
-      break;
-
+      return MAPSURF_16BIT | MT_16BIT_AY88;
    case MESA_FORMAT_RGB565:
-      t->intel.texelBytes = 2;
-      textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
-      break;
-
+      return MAPSURF_16BIT | MT_16BIT_RGB565;
    case MESA_FORMAT_ARGB1555:
-      t->intel.texelBytes = 2;
-      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
-      break;
-
+      return MAPSURF_16BIT | MT_16BIT_ARGB1555;
    case MESA_FORMAT_ARGB4444:
-      t->intel.texelBytes = 2;
-      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
-      break;
-
+      return MAPSURF_16BIT | MT_16BIT_ARGB4444;
    case MESA_FORMAT_ARGB8888:
-      t->intel.texelBytes = 4;
-      textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
-      break;
-
+      if (internal_format == GL_RGB)
+        return MAPSURF_32BIT | MT_32BIT_XRGB8888;
+      else
+        return MAPSURF_32BIT | MT_32BIT_ARGB8888;
    case MESA_FORMAT_YCBCR_REV:
-      t->intel.texelBytes = 2;
-      textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL | 
-                      TM0S1_COLORSPACE_CONVERSION);
-      break;
-
+      return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
    case MESA_FORMAT_YCBCR:
-      t->intel.texelBytes = 2;
-      textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */
-                      TM0S1_COLORSPACE_CONVERSION);
-      break;
-
+      return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
    case MESA_FORMAT_RGB_FXT1:
    case MESA_FORMAT_RGBA_FXT1:
-     t->intel.texelBytes = 2;
-     textureFormat = MAPSURF_COMPRESSED | MT_COMPRESS_FXT1;
-     break;
-
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
    case MESA_FORMAT_RGBA_DXT1:
    case MESA_FORMAT_RGB_DXT1:
-     /* 
-      * DXTn pitches are Width/4 * blocksize in bytes 
-      * for DXT1: blocksize=8 so Width/4*8 = Width * 2 
-      * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
-      */
-     t->intel.texelBytes = 2;
-     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
-     break;
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
    case MESA_FORMAT_RGBA_DXT3:
-     t->intel.texelBytes = 4;
-     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
-     break;
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
    case MESA_FORMAT_RGBA_DXT5:
-     t->intel.texelBytes = 4;
-     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
-     break;
-
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
    default:
-      fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
+      fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format);
       abort();
+      return 0;
    }
-
-   /* Compute which mipmap levels we really want to send to the hardware.
-    * This depends on the base image size, GL_TEXTURE_MIN_LOD,
-    * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
-    * Yes, this looks overly complicated, but it's all needed.
-    */
-   driCalculateTextureFirstLastLevel( (driTextureObject *) t );
+}
 
 
-   /* Figure out the amount of memory required to hold all the mipmap
-    * levels.  Choose the smallest pitch to accomodate the largest
-    * mipmap:
-    */
-   firstLevel = t->intel.base.firstLevel;
-   lastLevel = t->intel.base.lastLevel;
-   numLevels = lastLevel - firstLevel + 1;
 
 
-   /* All images must be loaded at this pitch.  Count the number of
-    * lines required:
-    */
-   switch (tObj->Target) {
-   case GL_TEXTURE_CUBE_MAP: {
-      const GLuint dim = tObj->Image[0][firstLevel]->Width;
-      GLuint face;
-
-      pitch = dim * t->intel.texelBytes;
-      pitch *= 2;              /* double pitch for cube layouts */
-      pitch = (pitch + 3) & ~3;
-      
-      total_height = dim * 4;
-
-      for ( face = 0 ; face < 6 ; face++) {
-        GLuint x = initial_offsets[face][0] * dim;
-        GLuint y = initial_offsets[face][1] * dim;
-        GLuint d = dim;
-        
-        t->intel.base.dirty_images[face] = ~0;
-
-        assert(tObj->Image[face][firstLevel]->Width == dim);
-        assert(tObj->Image[face][firstLevel]->Height == dim);
-
-        for (i = 0; i < numLevels; i++) {
-           t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
-           if (!t->intel.image[face][i].image) {
-              fprintf(stderr, "no image %d %d\n", face, i);
-              break;           /* can't happen */
-           }
-        
-           t->intel.image[face][i].offset = 
-              y * pitch + x * t->intel.texelBytes;
-           t->intel.image[face][i].internalFormat = baseImage->Format;
-
-           d >>= 1;
-           x += step_offsets[face][0] * d;
-           y += step_offsets[face][1] * d;
-        }
-      }
-      break;
-   }
+/* The i915 (and related graphics cores) do not support GL_CLAMP.  The
+ * Intel drivers for "other operating systems" implement GL_CLAMP as
+ * GL_CLAMP_TO_EDGE, so the same is done here.
+ */
+static GLuint
+translate_wrap_mode(GLenum wrap)
+{
+   switch (wrap) {
+   case GL_REPEAT:
+      return TEXCOORDMODE_WRAP;
+   case GL_CLAMP:
+   case GL_CLAMP_TO_EDGE:
+      return TEXCOORDMODE_CLAMP;        /* not really correct */
+   case GL_CLAMP_TO_BORDER:
+      return TEXCOORDMODE_CLAMP_BORDER;
+   case GL_MIRRORED_REPEAT:
+      return TEXCOORDMODE_MIRROR;
    default:
-      pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
-      pitch = (pitch + 3) & ~3;
-      t->intel.base.dirty_images[0] = ~0;
-
-      for ( total_height = i = 0 ; i < numLevels ; i++ ) {
-        t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
-        if (!t->intel.image[0][i].image) 
-           break;
-        
-        t->intel.image[0][i].offset = total_height * pitch;
-        t->intel.image[0][i].internalFormat = baseImage->Format;
-        if (t->intel.image[0][i].image->IsCompressed)
-        {
-          if (t->intel.image[0][i].image->Height > 4)
-            total_height += t->intel.image[0][i].image->Height/4;
-          else
-            total_height += 1;
-        }
-        else
-          total_height += MAX2(2, t->intel.image[0][i].image->Height);
-      }
-      break;
+      return TEXCOORDMODE_WRAP;
    }
-
-   t->intel.Pitch = pitch;
-   t->intel.base.totalSize = total_height*pitch;
-   t->intel.max_level = i-1;
-   t->Setup[I830_TEXREG_TM0S1] = 
-      (((tObj->Image[0][firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) |
-       ((tObj->Image[0][firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) |
-       textureFormat);
-   t->Setup[I830_TEXREG_TM0S2] = 
-      (((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) |
-      TM0S2_CUBE_FACE_ENA_MASK;
-   t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
-   t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
-   t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
-   t->intel.dirty = I830_UPLOAD_TEX_ALL;
-
-   return intelUploadTexImages( &i830->intel, &t->intel, 0 );
 }
 
 
-static void i830_import_tex_unit( i830ContextPtr i830, 
-                          i830TextureObjectPtr t,
-                          GLuint unit )
+/* Recalculate all state from scratch.  Perhaps not the most
+ * efficient, but this has gotten complex enough that we need
+ * something which is understandable and reliable.
+ */
+static GLboolean
+i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
 {
-   if(INTEL_DEBUG&DEBUG_TEXTURE)
-      fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
-   
-   if (i830->intel.CurrentTexObj[unit]) 
-      i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
-
-   i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
-   t->intel.base.bound |= (1 << unit);
-
-   I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
-
-   i830->state.Tex[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 
-                                              (LOAD_TEXTURE_MAP0 << unit) | 4);
-   i830->state.Tex[unit][I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE |
-                                              t->intel.TextureOffset);
-
-   i830->state.Tex[unit][I830_TEXREG_TM0S1] = t->Setup[I830_TEXREG_TM0S1];
-   i830->state.Tex[unit][I830_TEXREG_TM0S2] = t->Setup[I830_TEXREG_TM0S2];
-
-   i830->state.Tex[unit][I830_TEXREG_TM0S3] &= TM0S3_LOD_BIAS_MASK;
-   i830->state.Tex[unit][I830_TEXREG_TM0S3] |= (t->Setup[I830_TEXREG_TM0S3] &
-                                               ~TM0S3_LOD_BIAS_MASK);
-
-   i830->state.Tex[unit][I830_TEXREG_TM0S4] = t->Setup[I830_TEXREG_TM0S4];
-   i830->state.Tex[unit][I830_TEXREG_MCS] = (t->Setup[I830_TEXREG_MCS] & 
-                                            ~MAP_UNIT_MASK);   
-   i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE];
-   i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit);
-
-   t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
-}
-
-
-
-static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
-{
-   i830ContextPtr i830 = I830_CONTEXT(ctx);
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-   struct gl_texture_object *tObj = texUnit->_Current;
-   i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
-
-   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+   GLcontext *ctx = &intel->ctx;
+   struct i830_context *i830 = i830_context(ctx);
+   struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = tUnit->_Current;
+   struct intel_texture_object *intelObj = intel_texture_object(tObj);
+   struct gl_texture_image *firstImage;
+   GLuint *state = i830->state.Tex[unit], format, pitch;
+   GLint lodbias;
+   GLubyte border[4];
+
+   memset(state, 0, sizeof(state));
+
+   /*We need to refcount these. */
+
+   if (i830->state.tex_buffer[unit] != NULL) {
+       dri_bo_unreference(i830->state.tex_buffer[unit]);
+       i830->state.tex_buffer[unit] = NULL;
+   }
 
-   /* Fallback if there's a texture border */
-   if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
-      fprintf(stderr, "Texture border\n");
+   if (!intelObj->imageOverride && !intel_finalize_mipmap_tree(intel, unit))
       return GL_FALSE;
-   }
 
-   /* Upload teximages (not pipelined)
+   /* Get first image here, since intelObj->firstLevel will get set in
+    * the intel_finalize_mipmap_tree() call above.
     */
-   if (t->intel.base.dirty_images[0]) {
-      if (!i830SetTexImages( i830, tObj )) {
-        return GL_FALSE;
+   firstImage = tObj->Image[0][intelObj->firstLevel];
+
+   if (intelObj->imageOverride) {
+      i830->state.tex_buffer[unit] = NULL;
+      i830->state.tex_offset[unit] = intelObj->textureOffset;
+
+      switch (intelObj->depthOverride) {
+      case 32:
+        format = MAPSURF_32BIT | MT_32BIT_ARGB8888;
+        break;
+      case 24:
+      default:
+        format = MAPSURF_32BIT | MT_32BIT_XRGB8888;
+        break;
+      case 16:
+        format = MAPSURF_16BIT | MT_16BIT_RGB565;
+        break;
       }
-   }
 
-   /* Update state if this is a different texture object to last
-    * time.
-    */
-   if (i830->intel.CurrentTexObj[unit] != &t->intel || 
-       (t->intel.dirty & I830_UPLOAD_TEX(unit))) {
-      i830_import_tex_unit( i830, t, unit);
+      pitch = intelObj->pitchOverride;
+   } else {
+      dri_bo_reference(intelObj->mt->region->buffer);
+      i830->state.tex_buffer[unit] = intelObj->mt->region->buffer;
+      i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt,
+                                                               0, intelObj->
+                                                               firstLevel);
+
+      format = translate_texture_format(firstImage->TexFormat->MesaFormat,
+                                       firstImage->InternalFormat);
+      pitch = intelObj->mt->pitch * intelObj->mt->cpp;
    }
 
-   I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
+   state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+                               (LOAD_TEXTURE_MAP0 << unit) | 4);
 
-   return GL_TRUE;
-}
+   state[I830_TEXREG_TM0S1] =
+      (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
+       ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);
 
-static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
-{
-   i830ContextPtr i830 = I830_CONTEXT(ctx);
-   GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
-
-   mcs &= ~TEXCOORDS_ARE_NORMAL;
-   mcs |= TEXCOORDS_ARE_IN_TEXELUNITS;
-
-   if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
-       || (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
-      I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
-      i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
-      i830->state.Tex[unit][I830_TEXREG_CUBE] = 0;
+   if (intelObj->mt->region->tiling != I915_TILING_NONE) {
+      state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE;
+      if (intelObj->mt->region->tiling == I915_TILING_Y)
+        state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK;
    }
 
-   return GL_TRUE;
-}
-
-
-static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
-{
-   i830ContextPtr i830 = I830_CONTEXT(ctx);
-   GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
-
-   mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
-   mcs |= TEXCOORDS_ARE_NORMAL;
-
-   if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
-       || (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
-      I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
-      i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
-      i830->state.Tex[unit][I830_TEXREG_CUBE] = 0;
+   state[I830_TEXREG_TM0S2] =
+      ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);
+
+   {
+      if (tObj->Target == GL_TEXTURE_CUBE_MAP)
+         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
+                                    CUBE_NEGX_ENABLE |
+                                    CUBE_POSX_ENABLE |
+                                    CUBE_NEGY_ENABLE |
+                                    CUBE_POSY_ENABLE |
+                                    CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE);
+      else
+         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
    }
 
-   return GL_TRUE;
-}
 
-static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
-{
-   i830ContextPtr i830 = I830_CONTEXT(ctx);
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-   struct gl_texture_object *tObj = texUnit->_Current;
-   i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
-   GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
-   const GLuint cube = CUBE_NEGX_ENABLE | CUBE_POSX_ENABLE
-     | CUBE_NEGY_ENABLE | CUBE_POSY_ENABLE
-     | CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE;
-   GLuint face;
-
-   mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
-   mcs |= TEXCOORDS_ARE_NORMAL;
-
-   if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
-       || (cube != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
-      I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
-      i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
-      i830->state.Tex[unit][I830_TEXREG_CUBE] = cube;
-   }
 
-   /* Upload teximages (not pipelined)
-    */
-   if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
-        t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
-        t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
-      i830SetTexImages( i830, tObj );
-   }
 
-   /* upload (per face) */
-   for (face = 0; face < 6; face++) {
-      if (t->intel.base.dirty_images[face]) {
-        if (!intelUploadTexImages( &i830->intel, &t->intel, face )) {
-           return GL_FALSE;
-        }
+   {
+      GLuint minFilt, mipFilt, magFilt;
+
+      switch (tObj->MinFilter) {
+      case GL_NEAREST:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_NONE;
+         break;
+      case GL_LINEAR:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_NONE;
+         break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_NEAREST;
+         break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_NEAREST;
+         break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_LINEAR;
+         break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_LINEAR;
+         break;
+      default:
+         return GL_FALSE;
       }
-   }
 
+      if (tObj->MaxAnisotropy > 1.0) {
+         minFilt = FILTER_ANISOTROPIC;
+         magFilt = FILTER_ANISOTROPIC;
+      }
+      else {
+         switch (tObj->MagFilter) {
+         case GL_NEAREST:
+            magFilt = FILTER_NEAREST;
+            break;
+         case GL_LINEAR:
+            magFilt = FILTER_LINEAR;
+            break;
+         default:
+            return GL_FALSE;
+         }
+      }
 
-   return GL_TRUE;
-}
+      lodbias = (int) ((tUnit->LodBias + tObj->LodBias) * 16.0);
+      if (lodbias < -64)
+          lodbias = -64;
+      if (lodbias > 63)
+          lodbias = 63;
+      
+      state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) & 
+                                  TM0S3_LOD_BIAS_MASK);
+#if 0
+      /* YUV conversion:
+       */
+      if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
+          firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
+         state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
+#endif
+
+      state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel -
+                                    intelObj->firstLevel) *
+                                   4) << TM0S3_MIN_MIP_SHIFT;
+
+      state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
+                                   (mipFilt << TM0S3_MIP_FILTER_SHIFT) |
+                                   (magFilt << TM0S3_MAG_FILTER_SHIFT));
+   }
 
+   {
+      GLenum ws = tObj->WrapS;
+      GLenum wt = tObj->WrapT;
 
-static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
-{
-   i830ContextPtr i830 = I830_CONTEXT(ctx);
 
-   /* This is happening too often.  I need to conditionally send diffuse
-    * state to the card.  Perhaps a diffuse dirty flag of some kind.
-    * Will need to change this logic if more than 2 texture units are
-    * used.  We need to only do this up to the last unit enabled, or unit
-    * one if nothing is enabled.
-    */
-
-   if ( i830->intel.CurrentTexObj[unit] != NULL ) {
-      /* The old texture is no longer bound to this texture unit.
-       * Mark it as such.
+      /* 3D textures not available on i830
        */
-
-      i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
-      i830->intel.CurrentTexObj[unit] = NULL;
+      if (tObj->Target == GL_TEXTURE_3D)
+         return GL_FALSE;
+
+      state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
+                                MAP_UNIT(unit) |
+                                ENABLE_TEXCOORD_PARAMS |
+                                ss3 |
+                                ENABLE_ADDR_V_CNTL |
+                                TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt))
+                                | ENABLE_ADDR_U_CNTL |
+                                TEXCOORD_ADDR_U_MODE(translate_wrap_mode
+                                                     (ws)));
    }
 
-   return GL_TRUE;
-}
+   /* convert border color from float to ubyte */
+   CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor[0]);
+   CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor[1]);
+   CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor[2]);
+   CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor[3]);
 
-static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
-{
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(border[0],
+                                                  border[1],
+                                                  border[2],
+                                                  border[3]);
 
-   if (texUnit->_ReallyEnabled &&
-       INTEL_CONTEXT(ctx)->intelScreen->textureSize < 2048 * 1024)
-      return GL_FALSE;
 
-   switch(texUnit->_ReallyEnabled) {
-   case TEXTURE_1D_BIT:
-   case TEXTURE_2D_BIT:
-      return (enable_tex_common( ctx, unit ) &&
-             enable_tex_2d( ctx, unit ));
-   case TEXTURE_RECT_BIT:
-      return (enable_tex_common( ctx, unit ) &&
-             enable_tex_rect( ctx, unit ));
-   case TEXTURE_CUBE_BIT:
-      return (enable_tex_common( ctx, unit ) &&
-             enable_tex_cube( ctx, unit ));
-   case 0:
-      return disable_tex( ctx, unit );
-   default:
-      return GL_FALSE;
-   }
+   I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
+   /* memcmp was already disabled, but definitely won't work as the
+    * region might now change and that wouldn't be detected:
+    */
+   I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
+   return GL_TRUE;
 }
 
 
-void i830UpdateTextureState( intelContextPtr intel )
-{
-   i830ContextPtr i830 = I830_CONTEXT(intel);
-   GLcontext *ctx = &intel->ctx;
-   GLboolean ok;
-
-   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
 
-   I830_ACTIVESTATE(i830, I830_UPLOAD_TEX_ALL, GL_FALSE);
 
-   ok = (i830UpdateTexUnit( ctx, 0 ) &&
-        i830UpdateTexUnit( ctx, 1 ) &&
-        i830UpdateTexUnit( ctx, 2 ) &&
-        i830UpdateTexUnit( ctx, 3 ));
+void
+i830UpdateTextureState(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   GLboolean ok = GL_TRUE;
+   GLuint i;
+
+   for (i = 0; i < I830_TEX_UNITS && ok; i++) {
+      switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
+      case TEXTURE_1D_BIT:
+      case TEXTURE_2D_BIT:
+      case TEXTURE_CUBE_BIT:
+         ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_NORMAL);
+         break;
+      case TEXTURE_RECT_BIT:
+         ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_IN_TEXELUNITS);
+         break;
+      case 0:{
+        struct i830_context *i830 = i830_context(&intel->ctx);
+         if (i830->state.active & I830_UPLOAD_TEX(i)) 
+            I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE);
+
+        if (i830->state.tex_buffer[i] != NULL) {
+           dri_bo_unreference(i830->state.tex_buffer[i]);
+           i830->state.tex_buffer[i] = NULL;
+        }
+         break;
+      }
+      case TEXTURE_3D_BIT:
+      default:
+         ok = GL_FALSE;
+         break;
+      }
+   }
 
-   FALLBACK( intel, I830_FALLBACK_TEXTURE, !ok );
+   FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok);
 
    if (ok)
-      i830EmitTextureBlend( i830 );
+      i830EmitTextureBlend(i830);
 }
-
-
-