mesa: replace gl_texture_format with gl_format
[mesa.git] / src / mesa / drivers / dri / unichrome / via_tex.c
index 8a2b6b1abc12aa0ec81c38c45398ac05e8bdd2ac..b6be06d1ee29f6a507b6c9ef5f71d7a3fdd06bd8 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 
-#include "glheader.h"
-#include "mtypes.h"
-#include "simple_list.h"
-#include "enums.h"
-#include "teximage.h"
-#include "texobj.h"
-#include "texstore.h"
-#include "texformat.h"
-#include "swrast/swrast.h"
-#include "context.h"
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/enums.h"
+#include "main/formats.h"
+#include "main/colortab.h"
+#include "main/convolve.h"
+#include "main/context.h"
+#include "main/mipmap.h"
+#include "main/simple_list.h"
+#include "main/texcompress.h"
+#include "main/texformat.h"
+#include "main/texobj.h"
+#include "main/texstore.h"
+
+#include "main/mm.h"
 #include "via_context.h"
+#include "via_fb.h"
 #include "via_tex.h"
 #include "via_state.h"
 #include "via_ioctl.h"
+#include "via_3d_reg.h"
 
+static gl_format
+viaChooseTexFormat( GLcontext *ctx, GLint internalFormat,
+                   GLenum format, GLenum type )
+{
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   const GLboolean do32bpt = ( vmesa->viaScreen->bitsPerPixel == 32
+/*                            && vmesa->viaScreen->textureSize > 4*1024*1024 */
+      );
+
+
+   switch ( internalFormat ) {
+   case 4:
+   case GL_RGBA:
+   case GL_COMPRESSED_RGBA:
+      if ( format == GL_BGRA ) {
+        if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ||
+             type == GL_UNSIGNED_BYTE ) {
+           return MESA_FORMAT_ARGB8888;
+        }
+         else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
+            return MESA_FORMAT_ARGB4444;
+        }
+         else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
+           return MESA_FORMAT_ARGB1555;
+        }
+      }
+      else if ( type == GL_UNSIGNED_BYTE ||
+               type == GL_UNSIGNED_INT_8_8_8_8_REV ||
+               type == GL_UNSIGNED_INT_8_8_8_8 ) {
+        return MESA_FORMAT_ARGB8888;
+      }
+      return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
+
+   case 3:
+   case GL_RGB:
+   case GL_COMPRESSED_RGB:
+      if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
+        return MESA_FORMAT_RGB565;
+      }
+      else if ( type == GL_UNSIGNED_BYTE ) {
+        return MESA_FORMAT_ARGB8888;
+      }
+      return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
+
+   case GL_RGBA8:
+   case GL_RGB10_A2:
+   case GL_RGBA12:
+   case GL_RGBA16:
+      return MESA_FORMAT_ARGB8888;
+
+   case GL_RGBA4:
+   case GL_RGBA2:
+      return MESA_FORMAT_ARGB4444;
+
+   case GL_RGB5_A1:
+      return MESA_FORMAT_ARGB1555;
+
+   case GL_RGB8:
+   case GL_RGB10:
+   case GL_RGB12:
+   case GL_RGB16:
+      return MESA_FORMAT_ARGB8888;
+
+   case GL_RGB5:
+   case GL_RGB4:
+   case GL_R3_G3_B2:
+      return MESA_FORMAT_RGB565;
+
+   case GL_ALPHA:
+   case GL_ALPHA4:
+   case GL_ALPHA8:
+   case GL_ALPHA12:
+   case GL_ALPHA16:
+   case GL_COMPRESSED_ALPHA:
+      return MESA_FORMAT_A8;
+
+   case 1:
+   case GL_LUMINANCE:
+   case GL_LUMINANCE4:
+   case GL_LUMINANCE8:
+   case GL_LUMINANCE12:
+   case GL_LUMINANCE16:
+   case GL_COMPRESSED_LUMINANCE:
+      return MESA_FORMAT_L8;
+
+   case 2:
+   case GL_LUMINANCE_ALPHA:
+   case GL_LUMINANCE4_ALPHA4:
+   case GL_LUMINANCE6_ALPHA2:
+   case GL_LUMINANCE8_ALPHA8:
+   case GL_LUMINANCE12_ALPHA4:
+   case GL_LUMINANCE12_ALPHA12:
+   case GL_LUMINANCE16_ALPHA16:
+   case GL_COMPRESSED_LUMINANCE_ALPHA:
+      return MESA_FORMAT_AL88;
+
+   case GL_INTENSITY:
+   case GL_INTENSITY4:
+   case GL_INTENSITY8:
+   case GL_INTENSITY12:
+   case GL_INTENSITY16:
+   case GL_COMPRESSED_INTENSITY:
+      return MESA_FORMAT_I8;
+
+   case GL_YCBCR_MESA:
+      if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
+         type == GL_UNSIGNED_BYTE)
+         return MESA_FORMAT_YCBCR;
+      else
+         return MESA_FORMAT_YCBCR_REV;
+
+   case GL_COMPRESSED_RGB_FXT1_3DFX:
+      return MESA_FORMAT_RGB_FXT1;
+   case GL_COMPRESSED_RGBA_FXT1_3DFX:
+      return MESA_FORMAT_RGBA_FXT1;
+
+   case GL_RGB_S3TC:
+   case GL_RGB4_S3TC:
+   case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+      return MESA_FORMAT_RGB_DXT1;
+
+   case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+      return MESA_FORMAT_RGBA_DXT1;
+
+   case GL_RGBA_S3TC:
+   case GL_RGBA4_S3TC:
+   case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+      return MESA_FORMAT_RGBA_DXT3;
+
+   case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+      return MESA_FORMAT_RGBA_DXT5;
+
+   case GL_COLOR_INDEX:        
+   case GL_COLOR_INDEX1_EXT:   
+   case GL_COLOR_INDEX2_EXT:   
+   case GL_COLOR_INDEX4_EXT:   
+   case GL_COLOR_INDEX8_EXT:   
+   case GL_COLOR_INDEX12_EXT:      
+   case GL_COLOR_INDEX16_EXT:
+      return MESA_FORMAT_CI8;
+
+   default:
+      fprintf(stderr, "unexpected texture format %s in %s\n", 
+             _mesa_lookup_enum_by_nr(internalFormat),
+             __FUNCTION__);
+      return MESA_FORMAT_NONE;
+   }
+
+   return MESA_FORMAT_NONE; /* never get here */
+}
 
