patch to import Jon Smirl's work from Bitkeeper
[mesa.git] / src / mesa / drivers / dri / mga / mgatex.c
index b4ee787e0b8af9dad8eb7a56ae29e6a5255b46dc..82eccc81498f447b94056692c4397388a8f553fb 100644 (file)
  */
 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <GL/gl.h>
-
+#include "glheader.h"
 #include "mm.h"
 #include "mgacontext.h"
 #include "mgatex.h"
 #include "mgatris.h"
 #include "mgaioctl.h"
 
+#include "colormac.h"
+#include "context.h"
 #include "enums.h"
 #include "simple_list.h"
-/*#include "mem.h"*/
+#include "imports.h"
 #include "macros.h"
 #include "texformat.h"
 #include "texstore.h"
 
 #include "swrast/swrast.h"
 
-#define TEX_0 1
-#define TEX_1 2
-
-/*
- * mgaDestroyTexObj
- * Free all memory associated with a texture and NULL any pointers
- * to it.
+/**
+ * Set the texture wrap modes.
+ * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
+ * 
+ * \param t Texture object whose wrap modes are to be set
+ * \param swrap Wrap mode for the \a s texture coordinate
+ * \param twrap Wrap mode for the \a t texture coordinate
  */
-void
-mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t )
+
+static void 
+mgaSetTexWrapping( mgaTextureObjectPtr t, GLenum swrap, GLenum twrap )
 {
-   if ( !t ) return;
+   GLboolean  is_clamp = GL_FALSE;
+   GLboolean  is_clamp_to_edge = GL_FALSE;
 
-   /* free the texture memory */
-   if (t->MemBlock) {
-      mmFreeMem( t->MemBlock );
-      t->MemBlock = 0;
+   t->setup.texctl &= (TMC_clampu_MASK & TMC_clampv_MASK);
+   t->setup.texctl2 &= (TMC_borderen_MASK);
 
-      if (mmesa && t->age > mmesa->dirtyAge)
-        mmesa->dirtyAge = t->age;
+   switch( swrap ) {
+   case GL_REPEAT:
+      break;
+   case GL_CLAMP:
+      t->setup.texctl |= TMC_clampu_enable;
+      is_clamp = GL_TRUE;
+      break;
+   case GL_CLAMP_TO_EDGE:
+      t->setup.texctl |= TMC_clampu_enable;
+      is_clamp_to_edge = GL_TRUE;
+      break;
+   default:
+      _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
    }
 
-   /* free mesa's link */
-   if (t->tObj)
-      t->tObj->DriverData = NULL;
-
-   /* see if it was the driver's current object */
-   if (mmesa) {
-      if (t->bound & TEX_0) mmesa->CurrentTexObj[0] = 0;
-      if (t->bound & TEX_1) mmesa->CurrentTexObj[1] = 0;
+   switch( twrap ) {
+   case GL_REPEAT:
+      break;
+   case GL_CLAMP:
+      t->setup.texctl |= TMC_clampv_enable;
+      is_clamp = GL_TRUE;
+      break;
+   case GL_CLAMP_TO_EDGE:
+      t->setup.texctl |= TMC_clampv_enable;
+      is_clamp_to_edge = GL_TRUE;
+      break;
+   default:
+      _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
    }
-       
-   remove_from_list(t);
-   free( t );
-}
 
+   if ( is_clamp ) {
+      t->setup.texctl2 |= TMC_borderen_enable;
+   }
 
-/*
- * mgaSetTexWrappings
- */
-static void mgaSetTexWrapping( mgaTextureObjectPtr t,
-                              GLenum sWrap,
-                              GLenum tWrap )
-{
-   GLuint val = 0;
-
-   if (sWrap != GL_REPEAT)
-      val |= TMC_clampu_enable;
-
-   if (tWrap != GL_REPEAT)
-      val |= TMC_clampv_enable;
-
-   t->setup.texctl &= ~(TMC_clampu_enable|TMC_clampv_enable);
-   t->setup.texctl |= val;
+   t->border_fallback = (is_clamp && is_clamp_to_edge);
 }
 
 
-/*
- * mgaSetTexFilter
+/**
+ * Set the texture magnification and minification modes.
+ * 
+ * \param t Texture whose filter modes are to be set
+ * \param minf Texture minification mode
+ * \param magf Texture magnification mode
  */
-static void mgaSetTexFilter(mgaTextureObjectPtr t, GLenum minf, GLenum magf)
+
+static void
+mgaSetTexFilter( mgaTextureObjectPtr t, GLenum minf, GLenum magf )
 {
    GLuint val = 0;
 
@@ -136,123 +140,79 @@ static void mgaSetTexFilter(mgaTextureObjectPtr t, GLenum minf, GLenum magf)
    }
 
 
-   t->setup.texfilter &= (TF_minfilter_MASK |
-                         TF_magfilter_MASK |
+   /* Mask off the bits for the fields we are setting.  Remember, the MGA mask
+    * defines have 0s for the bits in the named fields.  This is the opposite
+    * of most of the other drivers.
+    */
+
+   t->setup.texfilter &= (TF_minfilter_MASK &
+                         TF_magfilter_MASK &
                          TF_fthres_MASK);
    t->setup.texfilter |= val;
 }
 
-/*
- * mgaSetTexBorderColor
- */
 static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4])
 {
-   t->setup.texbordercol = MGAPACKCOLOR8888(color[0],color[1],
-                                           color[2],color[3]);
+   t->setup.texbordercol = PACK_COLOR_8888(color[3], color[0], 
+                                          color[1], color[2] );
 }
 
 
