Add support for texture compression to R300 driver
authorDave Airlie <airliedfreedesktop.org>
Sun, 25 Sep 2005 10:20:38 +0000 (10:20 +0000)
committerDave Airlie <airliedfreedesktop.org>
Sun, 25 Sep 2005 10:20:38 +0000 (10:20 +0000)
This isn't perfect, texcmp still has some issues with the small textures..
but its a good start

src/mesa/drivers/dri/r300/r300_cmdbuf.c
src/mesa/drivers/dri/r300/r300_context.c
src/mesa/drivers/dri/r300/r300_tex.c
src/mesa/drivers/dri/r300/r300_texmem.c
src/mesa/drivers/dri/r300/r300_texstate.c
src/mesa/drivers/dri/r300/radeon_screen.c

index 9ef74dd..f24ebe1 100644 (file)
@@ -587,6 +587,7 @@ void r300EmitBlit(r300ContextPtr rmesa,
                                                        __FUNCTION__);
 
        cmd[0].header.cmd_type = R300_CMD_PACKET3;
+       cmd[0].header.pad0 = R300_CMD_PACKET3_RAW;
        cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16);
        cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
                    RADEON_GMC_DST_PITCH_OFFSET_CNTL |
index 927cc88..db8b0a6 100644 (file)
@@ -380,6 +380,14 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
 
        driInitExtensions(ctx, card_extensions, GL_TRUE);
        
+       if (r300->radeon.glCtx->Mesa_DXTn) {
+         _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+         _mesa_enable_extension( ctx, "GL_S3_s3tc" );
+       }
+       else if (driQueryOptionb (&r300->radeon.optionCache, "force_s3tc_enable")) {
+         _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+       }
+
        radeonInitSpanFuncs(ctx);
        r300InitCmdBuf(r300);
        r300InitState(r300);
index e6c8c18..44368c2 100644 (file)
@@ -433,6 +433,22 @@ static const struct gl_texture_format *r300ChooseTextureFormat(GLcontext * ctx,
                else
                        return &_mesa_texformat_ycbcr_rev;
 
+       case GL_RGB_S3TC:
+       case GL_RGB4_S3TC:
+       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+         return &_mesa_texformat_rgb_dxt1;
+         
+       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+         return &_mesa_texformat_rgba_dxt1;
+         
+       case GL_RGBA_S3TC:
+       case GL_RGBA4_S3TC:
+       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+         return &_mesa_texformat_rgba_dxt3;
+         
+       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+         return &_mesa_texformat_rgba_dxt5;
+         
        default:
                _mesa_problem(ctx,
                              "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
@@ -706,6 +722,115 @@ static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
        t->dirty_images[face] |= (1 << level);
 }
 
+static void r300CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+                              GLint internalFormat,
+                              GLint width, GLint height, GLint border,
+                              GLsizei imageSize, const GLvoid *data,
+                              struct gl_texture_object *texObj,
+                              struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+   GLuint face;
+
+   /* which cube face or ordinary 2D image */
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+      ASSERT(face < 6);
+      break;
+   default:
+      face = 0;
+   }
+
+   if ( t != NULL ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) r300AllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+         return;
+      }
+   }
+
+   texImage->IsClientData = GL_FALSE;
+/* can't call this, different parameters. Would never evaluate to true anyway currently
+   if (r300ValidateClientStorage( ctx, target, 
+                                 internalFormat,
+                                 width, height,
+                                 format, type, pixels,
+                                 packing, texObj, texImage)) {
+      if (RADEON_DEBUG & DEBUG_TEXTURE)
+        fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
+   }
+   else */{
+      if (RADEON_DEBUG & DEBUG_TEXTURE)
+        fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
+
+      /* Normal path: copy (to cached memory) and eventually upload
+       * via another copy to GART memory and then a blit...  Could
+       * eliminate one copy by going straight to (permanent) GART.
+       *
+       * Note, this will call r300ChooseTextureFormat.
+       */
+      _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
+                                 height, border, imageSize, data, texObj, texImage);
+
+      t->dirty_images[face] |= (1 << level);
+   }
+}
+
+
+static void r300CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
+                                 GLint xoffset, GLint yoffset,
+                                 GLsizei width, GLsizei height,
+                                 GLenum format,
+                                 GLsizei imageSize, const GLvoid *data,
+                                 struct gl_texture_object *texObj,
+                                 struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+   GLuint face;
+
+
+   /* which cube face or ordinary 2D image */
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+      ASSERT(face < 6);
+      break;
+   default:
+      face = 0;
+   }
+
+   assert( t ); /* this _should_ be true */
+   if ( t ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) r300AllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage3D");
+         return;
+      }
+   }
+
+   _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+                            height, format, imageSize, data, texObj, texImage);
+
+   t->dirty_images[face] |= (1 << level);
+}
+
 #if ENABLE_HW_3D_TEXTURE
 static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level,
                           GLint internalFormat,
