Add Roland Scheidegger's S3TC patch. This patch does not implement the
authorEric Anholt <anholt@FreeBSD.org>
Thu, 7 Oct 2004 23:30:29 +0000 (23:30 +0000)
committerEric Anholt <anholt@FreeBSD.org>
Thu, 7 Oct 2004 23:30:29 +0000 (23:30 +0000)
(patented) S3TC/DXTC algorithms, but adds an option to dlopen a library module
providing functions to do so.  Because it uses dlopen, it is only enabled if
USE_EXTERNAL_DXTN_LIB=1 is defined (which is only in linux-dri config, so far).
It adds support for S3TC to several DRI drivers, and adds a DRI config option to
force enabling S3TC even if the software compression/decompression is
unavailable.  This may allow people to use apps that require S3TC even though
they don't have a license to implement the patented material themselves, if
those apps use precompressed textures.

Ideally we would get permission from the current holder of the patents to
implement the algorithm in Mesa, at which point the dlopen mess could go away.
Until then, this allows some to run applications they couldn't otherwise, and
hopefully will provide us with more push to get the final step of getting that
permission done.

26 files changed:
configs/linux-dri
src/mesa/drivers/dri/common/xmlpool.h
src/mesa/drivers/dri/i830/i830_context.c
src/mesa/drivers/dri/i830/i830_screen.c
src/mesa/drivers/dri/i830/i830_tex.c
src/mesa/drivers/dri/i830/i830_texmem.c
src/mesa/drivers/dri/i830/i830_texstate.c
src/mesa/drivers/dri/i915/i830_texstate.c
src/mesa/drivers/dri/i915/i915_texstate.c
src/mesa/drivers/dri/i915/intel_context.c
src/mesa/drivers/dri/i915/intel_context.h
src/mesa/drivers/dri/i915/intel_screen.c
src/mesa/drivers/dri/i915/intel_screen.h
src/mesa/drivers/dri/i915/intel_tex.c
src/mesa/drivers/dri/r200/r200_context.c
src/mesa/drivers/dri/r200/r200_screen.c
src/mesa/drivers/dri/r200/r200_tex.c
src/mesa/drivers/dri/r200/r200_texmem.c
src/mesa/drivers/dri/r200/r200_texstate.c
src/mesa/drivers/dri/radeon/radeon_context.c
src/mesa/drivers/dri/radeon/radeon_screen.c
src/mesa/drivers/dri/radeon/radeon_tex.c
src/mesa/drivers/dri/radeon/radeon_texmem.c
src/mesa/drivers/dri/radeon/radeon_texstate.c
src/mesa/main/mtypes.h
src/mesa/main/texcompress_s3tc.c

index ea760c3cd5425bf1980092194411f5f5da89f6f3..0d5210d3c1c55b7195f503a22193f35fe71ad3a5 100644 (file)
@@ -17,6 +17,7 @@ PIC_FLAGS = -fPIC
 
 CFLAGS = -DDRI_NEW_INTERFACE_ONLY $(WARN_FLAGS) -g $(OPT_FLAGS) $(ASM_FLAGS) \
        -std=c99 $(PIC_FLAGS) -ffast-math $(SOURCE_FLAGS) -DPTHREADS \
+       -DUSE_EXTERNAL_DXTN_LIB=1 \
        -I/usr/X11R6/include -I/usr/X11R6/include/X11/extensions
 
 CXXFLAGS = -DDRI_NEW_INTERFACE_ONLY $(WARN_FLAGS) -g $(OPT_FLAGS) -fPIC \
index 7b8222e0a20b3af4b52876dc9878058fe032b82a..efd13a136ab0010caf75df5ff0ceadadb5a893b0 100644 (file)
@@ -159,6 +159,12 @@ DRI_CONF_OPT_BEGIN(no_neg_lod_bias,bool,def) \
         DRI_CONF_DESC(de,"Verbiete negativen Textur-LOD-Bias") \
 DRI_CONF_OPT_END
 
+#define DRI_CONF_FORCE_S3TC_ENABLE(def) \
+DRI_CONF_OPT_BEGIN(force_s3tc_enable,bool,def) \
+        DRI_CONF_DESC(en,"enable s3tc even if software support is not available") \
+        DRI_CONF_DESC(de,"Benutze s3tc auch ohne Softwareunterstuetzung") \
+DRI_CONF_OPT_END
+
 #define DRI_CONF_COLOR_REDUCTION_ROUND 0
 #define DRI_CONF_COLOR_REDUCTION_DITHER 1
 #define DRI_CONF_COLOR_REDUCTION(def) \