-static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
-                                struct gl_texture_image *texImage,
-                                GLenum format, GLenum type )
+static const struct gl_texture_format *
+mgaChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+                       GLenum format, GLenum type )
 {
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
    const GLboolean do32bpt = mmesa->default32BitTextures;
-   const struct gl_texture_format *texFormat;
-   GLint ret;
-
-   if ( 0 )
-      fprintf( stderr, "internal=%s format=%s type=%s\n",
-              texImage->IntFormat == 3 ? "GL_RGB (3)" :
-              texImage->IntFormat == 4 ? "GL_RGBA (4)" :
-              _mesa_lookup_enum_by_nr( texImage->IntFormat ),
-              _mesa_lookup_enum_by_nr( format ),
-              _mesa_lookup_enum_by_nr( type ) );
-
-#define SET_FORMAT( r, gl )                                            \
-   do {                                                                        \
-      ret = (r);                                                       \
-      texFormat = &(gl);                                               \
-   } while (0)
-
-#define SET_FORMAT_32BPT( r32, gl32, r16, gl16 )                       \
-   do {                                                                        \
-      if ( do32bpt ) {                                                 \
-        ret = (r32);                                                   \
-        texFormat = &(gl32);                                           \
-      } else {                                                         \
-        ret = (r16);                                                   \
-        texFormat = &(gl16);                                           \
-      }                                                                        \
-   } while (0)
-
-   switch ( texImage->IntFormat ) {
-      /* GH: Bias towards GL_RGB, GL_RGBA texture formats.  This has
-       * got to be better than sticking them way down the end of this
-       * huge list.
-       */
+
+   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 ) {
-           SET_FORMAT( TMC_tformat_tw32, _mesa_texformat_argb8888 );
-           break;
-        } else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
-           SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-           break;
-        } else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
-           SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 );
-           break;
+           return &_mesa_texformat_argb8888;
+        }
+         else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
+            return &_mesa_texformat_argb4444;
+        }
+         else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
+           return &_mesa_texformat_argb1555;
         }
       }
-      SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
-                       TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
 
    case 3:
    case GL_RGB:
    case GL_COMPRESSED_RGB:
       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
-        SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
-        break;
+        return &_mesa_texformat_rgb565;
       }
-      SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
-                       TMC_tformat_tw16, _mesa_texformat_rgb565 );
-      break;
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
 
-      /* GH: Okay, keep checking as normal.  Still test for GL_RGB,
-       * GL_RGBA formats first.
-       */
    case GL_RGBA8:
    case GL_RGB10_A2:
    case GL_RGBA12:
    case GL_RGBA16:
-      SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
-                       TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
 
    case GL_RGBA4:
    case GL_RGBA2:
-      SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return &_mesa_texformat_argb4444;
 
    case GL_RGB5_A1:
-      SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 );
-      break;
+      return &_mesa_texformat_argb1555;
 
    case GL_RGB8:
    case GL_RGB10:
    case GL_RGB12:
    case GL_RGB16:
-      SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
-                       TMC_tformat_tw16, _mesa_texformat_rgb565 );
-      break;
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
 
    case GL_RGB5:
    case GL_RGB4:
    case GL_R3_G3_B2:
-      SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
-      break;
+      return &_mesa_texformat_rgb565;
 
    case GL_ALPHA:
    case GL_ALPHA4:
@@ -261,8 +221,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_ALPHA16:
    case GL_COMPRESSED_ALPHA:
       /* FIXME: This will report incorrect component sizes... */
-      SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return &_mesa_texformat_argb4444;
 
    case 1:
    case GL_LUMINANCE:
@@ -272,8 +231,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_LUMINANCE16:
    case GL_COMPRESSED_LUMINANCE:
       /* FIXME: This will report incorrect component sizes... */
-      SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
-      break;
+      return &_mesa_texformat_rgb565;
 
    case 2:
    case GL_LUMINANCE_ALPHA:
@@ -285,8 +243,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_LUMINANCE16_ALPHA16:
    case GL_COMPRESSED_LUMINANCE_ALPHA:
       /* FIXME: This will report incorrect component sizes... */
-      SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return &_mesa_texformat_argb4444;
 
    case GL_INTENSITY:
    case GL_INTENSITY4:
@@ -295,8 +252,15 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_INTENSITY16:
    case GL_COMPRESSED_INTENSITY:
       /* FIXME: This will report incorrect component sizes... */
-      SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return &_mesa_texformat_argb4444;
+
+   case GL_YCBCR_MESA:
+      if (MGA_IS_G400(mmesa) &&
+          (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+           type == GL_UNSIGNED_BYTE))
+         return &_mesa_texformat_ycbcr;
+      else
+         return &_mesa_texformat_ycbcr_rev;
 
    case GL_COLOR_INDEX:
    case GL_COLOR_INDEX1_EXT:
@@ -305,502 +269,78 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_COLOR_INDEX8_EXT:
    case GL_COLOR_INDEX12_EXT:
    case GL_COLOR_INDEX16_EXT:
-      SET_FORMAT( TMC_tformat_tw8, _mesa_texformat_ci8 );
-      break;
+      return &_mesa_texformat_ci8;
 
    default:
-      fprintf( stderr, "bad texture format in mgaChooseTexFormat() %d",
-              texImage->IntFormat );
-      return -1;
+      _mesa_problem( ctx, "unexpected texture format in %s", __FUNCTION__ );
+      return NULL;
    }
 
-   texImage->TexFormat = texFormat;
-
-   return ret;
+   return NULL; /* never get here */
 }
 
 
-/*
- * mgaCreateTexObj
+
+
+/**
  * Allocate space for and load the mesa images into the texture memory block.
  * This will happen before drawing with a new texture, or drawing with a
  * texture after it was swapped out or teximaged again.
  */