-/*
- * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
- */
-/* 
-static GLuint viaComputeLodBias(GLfloat bias)
+static int logbase2(int n)
 {
-    int b = (int)(bias * 16.0) + 12;
-    if (b > 63)
-        b = 63;
-    else if (b < -64)
-        b = -64;
-    return (GLuint)(b & MLC_LOD_BIAS_MASK);
+   GLint i = 1;
+   GLint log2 = 0;
+
+   while (n > i) {
+      i *= 2;
+      log2++;
+   }
+
+   return log2;
 }
-*/
 
-viaTextureObjectPtr viaAllocTextureObject(struct gl_texture_object *texObj)
+static const char *get_memtype_name( GLint memType )
 {
-    viaTextureObjectPtr t;
+   static const char *names[] = {
+      "VIA_MEM_VIDEO",
+      "VIA_MEM_AGP",
+      "VIA_MEM_SYSTEM",
+      "VIA_MEM_MIXED",
+      "VIA_MEM_UNKNOWN"
+   };
+
+   return names[memType];
+}
+
+
+static GLboolean viaMoveTexBuffers( struct via_context *vmesa,
+                                   struct via_tex_buffer **buffers,
+                                   GLuint nr,
+                                   GLint newMemType )
+{
+   struct via_tex_buffer *newTexBuf[VIA_MAX_TEXLEVELS];
+   GLint i;
+
+   if (VIA_DEBUG & DEBUG_TEXTURE)
+      fprintf(stderr, "%s to %s\n",
+             __FUNCTION__,
+             get_memtype_name(newMemType));
+
+   memset(newTexBuf, 0, sizeof(newTexBuf));
+
+   /* First do all the allocations (or fail):
+    */ 
+   for (i = 0; i < nr; i++) {    
+      if (buffers[i]->memType != newMemType) {  
+
+        /* Don't allow uploads in a thrash state.  Should try and
+         * catch this earlier.
+         */
+        if (vmesa->thrashing && newMemType != VIA_MEM_SYSTEM)
+           goto cleanup;
+
+        newTexBuf[i] = via_alloc_texture(vmesa, 
+                                         buffers[i]->size,
+                                         newMemType);
+        if (!newTexBuf[i]) 
+           goto cleanup;
+      }
+   }
+
+
+   /* Now copy all the image data and free the old texture memory.
+    */
+   for (i = 0; i < nr; i++) {    
+      if (newTexBuf[i]) {
+        memcpy(newTexBuf[i]->bufAddr,
+               buffers[i]->bufAddr, 
+               buffers[i]->size);
+
+        newTexBuf[i]->image = buffers[i]->image;
+        newTexBuf[i]->image->texMem = newTexBuf[i];
+        newTexBuf[i]->image->image.Data = newTexBuf[i]->bufAddr;
+        via_free_texture(vmesa, buffers[i]);
+      }
+   }
+
+   if (VIA_DEBUG & DEBUG_TEXTURE)
+      fprintf(stderr, "%s - success\n", __FUNCTION__);
+
+   return GL_TRUE;
+
+ cleanup:
+   /* Release any allocations made prior to failure:
+    */
+   if (VIA_DEBUG & DEBUG_TEXTURE)
+      fprintf(stderr, "%s - failed\n", __FUNCTION__);
+
+   for (i = 0; i < nr; i++) {    
+      if (newTexBuf[i]) {
+        via_free_texture(vmesa, newTexBuf[i]);
+      }
+   }
+   
+   return GL_FALSE;   
+}
+
+
+static GLboolean viaMoveTexObject( struct via_context *vmesa,
+                                  struct via_texture_object *viaObj,
+                                  GLint newMemType )
+{   
+   struct via_texture_image **viaImage = 
+      (struct via_texture_image **)&viaObj->obj.Image[0][0];
+   struct via_tex_buffer *buffers[VIA_MAX_TEXLEVELS];
+   GLuint i, nr = 0;
 
-    t = (viaTextureObjectPtr)CALLOC_STRUCT(via_texture_object_t);
-    if (!t)
-        return NULL;
+   for (i = viaObj->firstLevel; i <= viaObj->lastLevel; i++)
+      buffers[nr++] = viaImage[i]->texMem;
 
-    /* Initialize non-image-dependent parts of the state:
-     */
-    t->bufAddr = NULL;
-    t->dirtyImages = ~0;
-    t->actualLevel = 0;
-    t->globj = texObj;
-    make_empty_list(t);
+   if (viaMoveTexBuffers( vmesa, &buffers[0], nr, newMemType )) {
+      viaObj->memType = newMemType;
+      return GL_TRUE;
+   }
 
-    return t;
+   return GL_FALSE;
 }
 
-static void viaTexParameter(GLcontext *ctx, GLenum target,
-                            struct gl_texture_object *texObj,
-                            GLenum pname, const GLfloat *params)
+
+
+static GLboolean viaSwapInTexObject( struct via_context *vmesa,
+                                    struct via_texture_object *viaObj )
 {
-    viaTextureObjectPtr t = (viaTextureObjectPtr)texObj->DriverData;
-    if (!t)
-        return;
+   const struct via_texture_image *baseImage = 
+      (struct via_texture_image *)viaObj->obj.Image[0][viaObj->obj.BaseLevel]; 
+
+   if (VIA_DEBUG & DEBUG_TEXTURE)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (baseImage->texMem->memType != VIA_MEM_SYSTEM) 
+      return viaMoveTexObject( vmesa, viaObj, baseImage->texMem->memType );
 
-    if (target != GL_TEXTURE_2D)
-        return;
+   return (viaMoveTexObject( vmesa, viaObj, VIA_MEM_AGP ) ||
+          viaMoveTexObject( vmesa, viaObj, VIA_MEM_VIDEO ));
 }
 