index b69f11a0c0d4cf1b02984dcb3e352a1b467bf454..3e6f8a9a1fb242e93d7fc302fb32ec48177f4018 100644 (file)
@@ -73,7 +73,7 @@ int I830_DEBUG = (0);
  * Mesa's Driver Functions
  ***************************************/
 
-#define DRIVER_DATE                     "20040506"
+#define DRIVER_DATE                     "20041007"
 
 
 static const GLubyte *i830DDGetString( GLcontext *ctx, GLenum name )
@@ -372,6 +372,14 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
 
    driInitExtensions( ctx, card_extensions, GL_TRUE );
 
+   if (imesa->glCtx->Mesa_DXTn) {
+     _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+     _mesa_enable_extension( ctx, "GL_S3_s3tc" );
+   }
+   else if (driQueryOptionb (&imesa->optionCache, "force_s3tc_enable")) {
+     _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+   }
+
    _mesa_enable_extension( ctx, "GL_3DFX_texture_compression_FXT1" );
 
    /* XXX these should really go right after _mesa_init_driver_functions() */
index 52aa22d9d16182bafd3f4df1fa49ed18571bb704..f323baccbfa48ecf9ca4acb321f2bc5f231dfa45 100644 (file)
@@ -59,9 +59,10 @@ const char __driConfigOptions[] =
 DRI_CONF_BEGIN
     DRI_CONF_SECTION_PERFORMANCE
        DRI_CONF_MAX_TEXTURE_UNITS(4,2,4)
+       DRI_CONF_FORCE_S3TC_ENABLE(false)
     DRI_CONF_SECTION_END
 DRI_CONF_END;
-const GLuint __driNConfigOptions = 1;
+const GLuint __driNConfigOptions = 2;
 
 #ifdef USE_NEW_INTERFACE
 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
index 2fb4cc93249775a7a8345e1f80a017a2077ef9d5..41b5d9293303c57ee385fcff7d63c63b203be786 100644 (file)
@@ -643,6 +643,22 @@ i830ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
    case GL_COMPRESSED_RGBA_FXT1_3DFX:
      return &_mesa_texformat_rgba_fxt1;
 
+   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:
       fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__);
       return NULL;
index 6a30b496555c714e8262eac453d055fde769f9c7..7faf90874ce1099dc95823fe041b2c38b9334e1a 100644 (file)
@@ -116,6 +116,20 @@ static void i830UploadTexLevel( i830ContextPtr imesa,
               src += image->Width*2;
             }
           }
+        else if ((t->Setup[I830_TEXREG_TM0S1] & TM0S1_MT_FORMAT_MASK)==MT_COMPRESS_DXT1)
+          {
+            for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
+              __memcpy(dst, src, (image->Width*2) );
+              src += image->Width*2;
+            }
+          }
+        else if (((t->Setup[I830_TEXREG_TM0S1] & TM0S1_MT_FORMAT_MASK)==MT_COMPRESS_DXT2_3) || ((t->Setup[I830_TEXREG_TM0S1] & TM0S1_MT_FORMAT_MASK)==MT_COMPRESS_DXT4_5))
+          {
+            for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
+              __memcpy(dst, src, (image->Width*4) );
+              src += image->Width*4;
+            }
+          }
    }
    else if (image->Width * image->TexFormat->TexelBytes == t->Pitch) {
         GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[0][hwlevel].offset);