@@ -1032,6 +1157,9 @@ void r300InitTextureFuncs(struct dd_function_table *functions)
        functions->TexEnv = r300TexEnv;
        functions->TexParameter = r300TexParameter;
        functions->TexGen = r300TexGen;
+       
+       functions->CompressedTexImage2D = r300CompressedTexImage2D;
+       functions->CompressedTexSubImage2D      = r300CompressedTexSubImage2D;
 
        driInitTextureFormats();
 
index ca39276..64fed68 100644 (file)
@@ -276,162 +276,185 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa,
  * Upload the texture image associated with texture \a t at the specified
  * level at the address relative to \a start.
  */
-static void uploadSubImage(r300ContextPtr rmesa, r300TexObjPtr t,
-                          GLint hwlevel,
-                          GLint x, GLint y, GLint width, GLint height,
-                          GLuint face)
+static void uploadSubImage( r300ContextPtr rmesa, r300TexObjPtr t, 
+                           GLint hwlevel,
+                           GLint x, GLint y, GLint width, GLint height,
+                           GLuint face )
 {
-       struct gl_texture_image *texImage = NULL;
-       GLuint offset;
-       GLint imageWidth, imageHeight;
-       GLint ret;
-       drm_radeon_texture_t tex;
-       drm_radeon_tex_image_t tmp;
-       const int level = hwlevel + t->base.firstLevel;
-
-       if (RADEON_DEBUG & DEBUG_TEXTURE) {
-               fprintf(stderr,
-                       "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n",
-                       __FUNCTION__, (void *)t, (void *)t->base.tObj, level,
-                       width, height, face);
-       }
-
-       ASSERT(face < 6);
-
-       /* Ensure we have a valid texture to upload */
-       if ((hwlevel < 0) || (hwlevel >= RADEON_MAX_TEXTURE_LEVELS)) {
-               _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
-               return;
-       }
-
-       texImage = t->base.tObj->Image[face][level];
-
-       if (!texImage) {
-               if (RADEON_DEBUG & DEBUG_TEXTURE)
-                       fprintf(stderr, "%s: texImage %d is NULL!\n",
-                               __FUNCTION__, level);
-               return;
-       }
-       if (!texImage->Data) {
-               if (RADEON_DEBUG & DEBUG_TEXTURE)
-                       fprintf(stderr, "%s: image data is NULL!\n",
-                               __FUNCTION__);
-               return;
-       }
-
-       if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
-               assert(level == 0);
-               assert(hwlevel == 0);
-               if (RADEON_DEBUG & DEBUG_TEXTURE)
-                       fprintf(stderr, "%s: image data is rectangular\n",
-                               __FUNCTION__);
-               r300UploadRectSubImage(rmesa, t, texImage, x, y, width, height);
-               return;
-       } else if (texImage->IsClientData) {
-               if (RADEON_DEBUG & DEBUG_TEXTURE)
-                       fprintf(stderr,
-                               "%s: image data is in GART client storage\n",
-                               __FUNCTION__);
-               r300UploadGARTClientSubImage(rmesa, t, texImage, hwlevel, x, y,
-                                            width, height);
-               return;
-       } else if (RADEON_DEBUG & DEBUG_TEXTURE)
-               fprintf(stderr, "%s: image data is in normal memory\n",
-                       __FUNCTION__);
-
-       imageWidth = texImage->Width;
-       imageHeight = texImage->Height;
-
-       offset = t->bufAddr;
-
-       if (RADEON_DEBUG & (DEBUG_TEXTURE | DEBUG_IOCTL)) {
-               GLint imageX = 0;
-               GLint imageY = 0;
-               GLint blitX = t->image[face][hwlevel].x;
-               GLint blitY = t->image[face][hwlevel].y;
-               GLint blitWidth = t->image[face][hwlevel].width;
-               GLint blitHeight = t->image[face][hwlevel].height;
-               fprintf(stderr, "   upload image: %d,%d at %d,%d\n",
-                       imageWidth, imageHeight, imageX, imageY);
-               fprintf(stderr, "   upload  blit: %d,%d at %d,%d\n",
-                       blitWidth, blitHeight, blitX, blitY);
-               fprintf(stderr, "       blit ofs: 0x%07x level: %d/%d\n",
-                       (GLuint) offset, hwlevel, level);
-       }
-
-       t->image[face][hwlevel].data = texImage->Data;
-
-       /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct.
-        * NOTE: we're always use a 1KB-wide blit and I8 texture format.
-        * We used to use 1, 2 and 4-byte texels and used to use the texture
-        * width to dictate the blit width - but that won't work for compressed
-        * textures. (Brian)
-        */
-
-       tex.offset = offset;
-       tex.pitch = BLIT_WIDTH_BYTES / 64;
-       tex.format = R200_TXFORMAT_I8;  /* any 1-byte texel format */
-#if 0 /* I am not sure HOSTDATA_BLT actually works.. Experiment here  - V.D */
-       tex.format = R200_TXFORMAT_RGBA8888;    /* any 4-byte texel format */
-#endif
-       if (texImage->TexFormat->TexelBytes) {
-               tex.width = imageWidth * texImage->TexFormat->TexelBytes;       /* in bytes */
-               tex.height = imageHeight;
-       } else {
-               tex.width = imageWidth; /* compressed */
-               tex.height = imageHeight;
-               if (tex.height < 4)
-                       tex.height = 4;
-       }
-       tex.image = &tmp;
+   struct gl_texture_image *texImage = NULL;
+   GLuint offset;
+   GLint imageWidth, imageHeight;
+   GLint ret;
+   drm_radeon_texture_t tex;
+   drm_radeon_tex_image_t tmp;
+   const int level = hwlevel + t->base.firstLevel;
+
+   if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+      fprintf( stderr, "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n", 
+              __FUNCTION__, (void *)t, (void *)t->base.tObj,
+              level, width, height, face );
+   }
+
+   ASSERT(face < 6);
+
+   /* Ensure we have a valid texture to upload */
+   if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) {
+      _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
+      return;
+   }
+
+   texImage = t->base.tObj->Image[face][level];
+
+   if ( !texImage ) {
+      if ( RADEON_DEBUG & DEBUG_TEXTURE )
+        fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
+      return;
+   }
+   if ( !texImage->Data ) {
+      if ( RADEON_DEBUG & DEBUG_TEXTURE )
+        fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
+      return;
+   }
+
+
+   if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+      assert(level == 0);
+      assert(hwlevel == 0);
+      if ( RADEON_DEBUG & DEBUG_TEXTURE )
+        fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
+      r300UploadRectSubImage( rmesa, t, texImage, x, y, width, height );
+      return;
+   }
+   else if (texImage->IsClientData) {
+      if ( RADEON_DEBUG & DEBUG_TEXTURE )
+        fprintf( stderr, "%s: image data is in GART client storage\n",
+                 __FUNCTION__);
+      r300UploadGARTClientSubImage( rmesa, t, texImage, hwlevel,
+                                  x, y, width, height );
+      return;
+   }
+   else if ( RADEON_DEBUG & DEBUG_TEXTURE )
+      fprintf( stderr, "%s: image data is in normal memory\n",
+              __FUNCTION__);
+      
+
+   imageWidth = texImage->Width;
+   imageHeight = texImage->Height;
+
+   offset = t->bufAddr + t->base.totalSize / 6 * face;
+
+   if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
+      GLint imageX = 0;
+      GLint imageY = 0;
+      GLint blitX = t->image[face][hwlevel].x;
+      GLint blitY = t->image[face][hwlevel].y;
+      GLint blitWidth = t->image[face][hwlevel].width;
+      GLint blitHeight = t->image[face][hwlevel].height;
+      fprintf( stderr, "   upload image: %d,%d at %d,%d\n",
+              imageWidth, imageHeight, imageX, imageY );
+      fprintf( stderr, "   upload  blit: %d,%d at %d,%d\n",
+              blitWidth, blitHeight, blitX, blitY );
+      fprintf( stderr, "       blit ofs: 0x%07x level: %d/%d\n",
+              (GLuint)offset, hwlevel, level );
+   }
+
+   t->image[face][hwlevel].data = texImage->Data;
+
+   /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct.
+    * NOTE: we're always use a 1KB-wide blit and I8 texture format.
+    * We used to use 1, 2 and 4-byte texels and used to use the texture
+    * width to dictate the blit width - but that won't work for compressed
+    * textures. (Brian)
+    * NOTE: can't do that with texture tiling. (sroland)
+    */
+   tex.offset = offset;
+   tex.image = &tmp;
+   /* copy (x,y,width,height,data) */
+   memcpy( &tmp, &t->image[face][hwlevel], sizeof(tmp) );
+   
+   if (texImage->TexFormat->TexelBytes) {
+      /* use multi-byte upload scheme */
+      tex.height = imageHeight;
+      tex.width = imageWidth;
+      switch(texImage->TexFormat->TexelBytes) {
+      case 1:
+       tex.format = RADEON_TXFORMAT_I8;
+       break;
+      case 2:
+       tex.format = RADEON_TXFORMAT_AI88;
+       break;
+      case 4:
+       tex.format = RADEON_TXFORMAT_ARGB8888;
+       break;
+      }
+      tex.pitch = MAX2((texImage->Width * texImage->TexFormat->TexelBytes) / 64, 1);
+      tex.offset += tmp.x & ~1023;
+      tmp.x = tmp.x % 1024;
 #if 0
-       tex.width /= 4;
+      if (t->tile_bits & R200_TXO_MICRO_TILE) {
+        /* need something like "tiled coordinates" ? */
+        tmp.y = tmp.x / (tex.pitch * 128) * 2;
+        tmp.x = tmp.x % (tex.pitch * 128) / 2 / texImage->TexFormat->TexelBytes;
+        tex.pitch |= RADEON_DST_TILE_MICRO >> 22;
+      }
+      else 
 #endif
-
-       /* copy (x,y,width,height,data) */
-       memcpy(&tmp, &t->image[face][hwlevel], sizeof(tmp));
+      {
+        tmp.x = tmp.x >> (texImage->TexFormat->TexelBytes >> 1);
+      }
 #if 0
-       tex.image->width /=4;
+      if ((t->tile_bits & R200_TXO_MACRO_TILE) &&
+        (texImage->Width * texImage->TexFormat->TexelBytes >= 256) &&
+        ((!(t->tile_bits & R200_TXO_MICRO_TILE) && (texImage->Height >= 8)) ||
+           (texImage->Height >= 16))) {
+        /* weird: R200 disables macro tiling if mip width is smaller than 256 bytes,
+           OR if height is smaller than 8 automatically, but if micro tiling is active
+           the limit is height 16 instead ? */
+        tex.pitch |= RADEON_DST_TILE_MACRO >> 22;
+      }
 #endif
-
-#if 0
-       sleep(1);
-
-       fprintf(stderr, "*** Uploading texture\n");
-               fprintf(stderr, "   offset=0x%08x\n", offset);
-               fprintf(stderr, "   image width=%d height=%d\n",
-                       imageWidth, imageHeight);
-               fprintf(stderr, "    blit width=%d height=%d data=%p\n",
-                       t->image[face][hwlevel].width,
-                       t->image[face][hwlevel].height,
-                       t->image[face][hwlevel].data);
-#endif
-
-       LOCK_HARDWARE(&rmesa->radeon);
-       do {
-               ret = drmCommandWriteRead(rmesa->radeon.dri.fd, DRM_RADEON_TEXTURE,
-                                         &tex, sizeof(drm_radeon_texture_t));
-               if (ret) {
-                       if (RADEON_DEBUG & DEBUG_IOCTL)
-                               fprintf(stderr,
-                                       "DRM_RADEON_TEXTURE:  again!\n");
-                       usleep(1);
-               }
-       } while (ret == -EAGAIN);
-
-       UNLOCK_HARDWARE(&rmesa->radeon);
-
-       if (ret) {
-               fprintf(stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret);
-               fprintf(stderr, "   offset=0x%08x\n", offset);
-               fprintf(stderr, "   image width=%d height=%d\n",
-                       imageWidth, imageHeight);
-               fprintf(stderr, "    blit width=%d height=%d data=%p\n",
-                       t->image[face][hwlevel].width,
-                       t->image[face][hwlevel].height,
-                       t->image[face][hwlevel].data);
-               exit(1);
-       }
+   }
+   else {
+      /* In case of for instance 8x8 texture (2x2 dxt blocks), padding after the first two blocks is
+         needed (only with dxt1 since 2 dxt3/dxt5 blocks already use 32 Byte). */
+      /* set tex.height to 1/4 since 1 "macropixel" (dxt-block) has 4 real pixels. Needed
+         so the kernel module reads the right amount of data. */
+      tex.format = R200_TXFORMAT_I8; /* any 1-byte texel format */
+      tex.pitch = (BLIT_WIDTH_BYTES / 64);
+      tex.height = (imageHeight + 3) / 4;
+      tex.width = (imageWidth + 3) / 4;
+      if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1)
+      {
+           tex.width *= 8;
+      } else {
+           tex.width *= 16;
+      }
+   }
+
+   LOCK_HARDWARE( &rmesa->radeon );
+   do {
+      ret = drmCommandWriteRead( rmesa->radeon.dri.fd, DRM_RADEON_TEXTURE,
+                                 &tex, sizeof(drm_radeon_texture_t) );
+      if (ret) {
+        if (RADEON_DEBUG & DEBUG_IOCTL)
+           fprintf(stderr, "DRM_RADEON_TEXTURE:  again!\n");
+        usleep(1);
+      }
+   } while ( ret == -EAGAIN );
+
+   UNLOCK_HARDWARE( &rmesa->radeon );
+
+   if ( ret ) {
+      fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
+      fprintf( stderr, "   offset=0x%08x\n",
+              offset );
+      fprintf( stderr, "   image width=%d height=%d\n",
+              imageWidth, imageHeight );
+      fprintf( stderr, "    blit width=%d height=%d data=%p\n",
+              t->image[face][hwlevel].width, t->image[face][hwlevel].height,
+              t->image[face][hwlevel].data );
+      exit( 1 );
+   }
 }
 
 /**
index 22fbe2e..5c51e30 100644 (file)
@@ -54,6 +54,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define R200_TXFORMAT_AL88      R200_TXFORMAT_AI88
 #define R200_TXFORMAT_YCBCR     R200_TXFORMAT_YVYU422
 #define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
+#define R200_TXFORMAT_RGB_DXT1  R200_TXFORMAT_DXT1
+#define R200_TXFORMAT_RGBA_DXT1 R200_TXFORMAT_DXT1
+#define R200_TXFORMAT_RGBA_DXT3 R200_TXFORMAT_DXT23
+#define R200_TXFORMAT_RGBA_DXT5 R200_TXFORMAT_DXT45
 
 #define _COLOR(f) \
     [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
@@ -67,7 +71,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
 #define _INVALID(f) \
     [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
-#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_YCBCR_REV) \
+#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
                             && tx_table[f].flag )
 
 #define _ASSIGN(entry, format) \
@@ -95,6 +99,12 @@ static const struct {
            _INVALID(CI8),
            _YUV(YCBCR),
            _YUV(YCBCR_REV),
+           _INVALID(RGB_FXT1),
+           _INVALID(RGBA_FXT1),
+           _COLOR(RGB_DXT1),
+           _ALPHA(RGBA_DXT1),
+           _ALPHA(RGBA_DXT3),
+           _ALPHA(RGBA_DXT5),
            };
 
 static const struct {
@@ -129,6 +139,10 @@ static const struct {
            _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
            _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE ),
            _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE),
+           _ASSIGN(RGB_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1)),
+           _ASSIGN(RGBA_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1)),
+           _ASSIGN(RGBA_DXT3, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3)),
+           _ASSIGN(RGBA_DXT5, R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5)),
            };
 
 #undef _COLOR
@@ -154,8 +168,8 @@ static void r300SetTexImages(r300ContextPtr rmesa,
        r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
        const struct gl_texture_image *baseImage =
            tObj->Image[0][tObj->BaseLevel];
-       GLint curOffset;
-       GLint i;
+       GLint curOffset, blitWidth;
+       GLint i, texelBytes;
        GLint numLevels;
        GLint log2Width, log2Height, log2Depth;
 
@@ -180,6 +194,8 @@ static void r300SetTexImages(r300ContextPtr rmesa,
                return;
        }
 
+       texelBytes = baseImage->TexFormat->TexelBytes;
+
        /* Compute which mipmap levels we really want to send to the hardware.
         */
 