-static void mgaCreateTexObj(mgaContextPtr mmesa,
-                           struct gl_texture_object *tObj)
-{
-   const GLint baseLevel = tObj->BaseLevel;
-   struct gl_texture_image *image = tObj->Image[baseLevel];
-   mgaTextureObjectPtr t;
-   int i, ofs;
-   int LastLevel;
-   int s, s2;
-   int tformat;
-
-   if (!image) return;
-
-   tObj->DriverData = t = calloc( 1, sizeof( *t ) );
-   if (!t) {
-      fprintf(stderr, "mgaCreateTexObj: Failed to malloc mgaTextureObject\n" );
-      return;
-   }
-
-   /* FIXME: Use the real DD interface...
-    */
-   tformat = mgaChooseTexFormat( mmesa, image, image->Format,
-                                GL_UNSIGNED_BYTE );
-   t->texelBytes = image->TexFormat->TexelBytes;
-
-   /* We are going to upload all levels that are present, even if
-    * later levels wouldn't be used by the current filtering mode.  This
-    * allows the filtering mode to change without forcing another upload
-    * of the images.
-    */
-   LastLevel = MGA_TEX_MAXLEVELS-1;
-
-   ofs = 0;
-   for ( i = 0 ; i <= LastLevel ; i++ ) {
-      if ( !tObj->Image[i] ) {
-        LastLevel = i - 1;
-        break;
-      }
-
-      t->offsets[i] = ofs;
-      t->dirty_images |= (1<<i);
-
-      ofs += ((MAX2( tObj->Image[i]->Width, 8 ) *
-              MAX2( tObj->Image[i]->Height, 8 ) *
-              t->texelBytes) + 31) & ~31;
-   }
-   t->totalSize = ofs;
-   t->lastLevel = LastLevel;
-   t->tObj = tObj;
-   t->ctx = mmesa;
-   t->age = 0;
-   t->bound = 0;
-   t->MemBlock = 0;
-
-   insert_at_tail(&(mmesa->SwappedOut), t);
-
-
-   /* setup hardware register values */
-   t->setup.texctl = TMC_takey_1 | TMC_tamask_0 | tformat;
-
-   if (image->WidthLog2 >= 3)
-      t->setup.texctl |= ((image->WidthLog2 - 3) << TMC_tpitch_SHIFT);
-   else
-      t->setup.texctl |= (TMC_tpitchlin_enable |
-                         (image->Width << TMC_tpitchext_SHIFT));
-
-
-   t->setup.texctl2 = TMC_ckstransdis_enable;
-
-   if ( mmesa->glCtx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR )
-      t->setup.texctl2 |= TMC_specen_enable;
-
-
-   t->setup.texfilter = (TF_minfilter_nrst |
-                        TF_magfilter_nrst |
-                        TF_filteralpha_enable |
-                        (0x10 << TF_fthres_SHIFT) |
-                        (LastLevel << TF_mapnb_SHIFT));
-
-   /* warp texture registers */
-   ofs = MGA_IS_G200(mmesa) ? 28 : 11;
-   s = image->Width;
-   s2 = image->WidthLog2;
-   t->setup.texwidth = (MGA_FIELD(TW_twmask, s - 1) |
-                       MGA_FIELD(TW_rfw, (10 - s2 - 8) & 63 ) |
-                       MGA_FIELD(TW_tw, (s2 + ofs ) | 0x40 ));
-
 
-   s = image->Height;
-   s2 = image->HeightLog2;
-   t->setup.texheight = (MGA_FIELD(TH_thmask, s - 1) |
-                        MGA_FIELD(TH_rfh, (10 - s2 - 8) & 63 ) |
-                        MGA_FIELD(TH_th, (s2 + ofs ) | 0x40 ));
-
-
-   /* set all the register values for filtering, border, etc */
-   mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
-   mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
-   mgaSetTexBorderColor( t, tObj->_BorderChan );
-}
-
-
-
-
-static void mgaUpdateTextureEnvG200( GLcontext *ctx )
+static mgaTextureObjectPtr
+mgaAllocTexObj( struct gl_texture_object *tObj )
 {
-   struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
    mgaTextureObjectPtr t;
 
-   if (!tObj || !tObj->DriverData)
-      return;
-
-   t = (mgaTextureObjectPtr)tObj->DriverData;
-
-   t->setup.texctl2 &= ~TMC_decalblend_enable;
-
-   switch (ctx->Texture.Unit[0].EnvMode) {
-   case GL_REPLACE:
-      t->setup.texctl &= ~TMC_tmodulate_enable;
-      break;
-   case GL_MODULATE:
-      t->setup.texctl |= TMC_tmodulate_enable;
-      break;
-   case GL_DECAL:
-      t->setup.texctl &= ~TMC_tmodulate_enable;
-      t->setup.texctl2 |= TMC_decalblend_enable;
-      break;
-   case GL_BLEND:
-      FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-      break;
-   default:
-      break;
-   }
-}
-
-static void mgaUpdateTextureEnvG400( GLcontext *ctx, int unit )
-{
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
-   GLuint source = mmesa->tmu_source[unit];
-   struct gl_texture_object *tObj = ctx->Texture.Unit[source]._Current;
-   GLenum format;
-
-   if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj ) 
-      return;
-
-   format = tObj->Image[tObj->BaseLevel]->Format;
-
-   switch (ctx->Texture.Unit[source].EnvMode) {
-   case GL_REPLACE:
-      if (format == GL_RGB || format == GL_LUMINANCE) {
-        *reg = (TD0_color_sel_arg1 |
-                 TD0_alpha_arg2_diffuse |
-                TD0_alpha_sel_arg2 );
-      }
-      else if (format == GL_ALPHA) {
-         *reg = (TD0_color_sel_arg2 |
-                 TD0_color_arg2_diffuse |
-                 TD0_alpha_sel_arg1 );
-      }
-      else {
-         *reg = (TD0_color_sel_arg1 |
-                 TD0_alpha_sel_arg1 );
-      }
-      break;
-
-   case GL_MODULATE:
-      if (unit == 0) {
-        *reg = ( TD0_color_arg2_diffuse |
-                 TD0_color_sel_mul |
-                 TD0_alpha_arg2_diffuse |
-                 TD0_alpha_sel_mul);
-      }
-      else {
-        *reg = ( TD0_color_arg2_prevstage |
-                 TD0_color_alpha_prevstage |
-                 TD0_color_sel_mul |
-                 TD0_alpha_arg2_prevstage |
-                 TD0_alpha_sel_mul);
-      }
-      break;
-   case GL_DECAL:
-      if (format == GL_RGB) {
-         if (unit == 0) {
-            *reg = (TD0_color_sel_arg1 |
-                    TD0_alpha_arg2_diffuse |
-                    TD0_alpha_sel_arg2 );
-         }
-         else {
-            *reg = (TD0_color_sel_arg1 |
-                    TD0_alpha_arg2_prevstage |
-                    TD0_alpha_sel_arg2 );
-         }
-      }
-      else if ( format == GL_RGBA ) {
-#if 0
-         if (unit == 0) {
-            /* this doesn't work */
-            *reg = (TD0_color_arg2_diffuse |
-                    TD0_color_alpha_currtex |
-                    TD0_color_alpha2inv_enable |
-                    TD0_color_arg2mul_alpha2 |
-                    TD0_color_arg1mul_alpha1 |
-                    TD0_color_blend_enable |
-                    TD0_color_arg1add_mulout |
-                    TD0_color_arg2add_mulout |
-                    TD0_color_add_add |
-                    TD0_color_sel_mul |
-                    TD0_alpha_arg2_diffuse |
-                    TD0_alpha_sel_arg2 );
-         }
-         else {
-            *reg = (TD0_color_arg2_prevstage |
-                    TD0_color_alpha_currtex |
-                    TD0_color_alpha2inv_enable |
-                    TD0_color_arg2mul_alpha2 |
-                    TD0_color_arg1mul_alpha1 |
-                    TD0_color_add_add |
-                    TD0_color_sel_add |
-                    TD0_alpha_arg2_prevstage |
-                    TD0_alpha_sel_arg2 );
-         }
-#else
-         /* s/w fallback, pretty sure we can't do in h/w */
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-        if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
-           fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n",
-                    unit );
-#endif
-      }
-      else {
-        if (unit == 0) {
-           *reg = ( TD0_color_arg2_diffuse |
-                    TD0_color_sel_arg2 |
-                    TD0_alpha_arg2_diffuse |
-                    TD0_alpha_sel_arg2);
-        }
-        else {
-           *reg = ( TD0_color_arg2_prevstage |
-                    TD0_color_sel_arg2 |
-                    TD0_alpha_arg2_prevstage |
-                    TD0_alpha_sel_arg2);
-        }
-      }
-      break;
-
-   case GL_ADD:
-      if (unit == 0) {
-         if (format == GL_INTENSITY)
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_add_enable |
-                     TD0_alpha_sel_add);
-         else if (format == GL_ALPHA)
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_sel_mul |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_sel_mul);
-         else
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_sel_mul);
-      }
-      else {
-         if (format == GL_INTENSITY) {
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_add_enable |
-                     TD0_alpha_sel_add);
-         }
-         else if (format == GL_ALPHA) {
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_sel_mul |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_sel_mul);
-         }
-         else {
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_alpha_prevstage |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_sel_mul);
-         }
-      }
-      break;
-
-   case GL_BLEND:
-      if (format == GL_ALPHA) {
-        *reg = ( TD0_color_arg2_diffuse |
-                 TD0_color_sel_mul |
-                 TD0_alpha_arg2_diffuse |
-                 TD0_alpha_sel_mul);
-      }
-      else {
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-        if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
-           fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n",
-                    mmesa->envcolor );
-
-         /* Do singletexture GL_BLEND with 'all ones' env-color
-          * by using both texture units.  Multitexture gl_blend
-          * is a fallback.
-          */
-         if (unit == 0) {
-            /* Part 1: R1 = Rf ( 1 - Rt )
-             *         A1 = Af At
-             */
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_arg1_inv_enable |
-                     TD0_color_sel_mul |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_sel_arg1);
-         } else {
-            /* Part 2: R2 = R1 + Rt
-             *         A2 = A1
-             */
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_sel_arg2);
-         }
-      }
-      break;
-   default:
-      break;
-   }
-}
-
-
-
-static void mgaUpdateTextureObject( GLcontext *ctx, int hw_unit )
-{
-   mgaTextureObjectPtr t;
-   struct gl_texture_object    *tObj;
-   GLuint enabled;
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   GLuint gl_unit = mmesa->tmu_source[hw_unit];
-
-
-   enabled = ctx->Texture.Unit[gl_unit]._ReallyEnabled;
-   tObj = ctx->Texture.Unit[gl_unit]._Current;
-
-   if (enabled != TEXTURE_2D_BIT) {
-      if (enabled)
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-      return;
-   }
-
-   if (tObj->Image[tObj->BaseLevel]->Border > 0) {
-      FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-      if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
-        fprintf( stderr, "FALLBACK: texture border\n" );
-      return;
-   }
-
-   if ( !tObj->DriverData ) {
-      mgaCreateTexObj( mmesa, tObj );
-      if ( !tObj->DriverData ) {
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-        return;                
-      }
-   }
-
-   t = (mgaTextureObjectPtr)tObj->DriverData;
-
-   if (t->dirty_images)
-      mmesa->dirty |= (MGA_UPLOAD_TEX0IMAGE << hw_unit);
-
-   mmesa->CurrentTexObj[hw_unit] = t;
-   t->bound |= hw_unit+1;
-
-/*     if (t->MemBlock) */
-/*        mgaUpdateTexLRU( mmesa, t ); */
-
-   t->setup.texctl2 &= ~TMC_dualtex_enable;
-   if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT) &&
-       (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) 
-      t->setup.texctl2 |= TMC_dualtex_enable;
-
-   t->setup.texctl2 &= ~TMC_specen_enable;
-   if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
-      t->setup.texctl2 |= TMC_specen_enable;
-}
-
-
 