index d5440141bfefbe955e467636ff9e653d14622c9e..358c554f3b351f047f95013a8e41163149ef23d8 100644 (file)
@@ -117,7 +117,24 @@ static void i830SetTexImages( i830ContextPtr imesa,
      t->texelBytes = 2;
      textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
      break;
-
+   case MESA_FORMAT_RGBA_DXT1:
+   case MESA_FORMAT_RGB_DXT1:
+     /*
+      * DXTn pitches are Width/4 * blocksize in bytes
+      * for DXT1: blocksize=8 so Width/4*8 = Width * 2
+      * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
+      */
+     t->texelBytes = 2;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
+     break;
+   case MESA_FORMAT_RGBA_DXT3:
+     t->texelBytes = 4;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
+     break;
+   case MESA_FORMAT_RGBA_DXT5:
+     t->texelBytes = 4;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
+     break;
    default:
       fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
       free( t );
index a393fd1d52ecf1da5f343f3e28eb5d94762e6fb4..ba452279baf2b695442c40ddf69cbfd8284916ba 100644 (file)
@@ -125,6 +125,25 @@ static GLboolean i830SetTexImages( i830ContextPtr i830,
      textureFormat = MAPSURF_COMPRESSED | MT_COMPRESS_FXT1;
      break;
 
+   case MESA_FORMAT_RGBA_DXT1:
+   case MESA_FORMAT_RGB_DXT1:
+     /* 
+      * DXTn pitches are Width/4 * blocksize in bytes 
+      * for DXT1: blocksize=8 so Width/4*8 = Width * 2 
+      * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
+      */
+     t->intel.texelBytes = 2;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
+     break;
+   case MESA_FORMAT_RGBA_DXT3:
+     t->intel.texelBytes = 4;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
+     break;
+   case MESA_FORMAT_RGBA_DXT5:
+     t->intel.texelBytes = 4;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
+     break;
+
    default:
       fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
       abort();
index 60ba0629528a838f1e42e412223f1519c11e774d..2f94e6743acca81b700f3854492dcc16647bb3b0 100644 (file)
@@ -127,6 +127,24 @@ static void i915SetTexImages( i915ContextPtr i915,
      t->intel.texelBytes = 2;
      textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
      break;
+   case MESA_FORMAT_RGBA_DXT1:
+   case MESA_FORMAT_RGB_DXT1:
+     /* 
+      * DXTn pitches are Width/4 * blocksize in bytes 
+      * for DXT1: blocksize=8 so Width/4*8 = Width * 2 
+      * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
+      */
+     t->intel.texelBytes = 2;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
+     break;
+   case MESA_FORMAT_RGBA_DXT3:
+     t->intel.texelBytes = 4;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
+     break;
+   case MESA_FORMAT_RGBA_DXT5:
+     t->intel.texelBytes = 4;
+     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
+     break;
 
    default:
       fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
index c1559e9567eaa247babcc904af62edfd55438684..302ddfa840ebdaf27981a7ffdc6116c5fb76a57b 100644 (file)
@@ -72,7 +72,7 @@ int prevLockLine;
  * Mesa's Driver Functions
  ***************************************/
 
-#define DRIVER_DATE                     "20040919"
+#define DRIVER_DATE                     "20041007"
 
 const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
 {
@@ -354,6 +354,14 @@ GLboolean intelInitContext( intelContextPtr intel,
 
    driInitExtensions( ctx, card_extensions, GL_TRUE );
 
+   if (intel->ctx.Mesa_DXTn) {
+     _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+     _mesa_enable_extension( ctx, "GL_S3_s3tc" );
+   }
+   else if (driQueryOptionb (&intelScreen->optionCache, "force_s3tc_enable")) {
+     _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+   }
+
 /*    driInitTextureObjects( ctx, & intel->swapped, */
 /*                       DRI_TEXMGR_DO_TEXTURE_1D | */
 /*                       DRI_TEXMGR_DO_TEXTURE_2D |  */
index 839062921ba3b69d32a49fb1ec7032f78fa906aa..625e96f580f4df8b008291251b9e8a8fe9c1968b 100644 (file)
@@ -230,6 +230,11 @@ struct intel_context
    __DRIscreenPrivate *driScreen;
    intelScreenPrivate *intelScreen; 
    drmI830Sarea *sarea; 
+
+   /**
+    * Configuration cache
+    */
+   driOptionCache optionCache;
 };
 
 
index e7e9b12915445bd2726983a8ecd51a5cc730d233..8007ff48c2ead2b1199ada51c62c1090836cf756 100644 (file)
@@ -30,6 +30,7 @@
 #include "matrix.h"
 #include "simple_list.h"
 #include "utils.h"
+#include "xmlpool.h"
 
 
 #include "intel_screen.h"
 
 #include "i830_dri.h"
 
-const char __driConfigOptions[] = { 0 };
-const GLuint __driNConfigOptions = 0;
+const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+    DRI_CONF_SECTION_PERFORMANCE
+       DRI_CONF_FORCE_S3TC_ENABLE(false)
+    DRI_CONF_SECTION_END
+DRI_CONF_END;
+const GLuint __driNConfigOptions = 1;
 
 #ifdef USE_NEW_INTERFACE
 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
@@ -78,6 +84,9 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
       fprintf(stderr,"\nERROR!  Allocating private area failed\n");
       return GL_FALSE;
    }
+   /* parse information in __driConfigOptions */
+   driParseOptionInfo (&intelScreen->optionCache,
+                      __driConfigOptions, __driNConfigOptions);
 
    intelScreen->driScrnPriv = sPriv;
    sPriv->private = (void *)intelScreen;
index ffe5e8e50d24249090d2096d7f8ae629dff1854c..f2fb1c6bc9510dcb5a65b7fcd253c2667559e10a 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <sys/time.h>
 #include "dri_util.h"
-
+#include "xmlconfig.h"
 
 typedef struct {
    drm_handle_t handle;
@@ -76,6 +76,11 @@ typedef struct
 
    int irq_active;
    int allow_batchbuffer;
+
+   /**
+    * Configuration cache with default values for all contexts 
+    */
+   driOptionCache optionCache;
 } intelScreenPrivate;
 
 
index 4e22d7e3f77305574385bb006ba4e5790f0c6e2f..b6b8188275a9168e2351a131debccd79763d8739 100644 (file)
@@ -554,6 +554,22 @@ intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
    case GL_COMPRESSED_RGBA_FXT1_3DFX:
      return &_mesa_texformat_rgba_fxt1;
 
+   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:
       fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__);
       return NULL;
@@ -628,11 +644,24 @@ static void intelUploadTexImage( intelContextPtr intel,
        {
        case GL_COMPRESSED_RGB_FXT1_3DFX:
        case GL_COMPRESSED_RGBA_FXT1_3DFX:
+       case GL_RGB_S3TC:
+       case GL_RGB4_S3TC:
+       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
          for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
            __memcpy(dst, src, row_len );
            src += row_len;
          }
          break;
+       case GL_RGBA_S3TC:
+       case GL_RGBA4_S3TC:
+       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+         for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
+           __memcpy(dst, src, (image->Width*4) );
+           src += image->Width*4;
+         }
+         break;
        default:
          fprintf(stderr,"Internal Compressed format not supported %d\n", image->IntFormat);
          break;
index d5ca2f9b3a64c721baa673957cd92fec30b32c41..0868febc34610de9c995f186676c42bb55f43e37 100644 (file)
@@ -62,7 +62,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r200_vtxfmt.h"
 #include "r200_maos.h"
 
-#define DRIVER_DATE    "20040929"
+#define DRIVER_DATE    "20041007"
 
 #include "vblank.h"
 #include "utils.h"
@@ -401,6 +401,14 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
    _math_matrix_set_identity( &rmesa->tmpmat );
 
    driInitExtensions( ctx, card_extensions, GL_TRUE );
+   if (rmesa->glCtx->Mesa_DXTn) {
+      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+      _mesa_enable_extension( ctx, "GL_S3_s3tc" );
+   }
+   else if (driQueryOptionb (&rmesa->optionCache, "force_s3tc_enable")) {
+      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+   }
+
    if (rmesa->r200Screen->drmSupportsCubeMaps)
       _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
    if (rmesa->r200Screen->drmSupportsBlendColor) {
index e338e5b353cf943df6966ce5e12979b16cf0cb7b..1411394ab50286ca04e60d1abd864359abfe6cad 100644 (file)
@@ -68,6 +68,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)
@@ -80,7 +81,7 @@ DRI_CONF_BEGIN
         DRI_CONF_NV_VERTEX_PROGRAM(false)
     DRI_CONF_SECTION_END
 DRI_CONF_END;
-static const GLuint __driNConfigOptions = 13;
+static const GLuint __driNConfigOptions = 14;
 
 #if 1
 /* Including xf86PciInfo.h introduces a bunch of errors...
index 346c27cee0a66025d05f9cf68e9cffe7ac85aa14..3d259c2ca668bed10eb172106a4d7457b3f9e906 100644 (file)
@@ -420,6 +420,22 @@ r200ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
       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 r200ChooseTextureFormat",
@@ -710,6 +726,116 @@ static void r200TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
 }
 
 
+static void r200CompressedTexImage2D( 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 *) r200AllocTexObj( 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 (r200ValidateClientStorage( ctx, target, 
+                                 internalFormat,
+                                 width, height,
+                                 format, type, pixels,
+                                 packing, texObj, texImage)) {
+      if (R200_DEBUG & DEBUG_TEXTURE)
+        fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
+   }
+   else */{
+      if (R200_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 r200ChooseTextureFormat.
+       */
+      _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
+                                 height, border, imageSize, data, texObj, texImage);
+
+      t->dirty_images[face] |= (1 << level);
+   }
+}
+
+
+static void r200CompressedTexSubImage2D( 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 *) r200AllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
+         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 r200TexImage3D( GLcontext *ctx, GLenum target, GLint level,
                             GLint internalFormat,
@@ -1036,6 +1162,9 @@ void r200InitTextureFuncs( struct dd_function_table *functions )
    functions->TexParameter             = r200TexParameter;
    functions->TexGen                   = r200TexGen;
 
+   functions->CompressedTexImage2D     = r200CompressedTexImage2D;
+   functions->CompressedTexSubImage2D  = r200CompressedTexSubImage2D;
+
    driInitTextureFormats();
 
 #if 000
index bc937ce6cb2f7da7ae98654111b8a28122e3e11f..3f8e5d6e7f89345a14b6202a53dd5d039b27c5c4 100644 (file)
@@ -372,10 +372,23 @@ static void uploadSubImage( r200ContextPtr rmesa, r200TexObjPtr t,
       tex.height = imageHeight;
    }
    else {
-      tex.width = imageWidth; /* compressed */
-      tex.height = imageHeight;
-      if (tex.height < 4)
-         tex.height = 4;
+      /* 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.height = (imageHeight + 3) / 4;
+      tex.width = (imageWidth + 3) / 4;
+      switch (t->pp_txformat & R200_TXFORMAT_FORMAT_MASK) {
+      case R200_TXFORMAT_DXT1:
+           tex.width *= 8;
+           break;
+      case R200_TXFORMAT_DXT23:
+      case R200_TXFORMAT_DXT45:
+           tex.width *= 16;
+           break;
+      default:
+          fprintf(stderr, "unknown compressed tex format in uploadSubImage\n");
+      }
    }
    tex.image = &tmp;
 
index 003c1e3e473415ee4fbe4fd7a39a035a0c110f28..f6df2c4f82256b1c278ec9d63ec1ce9e6815002d 100644 (file)
@@ -53,6 +53,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 }
@@ -66,7 +70,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].format != 0xffffffff) )
 
 static const struct {
@@ -93,6 +97,12 @@ tx_table[] =
    _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),
 };
 
 #undef _COLOR
@@ -165,7 +175,24 @@ static void r200SetTexImages( r200ContextPtr rmesa,
 
       /* find image size in bytes */
       if (texImage->IsCompressed) {
-         size = texImage->CompressedSize;
+      /* need to calculate the size AFTER padding even though the texture is
+         submitted without padding.
+         Only handle pot textures currently - don't know if npot is even possible,
+         size calculation would certainly need (trivial) adjustments.
+         Align (and later pad) to 32byte, not sure what that 64byte blit width is
+         good for? */
+         if ((t->pp_txformat & R200_TXFORMAT_FORMAT_MASK) == R200_TXFORMAT_DXT1) {
+            /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
+            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 */
+            if ((texImage->Width + 3) < 8)
+               size = texImage->CompressedSize * 2;
+            else size = texImage->CompressedSize;
       }
       else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
          size = ((texImage->Width * texImage->TexFormat->TexelBytes + 63)
index 5f419347b45f351437d43216d8b611e5df586f13..fc69ec1b5bcc88faf0e8c502c247f411a87d62b5 100644 (file)
@@ -62,7 +62,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "radeon_vtxfmt.h"
 #include "radeon_maos.h"
 
-#define DRIVER_DATE    "20040929"
+#define DRIVER_DATE    "20041007"
 
 #include "vblank.h"
 #include "utils.h"
@@ -397,6 +397,13 @@ radeonCreateContext( const __GLcontextModes *glVisual,
    _math_matrix_set_identity( &rmesa->tmpmat );
 
    driInitExtensions( ctx, card_extensions, GL_TRUE );
+   if (rmesa->glCtx->Mesa_DXTn) {
+      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+      _mesa_enable_extension( ctx, "GL_S3_s3tc" );
+   }
+   else if (driQueryOptionb (&rmesa->optionCache, "force_s3tc_enable")) {
+      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
+   }
 
    if (rmesa->dri.drmMinor >= 9)
       _mesa_enable_extension( ctx, "GL_NV_texture_rectangle");
index a3b2047bc8e1225b845ab939b816062d2813d21e..d725d312f4f258f791514b88c313945ace74cc6b 100644 (file)
@@ -65,6 +65,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)
@@ -73,7 +74,7 @@ DRI_CONF_BEGIN
         DRI_CONF_NO_RAST(false)
     DRI_CONF_SECTION_END
 DRI_CONF_END;
-static const GLuint __driNConfigOptions = 10;
+static const GLuint __driNConfigOptions = 11;
 
 #if 1
 /* Including xf86PciInfo.h introduces a bunch of errors...
index 82b5d940f88888f732e651e38b30ed25178489f6..c466af868c4981ba79553763914a8b31e57121d0 100644 (file)
@@ -382,6 +382,22 @@ radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
       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 texture format in %s", __FUNCTION__);
       return NULL;
@@ -544,8 +560,95 @@ static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
    t->dirty_images[face] |= (1 << level);
 }
 
+static void radeonCompressedTexImage2D( 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 *) radeonAllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+         return;
+      }
+   }
+
+   /* Note, this will call ChooseTextureFormat */
+   _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
+                                 height, border, imageSize, data, texObj, texImage);
+
+   t->dirty_images[face] |= (1 << level);
+}
 
 
+static void radeonCompressedTexSubImage2D( 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 *) radeonAllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
+         return;
+      }
+   }
+
+   _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+                                 height, format, imageSize, data, texObj, texImage);
+
+   t->dirty_images[face] |= (1 << level);
+}
+
 #define SCALED_FLOAT_TO_BYTE( x, scale ) \
                (((GLuint)((255.0F / scale) * (x))) / 2)
 