@@ -197,68 +213,85 @@ static void r300SetTexImages(r300ContextPtr rmesa,
         * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
         */
        curOffset = 0;
+       blitWidth = BLIT_WIDTH_BYTES;
 
        for (i = 0; i < numLevels; i++) {
-               const struct gl_texture_image *texImage;
-               GLuint size;
-
-               texImage = tObj->Image[0][i + t->base.firstLevel];
-               if (!texImage)
-                       break;
-
-               /* find image size in bytes */
-               if (texImage->IsCompressed) {
-                       size = texImage->CompressedSize;
-               } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
-                       size =
-                           ((texImage->Width *
-                             texImage->TexFormat->TexelBytes + 63)
-                            & ~63) * texImage->Height;
-               } else {
-                       int w =
-                           texImage->Width * texImage->TexFormat->TexelBytes;
-                       if (w < 32)
-                               w = 32;
-                       size = w * texImage->Height * texImage->Depth;
-               }
-               assert(size > 0);
-
-               if(0)
-                       fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage->Width, texImage->Height,
-                               texImage->Depth, texImage->TexFormat->TexelBytes,
-                               texImage->IntFormat);
-
-               /* Align to 32-byte offset.  It is faster to do this unconditionally
-                * (no branch penalty).
-                */
-
-               curOffset = (curOffset + 0x1f) & ~0x1f;
-
-               t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
-               t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
-               t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
-               t->image[0][i].height = size / t->image[0][i].width;
-
+         const struct gl_texture_image *texImage;
+         GLuint size;
+         
+         texImage = tObj->Image[0][i + t->base.firstLevel];
+         if (!texImage)
+           break;
+         
+         /* find image size in bytes */
+         if (texImage->IsCompressed) {
+           if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1) {
+             fprintf(stderr,"DXT 1 %d %08X\n", texImage->Width, t->format);
+             if ((texImage->Width + 3) < 8) /* width one block */
+               size = texImage->CompressedSize * 4;
+             else if ((texImage->Width + 3) < 16)
+               size = texImage->CompressedSize * 2;
+             else size = texImage->CompressedSize;
+           }
+           else /* DXT3/5, 16 bytes per block */
+           {
+             fprintf(stderr,"DXT 3/5 %d\n", texImage->Width);
+             if ((texImage->Width + 3) < 8)
+               size = texImage->CompressedSize * 2;
+             else size = texImage->CompressedSize;
+           }
+           
+         } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+           size = ((texImage->Width * texelBytes + 63) & ~63) * texImage->Height;
+         } else {
+           int w = (texImage->Width * texelBytes + 31) & ~31;
+           size = w * texImage->Height * texImage->Depth;
+           blitWidth = MAX2(texImage->Width, 64 / texelBytes);
+         }
+         assert(size > 0);
+         
+         if(0)
+           fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage->Width, texImage->Height,
+                   texImage->Depth, texImage->TexFormat->TexelBytes,
+                   texImage->IntFormat);
+         
+         /* Align to 32-byte offset.  It is faster to do this unconditionally
+          * (no branch penalty).
+          */
+         
+         curOffset = (curOffset + 0x1f) & ~0x1f;
+         
+         if (texelBytes) {
+           t->image[0][i].x = curOffset; /* fix x and y coords up later together with offset */
+           t->image[0][i].y = 0;
+           t->image[0][i].width = MIN2(size / texelBytes, blitWidth);
+           t->image[0][i].height = (size / texelBytes) / t->image[0][i].width;
+         } else {
+           t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
+           t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
+           t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
+           t->image[0][i].height = size / t->image[0][i].width;
+         }
 #if 0