-static void viaTexEnv(GLcontext *ctx, GLenum target,
-                      GLenum pname, const GLfloat *param)
+
+/* This seems crude, but it asks a fairly pertinent question and gives
+ * an accurate answer:
+ */
+static GLboolean viaIsTexMemLow( struct via_context *vmesa,
+                                GLuint heap )
 {
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
-    vmesa = vmesa;
-} 
-
-static void viaTexImage1D(GLcontext *ctx, GLenum target, GLint level,
-                          GLint internalFormat,
-                          GLint width, GLint border,
-                          GLenum format, GLenum type,
-                          const GLvoid *pixels,
-                          const struct gl_pixelstore_attrib *packing,
-                          struct gl_texture_object *texObj,
-                          struct gl_texture_image *texImage)
+   struct via_tex_buffer *buf =  via_alloc_texture(vmesa, 512 * 1024, heap );
+   if (!buf)
+      return GL_TRUE;
+   
+   via_free_texture(vmesa, buf);
+   return GL_FALSE;
+}
+
+
+/* Speculatively move texture images which haven't been used in a
+ * while back to system memory. 
+ * 
+ * TODO: only do this when texture memory is low.
+ * 
+ * TODO: use dma.
+ *
+ * TODO: keep the fb/agp version hanging around and use the local
+ * version as backing store, so re-upload might be avoided.
+ *
+ * TODO: do this properly in the kernel...
+ */
+GLboolean viaSwapOutWork( struct via_context *vmesa )
 {
-    viaTextureObjectPtr t = (viaTextureObjectPtr)texObj->DriverData;
-#ifdef DEBUG    
-    if (VIA_DEBUG) fprintf(stderr, "viaTexImage1D - in\n");
-#endif
-    if (t) {
-        if (level == 0) {
-           viaSwapOutTexObj(VIA_CONTEXT(ctx), t);
-           t->actualLevel = 0;
-       }
-       else
-           t->actualLevel++;
-    }
-    else {
-               t = viaAllocTextureObject(texObj);
-       if (!t) {
-               _mesa_error(ctx, GL_OUT_OF_MEMORY, "viaTexImage1D");
-            return;
-        }
-        texObj->DriverData = t;
-    }
-    _mesa_store_teximage1d(ctx, target, level, internalFormat,
-                           width, border, format, type,
-                           pixels, packing, texObj, texImage);
-#ifdef DEBUG                      
-    if (VIA_DEBUG) fprintf(stderr, "viaTexImage1D - out\n");
-#endif
+   struct via_tex_buffer *s, *tmp;
+   GLuint done = 0;
+   GLuint heap, target;
+
+   if (VIA_DEBUG & DEBUG_TEXTURE)
+      fprintf(stderr, "%s VID %d AGP %d SYS %d\n", __FUNCTION__,
+             vmesa->total_alloc[VIA_MEM_VIDEO],
+             vmesa->total_alloc[VIA_MEM_AGP],
+             vmesa->total_alloc[VIA_MEM_SYSTEM]);
+
+   
+   for (heap = VIA_MEM_VIDEO; heap <= VIA_MEM_AGP; heap++) {
+      GLuint nr = 0, sz = 0;
+
+      if (vmesa->thrashing) {
+        if (VIA_DEBUG & DEBUG_TEXTURE)
+           fprintf(stderr, "Heap %d: trash flag\n", heap);
+        target = 1*1024*1024;
+      }
+      else if (viaIsTexMemLow(vmesa, heap)) {
+        if (VIA_DEBUG & DEBUG_TEXTURE)
+           fprintf(stderr, "Heap %d: low memory\n", heap);
+        target = 64*1024;
+      }
+      else {
+        if (VIA_DEBUG & DEBUG_TEXTURE)
+           fprintf(stderr, "Heap %d: nothing to do\n", heap);
+        continue;
+      }
+
+      foreach_s( s, tmp, &vmesa->tex_image_list[heap] ) {
+        if (s->lastUsed < vmesa->lastSwap[1]) {
+           struct via_texture_object *viaObj = 
+              (struct via_texture_object *) s->image->image.TexObject;
+
+           if (VIA_DEBUG & DEBUG_TEXTURE)
+              fprintf(stderr, 
+                      "back copy tex sz %d, lastUsed %d lastSwap %d\n", 
+                      s->size, s->lastUsed, vmesa->lastSwap[1]);
+
+           if (viaMoveTexBuffers( vmesa, &s, 1, VIA_MEM_SYSTEM )) {
+              viaObj->memType = VIA_MEM_MIXED;
+              done += s->size;
+           }
+           else {
+              if (VIA_DEBUG & DEBUG_TEXTURE)
+                 fprintf(stderr, "Failed to back copy texture!\n");
+              sz += s->size;
+           }
+        }
+        else {
+           nr ++;
+           sz += s->size;
+        }
+
+        if (done > target) {
+           vmesa->thrashing = GL_FALSE; /* might not get set otherwise? */
+           return GL_TRUE;
+        }
+      }
+
+      assert(sz == vmesa->total_alloc[heap]);
+        
+      if (VIA_DEBUG & DEBUG_TEXTURE)
+        fprintf(stderr, "Heap %d: nr %d tot sz %d\n", heap, nr, sz);
+   }
+
+   
+   return done != 0;
 }
-static void viaTexSubImage1D(GLcontext *ctx,
-                             GLenum target,
-                             GLint level,
-                             GLint xoffset,
-                             GLsizei width,
-                             GLenum format, GLenum type,
-                             const GLvoid *pixels,
-                             const struct gl_pixelstore_attrib *packing,
-                             struct gl_texture_object *texObj,
-                             struct gl_texture_image *texImage)
 