@@ -756,5 +859,8 @@ void radeonInitTextureFuncs( struct dd_function_table *functions )
    functions->TexParameter             = radeonTexParameter;
    functions->TexGen                   = radeonTexGen;
 
+   functions->CompressedTexImage2D     = radeonCompressedTexImage2D;
+   functions->CompressedTexSubImage2D  = radeonCompressedTexSubImage2D;
+
    driInitTextureFormats();
 }
index c075c2c5625f21b21d036cab98c918f281234ebf..6ac00c27b2c5d62766cd125e65741191a42bf8b4 100644 (file)
@@ -257,10 +257,21 @@ static void uploadSubImage( radeonContextPtr rmesa, radeonTexObjPtr t,
       tex.height = imageHeight;
    }
    else {
-      tex.width = imageWidth; /* compressed */
-      tex.height = imageHeight;
-      if (tex.height < 4)
-         tex.height = 4;
+      /* 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.height = (imageHeight + 3) / 4;
+      tex.width = (imageWidth + 3) / 4;
+      switch (t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK) {
+      case RADEON_TXFORMAT_DXT1:
+         tex.width *= 8;
+         break;
+      case RADEON_TXFORMAT_DXT23:
+      case RADEON_TXFORMAT_DXT45:
+         tex.width *= 16;
+         break;
+      }
    }
    tex.image = &tmp;
 
index 49220472dfcf3a1495a461c5f1b9f8746d3a5e5e..5e818da9fd17af04dfb0bcc8ab9160cae013f94f 100644 (file)
@@ -55,6 +55,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RADEON_TXFORMAT_AL88      RADEON_TXFORMAT_AI88
 #define RADEON_TXFORMAT_YCBCR     RADEON_TXFORMAT_YVYU422
 #define RADEON_TXFORMAT_YCBCR_REV RADEON_TXFORMAT_VYUY422
+#define RADEON_TXFORMAT_RGB_DXT1  RADEON_TXFORMAT_DXT1
+#define RADEON_TXFORMAT_RGBA_DXT1 RADEON_TXFORMAT_DXT1
+#define RADEON_TXFORMAT_RGBA_DXT3 RADEON_TXFORMAT_DXT23
+#define RADEON_TXFORMAT_RGBA_DXT5 RADEON_TXFORMAT_DXT45
 
 #define _COLOR(f) \
     [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, 0 }
@@ -68,7 +72,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, RADEON_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].format != 0xffffffff) )
 
 static const struct {
@@ -95,6 +99,12 @@ tx_table[] =
    _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),
 };
 
 #undef _COLOR
@@ -167,7 +177,24 @@ static void radeonSetTexImages( radeonContextPtr rmesa,
 
       /* find image size in bytes */
       if (texImage->IsCompressed) {
-         size = texImage->CompressedSize;
+      /* need to calculate the size AFTER padding even though the texture is
+         submitted without padding.
+         Only handle pot textures currently - don't know if npot is even possible,
+         size calculation would certainly need (trivial) adjustments.
+         Align (and later pad) to 32byte, not sure what that 64byte blit width is
+         good for? */
+         if ((t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK) == RADEON_TXFORMAT_DXT1) {
+            /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
+            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 */
+            if ((texImage->Width + 3) < 8)
+               size = texImage->CompressedSize * 2;
+            else size = texImage->CompressedSize;
       }
       else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
         size = ((texImage->Width * texImage->TexFormat->TexelBytes + 63)
index 07119a2fb6e182ecdd67d8978927ee6c9b8290ba..4086ef94bedb44e5361eaee7489959ad61754ebc 100644 (file)
@@ -2455,6 +2455,9 @@ struct __GLcontextRec {
    /** Dither disable via MESA_NO_DITHER env var */
    GLboolean NoDither;
 
+   /** software compression/decompression supported or not */
+   GLboolean Mesa_DXTn;
+
    /** Core tnl module support */
    struct gl_tnl_module TnlModule;
 
index 572cdd25614f0eaba7a5916cf6e2fee26fa163ad..a797c2edf9b3587c9e6158b6081f811afe175c7b 100644 (file)
@@ -28,6 +28,9 @@
  * GL_EXT_texture_compression_s3tc support.
  */
 
+#ifndef USE_EXTERNAL_DXTN_LIB
+#define USE_EXTERNAL_DXTN_LIB 0
+#endif
 
 #include "glheader.h"
 #include "imports.h"
 #include "texformat.h"
 #include "texstore.h"
 
+#if USE_EXTERNAL_DXTN_LIB
+#include <dlfcn.h>
+#endif
+
+typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut );
+dxtFetchTexelFuncExt fetch_ext_rgb_dxt1;
+dxtFetchTexelFuncExt fetch_ext_rgba_dxt1;
+dxtFetchTexelFuncExt fetch_ext_rgba_dxt3;
+dxtFetchTexelFuncExt fetch_ext_rgba_dxt5;
+
+typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width, GLint height, const GLubyte *srcPixData, GLenum destformat, GLubyte *dest);
+dxtCompressTexFuncExt ext_tx_compress_dxtn;
 
+void *dxtlibhandle = NULL;
 
 void
 _mesa_init_texture_s3tc( GLcontext *ctx )
 {
    /* called during context initialization */
+   ctx->Mesa_DXTn = GL_FALSE;
+#if USE_EXTERNAL_DXTN_LIB
+   if (!dxtlibhandle) {
+      char *error;
+
+      dxtlibhandle = dlopen ("libtxc_dxtn.so", RTLD_LAZY | RTLD_GLOBAL);
+      if (!dxtlibhandle) {
+        _mesa_warning(ctx, "couldn't open libtxc_dxtn.so, software DXTn"
+           "compression/decompression unavailable\n");
+      }
+      else {
+         /* the fetch functions are not per context! Might be problematic... */
+         fetch_ext_rgb_dxt1 = dlsym(dxtlibhandle, "fetch_2d_texel_rgb_dxt1");
+         error = dlerror();
+         if (error == NULL) {
+            fetch_ext_rgba_dxt1 = dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt1");
+            error = dlerror();
+         }
+         if (error == NULL) {
+            fetch_ext_rgba_dxt3 = dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt3");
+            error = dlerror();
+         }
+         if (error == NULL) {
+            fetch_ext_rgba_dxt5 = dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt5");
+            error = dlerror();
+         }
+         if (error == NULL) {
+            ext_tx_compress_dxtn = dlsym(dxtlibhandle, "tx_compress_dxtn");
+            error = dlerror();
+         }
+
+         if (error) {
+           _mesa_warning(ctx, "couldn't reference all symbols in "
+              "libtxc_dxtn.so, software DXTn compression/decompression "
+              "unavailable\n");
+            fetch_ext_rgb_dxt1 = NULL;
+            fetch_ext_rgba_dxt1 = NULL;
+            fetch_ext_rgba_dxt3 = NULL;
+            fetch_ext_rgba_dxt5 = NULL;
+            ext_tx_compress_dxtn = NULL;
+            dlclose(dxtlibhandle);
+            dxtlibhandle = NULL;
+         }
+      }
+   }
+   if (dxtlibhandle) {
+      ctx->Mesa_DXTn = GL_TRUE;
+      _mesa_warning(ctx, "software DXTn compression/decompression available\n");
+   }
+#else
    (void) ctx;
+#endif
 }
 
-
 /**
  * Called via TexFormat->StoreImage to store an RGB_DXT1 texture.
  */
@@ -95,10 +161,12 @@ texstore_rgb_dxt1(STORE_PARAMS)
                                         GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
                                         texWidth, (GLubyte *) dstAddr);
 
-#if 0
-   compress_dxt1(ctx, srcWidth, srcHeight, srcFormat, pixels, srcRowStride,
-                 dst, dstRowStride);
-#endif
+   if (ext_tx_compress_dxtn) {
+      (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels,  GL_COMPRESSED_RGB_S3TC_DXT1_EXT, dst);
+   }
+   else {
+      _mesa_problem(ctx, "external dxt library not available");
+   }
 
    if (tempImage)
       _mesa_free((void *) tempImage);
@@ -152,10 +220,13 @@ texstore_rgba_dxt1(STORE_PARAMS)
    dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
                                         GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
                                         texWidth, (GLubyte *) dstAddr);