-               /* for debugging only and only  applicable to non-rectangle targets */
-               assert(size % t->image[0][i].width == 0);
-               assert(t->image[0][i].x == 0
-                      || (size < BLIT_WIDTH_BYTES
-                          && t->image[0][i].height == 1));
+         /* for debugging only and only  applicable to non-rectangle targets */
+         assert(size % t->image[0][i].width == 0);
+         assert(t->image[0][i].x == 0
+                || (size < BLIT_WIDTH_BYTES
+                    && t->image[0][i].height == 1));
 #endif
-
-               if (0)
-                       fprintf(stderr,
-                               "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
-                               i, texImage->Width, texImage->Height,
-                               t->image[0][i].x, t->image[0][i].y,
-                               t->image[0][i].width, t->image[0][i].height,
-                               size, curOffset);
-
-               curOffset += size;
-
+         
+         if (0)
+           fprintf(stderr,
+                   "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
+                   i, texImage->Width, texImage->Height,
+                   t->image[0][i].x, t->image[0][i].y,
+                   t->image[0][i].width, t->image[0][i].height,
+                   size, curOffset);
+         
+         curOffset += size;
+         
        }
-
+       
        /* Align the total size of texture memory block.
         */
        t->base.totalSize =
@@ -336,7 +369,7 @@ static void r300SetTexImages(r300ContextPtr rmesa,
        else
                t->pitch =
                    ((tObj->Image[0][t->base.firstLevel]->Width *
-                     baseImage->TexFormat->TexelBytes) + 63) & ~(63);
+                     texelBytes) + 63) & ~(63);
        t->pitch -= 32;
 
        t->dirty_state = TEX_ALL;