+
+
+/* Basically, just collect the image dimensions and addresses for each
+ * image and update the texture object state accordingly.
+ */
+static GLboolean viaSetTexImages(GLcontext *ctx,
+                                struct gl_texture_object *texObj)
 {
-    viaTextureObjectPtr t = (viaTextureObjectPtr)texObj->DriverData;
-    
-    if (t) {
-        viaSwapOutTexObj(VIA_CONTEXT(ctx), t);
-    }
-    _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
-                             format, type, pixels, packing, texObj,
-                              texImage);
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   struct via_texture_object *viaObj = (struct via_texture_object *)texObj;
+   const struct via_texture_image *baseImage = 
+      (struct via_texture_image *)texObj->Image[0][texObj->BaseLevel];
+   GLint firstLevel, lastLevel, numLevels;
+   GLuint texFormat;
+   GLint w, h, p;
+   GLint i, j = 0, k = 0, l = 0, m = 0;
+   GLuint texBase;
+   GLuint basH = 0;
+   GLuint widthExp = 0;
+   GLuint heightExp = 0;    
+
+   switch (baseImage->image.TexFormat) {
+   case MESA_FORMAT_ARGB8888:
+      texFormat = HC_HTXnFM_ARGB8888;
+      break;
+   case MESA_FORMAT_ARGB4444:
+      texFormat = HC_HTXnFM_ARGB4444; 
+      break;
+   case MESA_FORMAT_RGB565:
+      texFormat = HC_HTXnFM_RGB565;   
+      break;
+   case MESA_FORMAT_ARGB1555:
+      texFormat = HC_HTXnFM_ARGB1555;   
+      break;
+   case MESA_FORMAT_RGB888:
+      texFormat = HC_HTXnFM_ARGB0888;
+      break;
+   case MESA_FORMAT_L8:
+      texFormat = HC_HTXnFM_L8;       
+      break;
+   case MESA_FORMAT_I8:
+      texFormat = HC_HTXnFM_T8;       
+      break;
+   case MESA_FORMAT_CI8:
+      texFormat = HC_HTXnFM_Index8;   
+      break;
+   case MESA_FORMAT_AL88:
+      texFormat = HC_HTXnFM_AL88;     
+      break;
+   case MESA_FORMAT_A8:
+      texFormat = HC_HTXnFM_A8;     
+      break;
+   default:
+      _mesa_problem(vmesa->glCtx, "Bad texture format in viaSetTexImages");
+      return GL_FALSE;
+   }
+
+   /* 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.
+    */
+   if (texObj->MinFilter == GL_LINEAR || texObj->MinFilter == GL_NEAREST) {
+      firstLevel = lastLevel = texObj->BaseLevel;
+   }
+   else {
+      firstLevel = texObj->BaseLevel + (GLint)(texObj->MinLod + 0.5);
+      firstLevel = MAX2(firstLevel, texObj->BaseLevel);
+      lastLevel = texObj->BaseLevel + (GLint)(texObj->MaxLod + 0.5);
+      lastLevel = MAX2(lastLevel, texObj->BaseLevel);
+      lastLevel = MIN2(lastLevel, texObj->BaseLevel + baseImage->image.MaxLog2);
+      lastLevel = MIN2(lastLevel, texObj->MaxLevel);
+      lastLevel = MAX2(firstLevel, lastLevel);     /* need at least one level */
+   }
+
+   numLevels = lastLevel - firstLevel + 1;
+
+   /* The hardware supports only 10 mipmap levels; ignore higher levels.
+    */
+   if ((numLevels > 10) && (ctx->Const.MaxTextureLevels > 10)) {
+       lastLevel -= numLevels - 10;
+       numLevels = 10;
+   }
+
+   /* save these values, check if they effect the residency of the
+    * texture:
+    */
+   if (viaObj->firstLevel != firstLevel ||
+       viaObj->lastLevel != lastLevel) {
+      viaObj->firstLevel = firstLevel;
+      viaObj->lastLevel = lastLevel;
+      viaObj->memType = VIA_MEM_MIXED;
+   }
+
+   if (VIA_DEBUG & DEBUG_TEXTURE & 0)
+      fprintf(stderr, "%s, current memType: %s\n",
+             __FUNCTION__,
+             get_memtype_name(viaObj->memType));
+
+   
+   if (viaObj->memType == VIA_MEM_MIXED ||
+       viaObj->memType == VIA_MEM_SYSTEM) {
+      if (!viaSwapInTexObject(vmesa, viaObj)) {
+        if (VIA_DEBUG & DEBUG_TEXTURE) 
+           if (!vmesa->thrashing)
+              fprintf(stderr, "Thrashing flag set for frame %d\n", 
+                      vmesa->swap_count);
+        vmesa->thrashing = GL_TRUE;
+        return GL_FALSE;
+      }
+   }
+
+   if (viaObj->memType == VIA_MEM_AGP)
+      viaObj->regTexFM = (HC_SubA_HTXnFM << 24) | HC_HTXnLoc_AGP | texFormat;
+   else
+      viaObj->regTexFM = (HC_SubA_HTXnFM << 24) | HC_HTXnLoc_Local | texFormat;
+
+
+   for (i = 0; i < numLevels; i++) {    
+      struct via_texture_image *viaImage = 
+        (struct via_texture_image *)texObj->Image[0][firstLevel + i];
+
+      w = viaImage->image.WidthLog2;
+      h = viaImage->image.HeightLog2;
+      p = viaImage->pitchLog2;
+
+      assert(viaImage->texMem->memType == viaObj->memType);
+
+      texBase = viaImage->texMem->texBase;
+      if (!texBase) {
+        if (VIA_DEBUG & DEBUG_TEXTURE)
+           fprintf(stderr, "%s: no texBase[%d]\n", __FUNCTION__, i); 
+        return GL_FALSE;
+      }
+
+      /* Image has to remain resident until the coming fence is retired.
+       */
+      move_to_head( &vmesa->tex_image_list[viaImage->texMem->memType],
+                   viaImage->texMem );
+      viaImage->texMem->lastUsed = vmesa->lastBreadcrumbWrite;
+
+
+      viaObj->regTexBaseAndPitch[i].baseL = 
+        ((HC_SubA_HTXnL0BasL + i) << 24) | (texBase & 0xFFFFFF);
+
+      viaObj->regTexBaseAndPitch[i].pitchLog2 = 
+        ((HC_SubA_HTXnL0Pit + i) << 24) | (p << 20);
+                                             
+                                             
+      /* The base high bytes for each 3 levels are packed
+       * together into one register:
+       */
+      j = i / 3;
+      k = 3 - (i % 3);
+      basH |= ((texBase & 0xFF000000) >> (k << 3));
+      if (k == 1) {
+        viaObj->regTexBaseH[j] = ((j + HC_SubA_HTXnL012BasH) << 24) | basH;
+        basH = 0;
+      }
+            
+      /* Likewise, sets of 6 log2width and log2height values are
+       * packed into individual registers:
+       */
+      l = i / 6;
+      m = i % 6;
+      widthExp |= (((GLuint)w & 0xF) << (m << 2));
+      heightExp |= (((GLuint)h & 0xF) << (m << 2));
+      if (m == 5) {
+        viaObj->regTexWidthLog2[l] = 
+           (l + HC_SubA_HTXnL0_5WE) << 24 | widthExp;
+        viaObj->regTexHeightLog2[l] = 
+           (l + HC_SubA_HTXnL0_5HE) << 24 | heightExp;
+        widthExp = 0;
+        heightExp = 0;
+      }
+      if (w) w--;
+      if (h) h--;
+      if (p) p--;                                           
+   }
+        
+   if (k != 1) {
+      viaObj->regTexBaseH[j] = ((j + HC_SubA_HTXnL012BasH) << 24) | basH;      
+   }
+   if (m != 5) {
+      viaObj->regTexWidthLog2[l] = (l + HC_SubA_HTXnL0_5WE) << 24 | widthExp;
+      viaObj->regTexHeightLog2[l] = (l + HC_SubA_HTXnL0_5HE) << 24 | heightExp;
+   }
+
+   return GL_TRUE;
+}
+
 