+   t = CALLOC( sizeof( *t ) );
+   tObj->DriverData = t;
+   if ( t != NULL ) {
+      /* Initialize non-image-dependent parts of the state:
+       */
+      t->base.tObj = tObj;
 
+      t->setup.texctl = TMC_takey_1 | TMC_tamask_0;
+      t->setup.texctl2 = TMC_ckstransdis_enable;
+      t->setup.texfilter = (TF_minfilter_nrst 
+                           | TF_magfilter_nrst
+                           | TF_filteralpha_enable
+                           | TF_uvoffset_OGL);
 
+      t->border_fallback = GL_FALSE;
 
-/* The G400 is now programmed quite differently wrt texture environment.
- */
-void mgaUpdateTextureState( GLcontext *ctx )
-{
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_FALSE );
+      make_empty_list( & t->base );
 
-   if (mmesa->CurrentTexObj[0]) {
-      mmesa->CurrentTexObj[0]->bound = 0;
-      mmesa->CurrentTexObj[0] = 0;
-   }
-
-   if (mmesa->CurrentTexObj[1]) {
-      mmesa->CurrentTexObj[1]->bound = 0;
-      mmesa->CurrentTexObj[1] = 0;
-   }
-
-   if (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT) {
-      mmesa->tmu_source[0] = 1;
-   } else {
-      mmesa->tmu_source[0] = 0;
-   }
-
-   if (MGA_IS_G400(mmesa)) {
-      mgaUpdateTextureObject( ctx, 0 );
-      mgaUpdateTextureEnvG400( ctx, 0 );
-
-      mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
-      
-      if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT) &&
-          (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
-        mgaUpdateTextureObject( ctx, 1 );      
-        mgaUpdateTextureEnvG400( ctx, 1 );
-        mmesa->dirty |= MGA_UPLOAD_TEX1;
-      }
-   } else {
-      mgaUpdateTextureObject( ctx, 0 );
-      mgaUpdateTextureEnvG200( ctx );
+      mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
+      mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
+      mgaSetTexBorderColor( t, tObj->_BorderChan );
    }
 
