summaryrefslogtreecommitdiff
path: root/src/mesa/main/texcompress_s3tc.c
diff options
context:
space:
mode:
authorEric Anholt <anholt@FreeBSD.org>2004-10-07 23:30:29 +0000
committerEric Anholt <anholt@FreeBSD.org>2004-10-07 23:30:29 +0000
commitd09209f5530e8bba78e4e0ec62b2027c588cc8f3 (patch)
tree0c7bdde2064bcf0c880e8bf259a8ef80dbc933a0 /src/mesa/main/texcompress_s3tc.c
parent554e5a2eaf4b681b5c43b6aeb66f100a66da4a42 (diff)
Add Roland Scheidegger's S3TC patch. This patch does not implement the
(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.
Diffstat (limited to 'src/mesa/main/texcompress_s3tc.c')
-rw-r--r--src/mesa/main/texcompress_s3tc.c137
1 files changed, 116 insertions, 21 deletions
diff --git a/src/mesa/main/texcompress_s3tc.c b/src/mesa/main/texcompress_s3tc.c
index 572cdd2561..a797c2edf9 100644
--- a/src/mesa/main/texcompress_s3tc.c
+++ b/src/mesa/main/texcompress_s3tc.c
@@ -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"
@@ -39,16 +42,79 @@
#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");
}