+GLboolean viaUpdateTextureState( GLcontext *ctx )
+{
+   struct gl_texture_unit *texUnit = ctx->Texture.Unit;
+   GLuint i;
+
+   for (i = 0; i < 2; i++) {   
+      if (texUnit[i]._ReallyEnabled == TEXTURE_2D_BIT || 
+         texUnit[i]._ReallyEnabled == TEXTURE_1D_BIT) {
+
+        if (!viaSetTexImages(ctx, texUnit[i]._Current)) 
+           return GL_FALSE;
+      }
+      else if (texUnit[i]._ReallyEnabled) {
+        return GL_FALSE;
+      } 
+   }
+   
+   return GL_TRUE;
 }
 
 
-static void viaTexImage2D(GLcontext *ctx, GLenum target, GLint level,
-                          GLint internalFormat,
-                          GLint width, GLint height, GLint border,
-                          GLenum format, GLenum type, const GLvoid *pixels,
-                          const struct gl_pixelstore_attrib *packing,
-                          struct gl_texture_object *texObj,
-                          struct gl_texture_image *texImage)
+
+
+
+                                
+
+
+static void viaTexImage(GLcontext *ctx, 
+                       GLint dims,
+                       GLenum target, GLint level,
+                       GLint internalFormat,
+                       GLint width, GLint height, GLint border,
+                       GLenum format, GLenum type, const void *pixels,
+                       const struct gl_pixelstore_attrib *packing,
+                       struct gl_texture_object *texObj,
+                       struct gl_texture_image *texImage)
 {
-    viaTextureObjectPtr t = (viaTextureObjectPtr)texObj->DriverData;
-#ifdef DEBUG    
-    if (VIA_DEBUG) fprintf(stderr, "viaTexImage2D - in\n");
-#endif    
-    if (t) {
-        if (level == 0) {
-           viaSwapOutTexObj(VIA_CONTEXT(ctx), t);
-           t->actualLevel = 0;
-       }
-       else
-           t->actualLevel++;
-    }
-    else {
-               t = viaAllocTextureObject(texObj);
-       if (!t) {
-               _mesa_error(ctx, GL_OUT_OF_MEMORY, "viaTexImage2D");
-            return;
-        }
-        texObj->DriverData = t;
-    }
-    _mesa_store_teximage2d(ctx, target, level, internalFormat,
-                           width, height, border, format, type,
-                           pixels, packing, texObj, texImage);
-#ifdef DEBUG                      
-    if (VIA_DEBUG) fprintf(stderr, "viaTexImage2D - out\n");
-#endif
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   GLint postConvWidth = width;
+   GLint postConvHeight = height;
+   GLint texelBytes, sizeInBytes;
+   struct via_texture_object *viaObj = (struct via_texture_object *)texObj;
+   struct via_texture_image *viaImage = (struct via_texture_image *)texImage;
+   int heaps[3], nheaps, i;
+
+   if (!is_empty_list(&vmesa->freed_tex_buffers)) {
+      viaCheckBreadcrumb(vmesa, 0);
+      via_release_pending_textures(vmesa);
+   }
+
+   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+      _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
+                                         &postConvHeight);
+   }
+
+   /* choose the texture format */
+   texImage->TexFormat = viaChooseTexFormat(ctx, internalFormat, 
+                                           format, type);
+
+   assert(texImage->TexFormat);
+
+   _mesa_set_fetch_functions(texImage, dims);
+
+   texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
+
+   if (texelBytes == 0) {
+      /* compressed format */
+      texImage->IsCompressed = GL_TRUE;
+      texImage->CompressedSize =
+         ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
+                                           texImage->Height, texImage->Depth,
+                                           texImage->TexFormat);
+   }
+
+   /* Minimum pitch of 32 bytes */
+   if (postConvWidth * texelBytes < 32) {
+      postConvWidth = 32 / texelBytes;
+      texImage->RowStride = postConvWidth;
+   }
+
+   assert(texImage->RowStride == postConvWidth);
+   viaImage->pitchLog2 = logbase2(postConvWidth * texelBytes);
+
+   /* allocate memory */
+   if (texImage->IsCompressed)
+      sizeInBytes = texImage->CompressedSize;
+   else
+      sizeInBytes = postConvWidth * postConvHeight * texelBytes;
+
+
+   /* Attempt to allocate texture memory directly, otherwise use main
+    * memory and this texture will always be a fallback.   FIXME!
+    *
+    * TODO: make room in agp if this fails.
+    * TODO: use fb ram for textures as well.
+    */
+   
+      
+   switch (viaObj->memType) {
+   case VIA_MEM_UNKNOWN:
+      heaps[0] = VIA_MEM_AGP;
+      heaps[1] = VIA_MEM_VIDEO;
+      heaps[2] = VIA_MEM_SYSTEM;
+      nheaps = 3;
+      break;
+   case VIA_MEM_AGP:
+   case VIA_MEM_VIDEO:
+      heaps[0] = viaObj->memType;
+      heaps[1] = VIA_MEM_SYSTEM;
+      nheaps = 2;
+      break;
+   case VIA_MEM_MIXED:
+   case VIA_MEM_SYSTEM:
+   default:
+      heaps[0] = VIA_MEM_SYSTEM;
+      nheaps = 1;
+      break;
+   }
+       
+   for (i = 0; i < nheaps && !viaImage->texMem; i++) {
+      if (VIA_DEBUG & DEBUG_TEXTURE) 
+        fprintf(stderr, "try %s (obj %s)\n", get_memtype_name(heaps[i]),
+                get_memtype_name(viaObj->memType));
+      viaImage->texMem = via_alloc_texture(vmesa, sizeInBytes, heaps[i]);
+   }
+
+   if (!viaImage->texMem) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+      return;
+   }
+
+   if (VIA_DEBUG & DEBUG_TEXTURE)
+      fprintf(stderr, "upload %d bytes to %s\n", sizeInBytes, 
+             get_memtype_name(viaImage->texMem->memType));
+
+   viaImage->texMem->image = viaImage;
+   texImage->Data = viaImage->texMem->bufAddr;
+
+   if (viaObj->memType == VIA_MEM_UNKNOWN)
+      viaObj->memType = viaImage->texMem->memType;
+   else if (viaObj->memType != viaImage->texMem->memType)
+      viaObj->memType = VIA_MEM_MIXED;
+
+   if (VIA_DEBUG & DEBUG_TEXTURE)
+      fprintf(stderr, "%s, obj %s, image : %s\n",
+             __FUNCTION__,           
+             get_memtype_name(viaObj->memType),
+             get_memtype_name(viaImage->texMem->memType));
+
+   vmesa->clearTexCache = 1;
+
+   pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, 
+                                       format, type,
+                                       pixels, packing, "glTexImage");
+   if (!pixels) {
+      /* Note: we check for a NULL image pointer here, _after_ we allocated
+       * memory for the texture.  That's what the GL spec calls for.
+       */
+      return;
+   }
+   else {
+      GLint dstRowStride;
+      GLboolean success;
+
+      if (texImage->IsCompressed) {
+         dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat, width);
+      }
+      else {
+         dstRowStride = postConvWidth * _mesa_get_format_bytes(texImage->TexFormat);
+      }
+      success = _mesa_texstore(ctx, dims,
+                               texImage->_BaseFormat,
+                               texImage->TexFormat,
+                               texImage->Data,
+                               0, 0, 0,  /* dstX/Y/Zoffset */
+                               dstRowStride,
+                               texImage->ImageOffsets,
+                               width, height, 1,
+                               format, type, pixels, packing);
+      if (!success) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+      }
+   }
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
+}
+
+static void viaTexImage2D(GLcontext *ctx, 
+                         GLenum target, GLint level,
+                         GLint internalFormat,
+                         GLint width, GLint height, GLint border,
+                         GLenum format, GLenum type, const void *pixels,
+                         const struct gl_pixelstore_attrib *packing,
+                         struct gl_texture_object *texObj,
+                         struct gl_texture_image *texImage)
+{
+   viaTexImage( ctx, 2, target, level, 
+               internalFormat, width, height, border,
+               format, type, pixels,
+               packing, texObj, texImage );
 }
 
 static void viaTexSubImage2D(GLcontext *ctx,
@@ -202,233 +842,135 @@ static void viaTexSubImage2D(GLcontext *ctx,
                              struct gl_texture_object *texObj,
                              struct gl_texture_image *texImage)
 {
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
-    
-    viaTextureObjectPtr t = (viaTextureObjectPtr)texObj->DriverData;
-    
-    if (t) {
-        viaSwapOutTexObj(VIA_CONTEXT(ctx), t);
-    }
-    _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
-                              height, format, type, pixels, packing, texObj,
-                              texImage);
-
-    if(vmesa->shareCtx)
-       vmesa->shareCtx->NewState |= _NEW_TEXTURE;
-
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+  
+   viaWaitIdle(vmesa, GL_TRUE);
+   vmesa->clearTexCache = 1;
+
+   _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+                            height, format, type, pixels, packing, texObj,
+                            texImage);
 }
 