-#if 0
-   compress_dxt1(ctx, srcWidth, srcHeight, srcFormat, pixels, srcRowStride,
-                 dst, dstRowStride);
-#endif
+   if (ext_tx_compress_dxtn) {
+      (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,  GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, dst);
+   }
+   else {
+      _mesa_problem(ctx, "external dxt library not available");
+   }
+
    if (tempImage)
       _mesa_free((void*) tempImage);
 
@@ -207,10 +278,13 @@ texstore_rgba_dxt3(STORE_PARAMS)
    dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
                                         GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
                                         texWidth, (GLubyte *) dstAddr);
-#if 0
-   compress_rgba_dxt3(ctx, srcWidth, srcHeight, pixels,
-                      srcRowStride, dst, dstRowStride);
-#endif
+   if (ext_tx_compress_dxtn) {
+      (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,  GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, dst);
+   }
+   else {
+      _mesa_problem(ctx, "external dxt library not available");
+   }
+
    if (tempImage)
       _mesa_free((void *) tempImage);
 
@@ -262,10 +336,13 @@ texstore_rgba_dxt5(STORE_PARAMS)
    dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
                                         GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
                                         texWidth, (GLubyte *) dstAddr);
-#if 0
-   compress_rgba_dxt5(ctx, srcWidth, srcHeight, pixels,
-                      srcRowStride, dst, dstRowStride);
-#endif
+   if (ext_tx_compress_dxtn) {
+      (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,  GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, dst);
+   }
+   else {
+      _mesa_problem(ctx, "external dxt library not available");
+   }
+
    if (tempImage)
       _mesa_free((void *) tempImage);
 