-   mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0;
-
-   mmesa->setup.dwgctl &= DC_opcod_MASK;
-   mmesa->setup.dwgctl |= (ctx->Texture.Unit[0]._ReallyEnabled
-                          ? DC_opcod_texture_trap
-                          : DC_opcod_trap);
+   return( t );
 }
 
 
-
-
 static void mgaDDTexEnv( GLcontext *ctx, GLenum target,
                         GLenum pname, const GLfloat *param )
 {
+   GLuint unit = ctx->Texture.CurrentUnit;
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
 
 
-   if (pname == GL_TEXTURE_ENV_MODE) {
-      /* force the texture state to be updated */
-      FLUSH_BATCH( MGA_CONTEXT(ctx) );
-      MGA_CONTEXT(ctx)->new_state |= (MGA_NEW_TEXTURE |
-                                     MGA_NEW_ALPHA);
-   }
-   else if (pname == GL_TEXTURE_ENV_COLOR)
-   {
-      struct gl_texture_unit *texUnit =
-        &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-      GLfloat *fc = texUnit->EnvColor;
+   switch( pname ) {
+   case GL_TEXTURE_ENV_COLOR: {
       GLubyte c[4];
-      GLuint col;
+      GLuint envColor;
 
-      COPY_4V(c, fc);
-      col = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] );
-      mmesa->envcolor = (c[3]<<24) | (c[0]<<16) | (c[1]<<8) | (c[2]);
+      UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
+      envColor = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] );
+      mmesa->envcolor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
 
-      if (mmesa->setup.fcol != col) {
+      if (mmesa->setup.fcol != envColor) {
         FLUSH_BATCH(mmesa);
-        mmesa->setup.fcol = col;
+        mmesa->setup.fcol = envColor;
         mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 
         mmesa->blend_flags &= ~MGA_BLEND_ENV_COLOR;
@@ -814,6 +354,8 @@ static void mgaDDTexEnv( GLcontext *ctx, GLenum target,
         if (mmesa->envcolor != 0x0 && mmesa->envcolor != 0xffffffff)
            mmesa->blend_flags |= MGA_BLEND_ENV_COLOR;
       }
+      break;
+   }
    }
 }
 