-static void viaBindTexture(GLcontext *ctx, GLenum target,
-                           struct gl_texture_object *texObj)
+static void viaTexImage1D(GLcontext *ctx, 
+                         GLenum target, GLint level,
+                         GLint internalFormat,
+                         GLint width, GLint border,
+                         GLenum format, GLenum type, const void *pixels,
+                         const struct gl_pixelstore_attrib *packing,
+                         struct gl_texture_object *texObj,
+                         struct gl_texture_image *texImage)
 {
-#ifdef DEBUG    
-    if (VIA_DEBUG) fprintf(stderr, "viaBindTexture - in\n");
-#endif
-    if (target == GL_TEXTURE_2D) {
-        viaTextureObjectPtr t = (viaTextureObjectPtr)texObj->DriverData;
-
-        if (!t) {
-
-            t = viaAllocTextureObject(texObj);
-           if (!t) {
-                   _mesa_error(ctx, GL_OUT_OF_MEMORY, "viaBindTexture");
-                return;
-            }
-            texObj->DriverData = t;
-        }
-    }
-#ifdef DEBUG    
-    if (VIA_DEBUG) fprintf(stderr, "viaBindTexture - out\n");
-#endif
+   viaTexImage( ctx, 1, target, level, 
+               internalFormat, width, 1, border,
+               format, type, pixels,
+               packing, texObj, texImage );
 }
 