@@ -277,7 +354,12 @@ static void
 fetch_texel_2d_rgb_dxt1( const struct gl_texture_image *texImage,
                          GLint i, GLint j, GLint k, GLchan *texel )
 {
-   (void) texImage; (void) i; (void) j; (void) k; (void) texel;
+    (void) k;
+    if (fetch_ext_rgb_dxt1) {
+       ASSERT (sizeof(GLchan) == sizeof(GLubyte));
+       (*fetch_ext_rgb_dxt1)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel);
+    }
+    else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
 }
 
 
@@ -299,7 +381,11 @@ static void
 fetch_texel_2d_rgba_dxt1( const struct gl_texture_image *texImage,
                           GLint i, GLint j, GLint k, GLchan *texel )
 {
-   (void) texImage; (void) i; (void) j; (void) k; (void) texel;
+   (void) k;
+   if (fetch_ext_rgba_dxt1) {
+       (*fetch_ext_rgba_dxt1)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel);
+    }
+    else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
 }
 
 
@@ -321,7 +407,12 @@ static void
 fetch_texel_2d_rgba_dxt3( const struct gl_texture_image *texImage,
                           GLint i, GLint j, GLint k, GLchan *texel )
 {
-   (void) texImage; (void) i; (void) j; (void) k; (void) texel;
+   (void) k;
+   if (fetch_ext_rgba_dxt3) {
+       ASSERT (sizeof(GLchan) == sizeof(GLubyte));
+       (*fetch_ext_rgba_dxt3)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel);
+    }
+    else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
 }
 
 
@@ -343,7 +434,11 @@ static void
 fetch_texel_2d_rgba_dxt5( const struct gl_texture_image *texImage,
                           GLint i, GLint j, GLint k, GLchan *texel )
 {
-   (void) texImage; (void) i; (void) j; (void) k; (void) texel;
+   (void) k;
+   if (fetch_ext_rgba_dxt5) {
+       (*fetch_ext_rgba_dxt5)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel);
+    }
+    else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
 }