index 7b66ce7..b169b7e 100644 (file)
@@ -74,6 +74,7 @@ DRI_CONF_BEGIN
                DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
                DRI_CONF_DEF_MAX_ANISOTROPY(1.0, "1.0,2.0,4.0,8.0,16.0")
                DRI_CONF_NO_NEG_LOD_BIAS(false)
+               DRI_CONF_FORCE_S3TC_ENABLE(false)
                DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
                DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC)
                DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF)
@@ -86,7 +87,7 @@ DRI_CONF_BEGIN
                DRI_CONF_NV_VERTEX_PROGRAM(false)
        DRI_CONF_SECTION_END
 DRI_CONF_END;
-static const GLuint __driR200NConfigOptions = 13;
+static const GLuint __driR200NConfigOptions = 14;
 
 /* TODO: integrate these into xmlpool.h! */
 #define DRI_CONF_MAX_TEXTURE_IMAGE_UNITS(def,min,max) \
@@ -122,6 +123,7 @@ DRI_CONF_BEGIN
                DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
                DRI_CONF_DEF_MAX_ANISOTROPY(1.0, "1.0,2.0,4.0,8.0,16.0")
                DRI_CONF_NO_NEG_LOD_BIAS(false)
+                DRI_CONF_FORCE_S3TC_ENABLE(false)
                DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
                DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC)
                DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF)
@@ -130,7 +132,7 @@ DRI_CONF_BEGIN
                DRI_CONF_NO_RAST(false)
        DRI_CONF_SECTION_END
 DRI_CONF_END;
-static const GLuint __driR300NConfigOptions = 13;
+static const GLuint __driR300NConfigOptions = 14;
 
 extern const struct dri_extension card_extensions[];