@@ -826,14 +368,26 @@ static void mgaTexImage2D( GLcontext *ctx, GLenum target, GLint level,
                            struct gl_texture_object *texObj,
                            struct gl_texture_image *texImage )
 {
-   mgaTextureObjectPtr t = (mgaTextureObjectPtr) texObj->DriverData;
-   if (t) {
-      mgaDestroyTexObj( MGA_CONTEXT(ctx), t );
-      texObj->DriverData = 0;
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+
+   if ( t != NULL ) {
+      driSwapOutTextureObject( t );
+   } 
+   else {
+      t = (driTextureObject *) mgaAllocTexObj( texObj );
+      if ( t == NULL ) {
+        _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
+        return;
+      }
    }
+
    _mesa_store_teximage2d( ctx, target, level, internalFormat,
                           width, height, border, format, type,
                           pixels, packing, texObj, texImage );
+   level -= t->firstLevel;
+   if (level >= 0)
+      t->dirty_images[0] |= (1UL << level);
 }
 
 static void mgaTexSubImage2D( GLcontext *ctx, 
@@ -847,44 +401,59 @@ static void mgaTexSubImage2D( GLcontext *ctx,
                               struct gl_texture_object *texObj,
                               struct gl_texture_image *texImage )
 {
-   mgaTextureObjectPtr t = (mgaTextureObjectPtr) texObj->DriverData;
-   if (t) {
-      mgaDestroyTexObj( MGA_CONTEXT(ctx), t );
-      texObj->DriverData = 0;
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+
+   assert( t != NULL ); /* this _should_ be true */
+   if ( t != NULL ) {
+      driSwapOutTextureObject( t );
+   } 
+   else {
+      t = (driTextureObject *) mgaAllocTexObj( texObj );
+      if ( t == NULL ) {
+        _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
+        return;
+      }
    }
+
    _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, 
                             height, format, type, pixels, packing, texObj,
                             texImage);
-
+   level -= t->firstLevel;
+   if (level >= 0)
+      t->dirty_images[0] |= (1UL << level);
 }
 
 
-
-
-/*
- * mgaTexParameter
- * This just changes variables and flags for a state update, which
- * will happen at the next mgaUpdateTextureState
+/**
+ * Changes variables and flags for a state update, which will happen at the
+ * next UpdateTextureState
  */
+
 static void
 mgaDDTexParameter( GLcontext *ctx, GLenum target,
                   struct gl_texture_object *tObj,
                   GLenum pname, const GLfloat *params )
 {
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+   mgaContextPtr       mmesa = MGA_CONTEXT( ctx );
    mgaTextureObjectPtr t;
 
    t = (mgaTextureObjectPtr) tObj->DriverData;
 
-   /* if we don't have a hardware texture, it will be automatically
-      created with current state before it is used, so we don't have
-      to do anything now */
-   if ( !t || !t->bound || target != GL_TEXTURE_2D ) {
+   /* If we don't have a hardware texture, it will be automatically
+    * created with current state before it is used, so we don't have
+    * to do anything now 
+    */
+
+   if ( (t == NULL)
+        || (target != GL_TEXTURE_2D) ) {
       return;
    }
 
    switch (pname) {
    case GL_TEXTURE_MIN_FILTER:
+      driSwapOutTextureObject( (driTextureObject *) t );
+      /* FALLTHROUGH */
    case GL_TEXTURE_MAG_FILTER:
       FLUSH_BATCH(mmesa);
       mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
@@ -898,14 +467,24 @@ mgaDDTexParameter( GLcontext *ctx, GLenum target,
 
    case GL_TEXTURE_BORDER_COLOR:
       FLUSH_BATCH(mmesa);
-      mgaSetTexBorderColor(t,tObj->_BorderChan);
+      mgaSetTexBorderColor(t, tObj->_BorderChan);
+      break;
+
+   case GL_TEXTURE_BASE_LEVEL:
+   case GL_TEXTURE_MAX_LEVEL:
+   case GL_TEXTURE_MIN_LOD:
+   case GL_TEXTURE_MAX_LOD:
+      /* This isn't the most efficient solution but there doesn't appear to
+       * be a nice alternative.  Since there's no LOD clamping,
+       * we just have to rely on loading the right subset of mipmap levels
+       * to simulate a clamped LOD.
+       */
+      driSwapOutTextureObject( (driTextureObject *) t );
       break;
 
    default:
       return;
    }
-
-   mmesa->new_state |= MGA_NEW_TEXTURE;
 }
 
 
@@ -913,19 +492,11 @@ static void
 mgaDDBindTexture( GLcontext *ctx, GLenum target,
                  struct gl_texture_object *tObj )
 {
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   int unit = ctx->Texture.CurrentUnit;
-
-   FLUSH_BATCH(mmesa);
-
-   if (mmesa->CurrentTexObj[unit]) {
-      mmesa->CurrentTexObj[unit]->bound &= ~(unit+1);
-      mmesa->CurrentTexObj[unit] = 0;
+   if ( target == GL_TEXTURE_2D ) {
+      if ( tObj->DriverData == NULL ) {
+        mgaAllocTexObj( tObj );
+      }
    }
-
-   /* force the texture state to be updated
-    */
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
 }
 
 
@@ -933,53 +504,48 @@ static void
 mgaDDDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
 {
    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   mgaTextureObjectPtr t = (mgaTextureObjectPtr)tObj->DriverData;
+   driTextureObject * t = (driTextureObject *) tObj->DriverData;
 
    if ( t ) {
-      if (mmesa) {
-         if (t->bound) {
-            FLUSH_BATCH(mmesa);
-            if (t->bound & TEX_0) mmesa->CurrentTexObj[0] = 0;
-            if (t->bound & TEX_1) mmesa->CurrentTexObj[1] = 0;
-         }
-         mmesa->new_state |= MGA_NEW_TEXTURE;
+      if ( mmesa ) {
+        FLUSH_BATCH( mmesa );
       }
 
-      mgaDestroyTexObj( mmesa, t );
+      driDestroyTextureObject( t );
    }
 }
 
 
-static GLboolean
-mgaDDIsTextureResident( GLcontext *ctx, struct gl_texture_object *t )
-{
-   mgaTextureObjectPtr mt = (mgaTextureObjectPtr)t->DriverData;
-   return mt && mt->MemBlock;
-}
-
-
 void
 mgaDDInitTextureFuncs( GLcontext *ctx )
 {
-   ctx->Driver.TexEnv = mgaDDTexEnv;
-
-   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
-   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
-   ctx->Driver.TexImage2D = mgaTexImage2D;
-   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
-   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
-   ctx->Driver.TexSubImage2D = mgaTexSubImage2D;
-   ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
-   ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
-   ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
-   ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
-   ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
-   ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
-   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
-
-   ctx->Driver.BindTexture = mgaDDBindTexture;
-   ctx->Driver.DeleteTexture = mgaDDDeleteTexture;
-   ctx->Driver.TexParameter = mgaDDTexParameter;
-   ctx->Driver.UpdateTexturePalette = 0;
-   ctx->Driver.IsTextureResident = mgaDDIsTextureResident;
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+
+   ctx->Driver.ChooseTextureFormat     = mgaChooseTextureFormat;
+   ctx->Driver.TexImage1D              = _mesa_store_teximage1d;
+   ctx->Driver.TexImage2D              = mgaTexImage2D;
+   ctx->Driver.TexImage3D              = _mesa_store_teximage3d;
+   ctx->Driver.TexSubImage1D           = _mesa_store_texsubimage1d;
+   ctx->Driver.TexSubImage2D           = mgaTexSubImage2D;
+   ctx->Driver.TexSubImage3D           = _mesa_store_texsubimage3d;
+   ctx->Driver.CopyTexImage1D          = _swrast_copy_teximage1d;
+   ctx->Driver.CopyTexImage2D          = _swrast_copy_teximage2d;
+   ctx->Driver.CopyTexSubImage1D       = _swrast_copy_texsubimage1d;
+   ctx->Driver.CopyTexSubImage2D       = _swrast_copy_texsubimage2d;
+   ctx->Driver.CopyTexSubImage3D       = _swrast_copy_texsubimage3d;
+   ctx->Driver.TestProxyTexImage       = _mesa_test_proxy_teximage;
+
+   ctx->Driver.BindTexture             = mgaDDBindTexture;
+   ctx->Driver.CreateTexture           = NULL; /* FIXME: Is this used??? */
+   ctx->Driver.DeleteTexture           = mgaDDDeleteTexture;
+   ctx->Driver.IsTextureResident       = driIsTextureResident;
+   ctx->Driver.PrioritizeTexture       = NULL;
+   ctx->Driver.ActiveTexture           = NULL;
+   ctx->Driver.UpdateTexturePalette    = NULL;
+
+   ctx->Driver.TexEnv                  = mgaDDTexEnv;
+   ctx->Driver.TexParameter            = mgaDDTexParameter;
+
+   driInitTextureObjects( ctx, & mmesa->swapped, DRI_TEXMGR_DO_TEXTURE_2D );
 }