-static void viaDeleteTexture(GLcontext *ctx, struct gl_texture_object *texObj)
+static void viaTexSubImage1D(GLcontext *ctx,
+                             GLenum target,
+                             GLint level,
+                             GLint xoffset,
+                             GLsizei width,
+                             GLenum format, GLenum type,
+                             const GLvoid *pixels,
+                             const struct gl_pixelstore_attrib *packing,
+                             struct gl_texture_object *texObj,
+                             struct gl_texture_image *texImage)
 {
-    viaTextureObjectPtr t = (viaTextureObjectPtr)texObj->DriverData;
-#ifdef DEBUG    
-    if (VIA_DEBUG) fprintf(stderr, "viaDeleteTexture - in\n");    
-#endif
-    if (t) {
-        viaContextPtr vmesa = VIA_CONTEXT(ctx);
-        if (vmesa) {
-           /*=* John Sheng [2003.7.18] viewperf frames/sec *=*/
-           /*VIA_FIREVERTICES(vmesa);*/
-           if (vmesa->dma[0].map) { /* imply vmesa is not under destroying */
-               VIA_FIREVERTICES(vmesa);
-           }
-           viaDestroyTexObj(vmesa, t);
-       }
-        texObj->DriverData = 0;
-    }
-#ifdef DEBUG    
-    if (VIA_DEBUG) fprintf(stderr, "viaDeleteTexture - out\n");    
-#endif
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
 
-   /* Free mipmap images and the texture object itself */
-   _mesa_delete_texture_object(ctx, texObj);
+   viaWaitIdle(vmesa, GL_TRUE); 
+   vmesa->clearTexCache = 1;
+
+   _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
+                            format, type, pixels, packing, texObj,
+                            texImage);
 }
 
+
+
 static GLboolean viaIsTextureResident(GLcontext *ctx,
                                       struct gl_texture_object *texObj)
 {
-    viaTextureObjectPtr t = (viaTextureObjectPtr)texObj->DriverData;
+   struct via_texture_object *viaObj = 
+      (struct via_texture_object *)texObj;
 
-    return t && t->bufAddr;
+   return (viaObj->memType == VIA_MEM_AGP ||
+          viaObj->memType == VIA_MEM_VIDEO);
 }
 
-static const struct gl_texture_format *
-viaChooseTexFormat(GLcontext *ctx, GLint internalFormat,
-                  GLenum format, GLenum type)
+
+
+static struct gl_texture_image *viaNewTextureImage( GLcontext *ctx )
 {
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
-    (void)format;
-    (void)type;
-#ifdef DEBUG    
-    if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);    
-    if (VIA_DEBUG) fprintf(stderr, "internalFormat:%d format:%d\n", internalFormat, format);    
-#endif    
-    switch (internalFormat) {
-    case 1:
-    case GL_LUMINANCE:
-    case GL_LUMINANCE4:    
-    case GL_LUMINANCE8:    
-    case GL_LUMINANCE12:    
-    case GL_LUMINANCE16:    
-        return &_mesa_texformat_l8;
-    case 2:
-    case GL_LUMINANCE_ALPHA:    
-    case GL_LUMINANCE4_ALPHA4:        
-    case GL_LUMINANCE6_ALPHA2:    
-    case GL_LUMINANCE8_ALPHA8:    
-    case GL_LUMINANCE12_ALPHA4:    
-    case GL_LUMINANCE12_ALPHA12:
-    case GL_LUMINANCE16_ALPHA16:        
-        return &_mesa_texformat_al88;
-    case GL_R3_G3_B2:  
-    case GL_RGB4:    
-    case GL_RGB5:
-#ifdef DEBUG    
-       if (VIA_DEBUG) fprintf(stderr, "2 &_mesa_texformat_arg565\n");    
-#endif
-        return &_mesa_texformat_rgb565;    
-    case 3:
-    case GL_RGB:
-    case GL_RGB8:    
-    case GL_RGB10:
-    case GL_RGB12:    
-    case GL_RGB16:
-       if (vmesa->viaScreen->bitsPerPixel == 0x20) {
-#ifdef DEBUG    
-           if (VIA_DEBUG) fprintf(stderr,"3 argb8888\n");
-#endif
-           return &_mesa_texformat_argb8888;
-       }           
-       else {
-#ifdef DEBUG    
-           if (VIA_DEBUG) fprintf(stderr,"3 rgb565\n");        
-#endif
-            return &_mesa_texformat_rgb565;
-       }
-    case 4:
-       if (vmesa->viaScreen->bitsPerPixel == 0x20) {
-#ifdef DEBUG    
-           if (VIA_DEBUG) fprintf(stderr, "4 &_mesa_texformat_argb8888\n");
-#endif
-           return &_mesa_texformat_argb8888;
-       }
-       else {
-#ifdef DEBUG    
-           if (VIA_DEBUG) fprintf(stderr, "4 &_mesa_texformat_argb4444\n");
-#endif
-           return &_mesa_texformat_argb4444;               
-       }
-    case GL_RGBA2:    
-    case GL_RGBA4:         
-#ifdef DEBUG
-       if (VIA_DEBUG) fprintf(stderr, "GL_RGBA4 &_mesa_texformat_argb4444\n");    
-#endif
-        return &_mesa_texformat_argb4444;
+   (void) ctx;
+   return (struct gl_texture_image *)CALLOC_STRUCT(via_texture_image);
+}
 
