diff options
author | Eric Anholt <[email protected]> | 2004-10-07 23:30:29 +0000 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2004-10-07 23:30:29 +0000 |
commit | d09209f5530e8bba78e4e0ec62b2027c588cc8f3 (patch) | |
tree | 0c7bdde2064bcf0c880e8bf259a8ef80dbc933a0 /src/mesa/drivers/dri/radeon | |
parent | 554e5a2eaf4b681b5c43b6aeb66f100a66da4a42 (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/drivers/dri/radeon')
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_context.c | 9 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_screen.c | 3 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_tex.c | 106 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_texmem.c | 19 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_texstate.c | 31 |
5 files changed, 160 insertions, 8 deletions
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c index 5f419347b45..fc69ec1b5bc 100644 --- a/src/mesa/drivers/dri/radeon/radeon_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_context.c @@ -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"); diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c index a3b2047bc8e..d725d312f4f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.c +++ b/src/mesa/drivers/dri/radeon/radeon_screen.c @@ -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... diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.c b/src/mesa/drivers/dri/radeon/radeon_tex.c index 82b5d940f88..c466af868c4 100644 --- a/src/mesa/drivers/dri/radeon/radeon_tex.c +++ b/src/mesa/drivers/dri/radeon/radeon_tex.c @@ -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(); } diff --git a/src/mesa/drivers/dri/radeon/radeon_texmem.c b/src/mesa/drivers/dri/radeon/radeon_texmem.c index c075c2c5625..6ac00c27b2c 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texmem.c +++ b/src/mesa/drivers/dri/radeon/radeon_texmem.c @@ -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; diff --git a/src/mesa/drivers/dri/radeon/radeon_texstate.c b/src/mesa/drivers/dri/radeon/radeon_texstate.c index 49220472dfc..5e818da9fd1 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texstate.c +++ b/src/mesa/drivers/dri/radeon/radeon_texstate.c @@ -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) |