-    case GL_RGB5_A1:
-#ifdef DEBUG
-       if (VIA_DEBUG) fprintf(stderr, "GL_RGB5_A1 &_mesa_texformat_argb1555\n");
-#endif
-        return &_mesa_texformat_argb1555;    
-    case GL_RGBA:
-    case GL_RGBA8:
-    case GL_RGBA12:
-    case GL_RGBA16:    
-    case GL_RGB10_A2:
-#ifdef DEBUG
-       if (VIA_DEBUG) fprintf(stderr, "GL_RGBA &_mesa_texformat_argb8888\n");
-#endif
-        return &_mesa_texformat_argb8888;
-    case GL_ALPHA:     
-    case GL_ALPHA4:            
-    case GL_ALPHA8:            
-    case GL_ALPHA12:
-    case GL_ALPHA16:    
-        return &_mesa_texformat_a8;    
-    case GL_INTENSITY:
-    case GL_INTENSITY4:        
-    case GL_INTENSITY8:        
-    case GL_INTENSITY12:
-    case GL_INTENSITY16:    
-        return &_mesa_texformat_i8;
-    case GL_COLOR_INDEX:       
-    case GL_COLOR_INDEX1_EXT:  
-    case GL_COLOR_INDEX2_EXT:  
-    case GL_COLOR_INDEX4_EXT:  
-    case GL_COLOR_INDEX8_EXT:  
-    case GL_COLOR_INDEX12_EXT:     
-    case GL_COLOR_INDEX16_EXT:
-        return &_mesa_texformat_ci8;    
-    default:
-        _mesa_problem(ctx, "unexpected format in viaChooseTextureFormat");
-        return NULL;
-    }  
-}                 
 
-void viaInitTextureFuncs(struct dd_function_table * functions)
+static struct gl_texture_object *viaNewTextureObject( GLcontext *ctx, 
+                                                     GLuint name, 
+                                                     GLenum target )
 {
-#ifdef DEBUG
-    if (VIA_DEBUG) fprintf(stderr, "viaInitTextureFuncs - in\n");
-#endif    
-    functions->TexEnv = viaTexEnv;
-    functions->ChooseTextureFormat = viaChooseTexFormat;
-    functions->TexImage1D = viaTexImage1D;
-    functions->TexImage2D = viaTexImage2D;
-    functions->TexImage3D = _mesa_store_teximage3d;
-    functions->TexSubImage1D = viaTexSubImage1D;
-    functions->TexSubImage2D = viaTexSubImage2D;
-    functions->TexSubImage3D = _mesa_store_texsubimage3d;
-    functions->CopyTexImage1D = _swrast_copy_teximage1d;
-    functions->CopyTexImage2D = _swrast_copy_teximage2d;
-    functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
-    functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
-    functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
-
-    functions->NewTextureObject = _mesa_new_texture_object;
-    functions->BindTexture = viaBindTexture;
-    functions->DeleteTexture = viaDeleteTexture;
-    functions->TexParameter = viaTexParameter;
-    functions->UpdateTexturePalette = 0;
-    functions->IsTextureResident = viaIsTextureResident;
-    functions->TestProxyTexImage = _mesa_test_proxy_teximage;
-
-#ifdef DEBUG
-    if (VIA_DEBUG) fprintf(stderr, "viaInitTextureFuncs - out\n");
-#endif
+   struct via_texture_object *obj = CALLOC_STRUCT(via_texture_object);
+
+   _mesa_initialize_texture_object(&obj->obj, name, target);
+   (void) ctx;
+
+   obj->memType = VIA_MEM_UNKNOWN;
+
+   return &obj->obj;
 }
 
-void viaInitTextures(GLcontext *ctx)
+
+static void viaFreeTextureImageData( GLcontext *ctx, 
+                                    struct gl_texture_image *texImage )
+{
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   struct via_texture_image *image = (struct via_texture_image *)texImage;
+
+   if (image->texMem) {
+      via_free_texture(vmesa, image->texMem);
+      image->texMem = NULL;
+   }
+   
+   texImage->Data = NULL;
+}
+
+
+
+
+void viaInitTextureFuncs(struct dd_function_table * functions)
 {
-    GLuint tmp = ctx->Texture.CurrentUnit;
-    ctx->Texture.CurrentUnit = 0;
-    viaBindTexture(ctx, GL_TEXTURE_1D, ctx->Texture.Unit[0].Current1D);
-    viaBindTexture(ctx, GL_TEXTURE_2D, ctx->Texture.Unit[0].Current2D);
-    ctx->Texture.CurrentUnit = 1;
-    viaBindTexture(ctx, GL_TEXTURE_1D, ctx->Texture.Unit[1].Current1D);
-    viaBindTexture(ctx, GL_TEXTURE_2D, ctx->Texture.Unit[1].Current2D);
-    ctx->Texture.CurrentUnit = tmp;
+   functions->ChooseTextureFormat = viaChooseTexFormat;
+   functions->TexImage1D = viaTexImage1D;
+   functions->TexImage2D = viaTexImage2D;
+   functions->TexSubImage1D = viaTexSubImage1D;
+   functions->TexSubImage2D = viaTexSubImage2D;
+
+   functions->NewTextureObject = viaNewTextureObject;
+   functions->NewTextureImage = viaNewTextureImage;
+   functions->DeleteTexture = _mesa_delete_texture_object;
+   functions->FreeTexImageData = viaFreeTextureImageData;
+
+#if 0 && defined( USE_SSE_ASM )
+   /*
+    * XXX this code is disabled for now because the via_sse_memcpy()
+    * routine causes segfaults with flightgear.
+    * See Mesa3d-dev mail list messages from 7/15/2005 for details.
+    * Note that this function is currently disabled in via_tris.c too.
+    */
+   if (getenv("VIA_NO_SSE"))
+      functions->TextureMemCpy = _mesa_memcpy;
+   else
+      functions->TextureMemCpy = via_sse_memcpy;
+#else
+   functions->TextureMemCpy = _mesa_memcpy;
+#endif
+
+   functions->UpdateTexturePalette = 0;
+   functions->IsTextureResident = viaIsTextureResident;
 }
+
+