summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDave Airlie <airliedfreedesktop.org>2005-09-25 10:20:38 +0000
committerDave Airlie <airliedfreedesktop.org>2005-09-25 10:20:38 +0000
commit4aeaff2ae7f4a4b209e0d0ee2081b592951b7054 (patch)
treed1bb92bf0c1fa0a448d21c1ef8d90724877d9df5 /src
parent310a10b0f29d4aba36242b9d90f19d016505eddb (diff)
Add support for texture compression to R300 driver
This isn't perfect, texcmp still has some issues with the small textures.. but its a good start
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/r300/r300_cmdbuf.c1
-rw-r--r--src/mesa/drivers/dri/r300/r300_context.c8
-rw-r--r--src/mesa/drivers/dri/r300/r300_tex.c128
-rw-r--r--src/mesa/drivers/dri/r300/r300_texmem.c325
-rw-r--r--src/mesa/drivers/dri/r300/r300_texstate.c155
-rw-r--r--src/mesa/drivers/dri/r300/radeon_screen.c6
6 files changed, 409 insertions, 214 deletions
diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
index 9ef74dd9aba..f24ebe1a91c 100644
--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c
+++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
@@ -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 |
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index 927cc88fda0..db8b0a6e11c 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r300/r300_tex.c b/src/mesa/drivers/dri/r300/r300_tex.c
index e6c8c18011b..44368c28196 100644
--- a/src/mesa/drivers/dri/r300/r300_tex.c
+++ b/src/mesa/drivers/dri/r300/r300_tex.c
@@ -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();
diff --git a/src/mesa/drivers/dri/r300/r300_texmem.c b/src/mesa/drivers/dri/r300/r300_texmem.c
index ca392762ad4..64fed681f1e 100644
--- a/src/mesa/drivers/dri/r300/r300_texmem.c
+++ b/src/mesa/drivers/dri/r300/r300_texmem.c
@@ -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 );
+ }
}
/**
diff --git a/src/mesa/drivers/dri/r300/r300_texstate.c b/src/mesa/drivers/dri/r300/r300_texstate.c
index 22fbe2e18a0..5c51e30637b 100644
--- a/src/mesa/drivers/dri/r300/r300_texstate.c
+++ b/src/mesa/drivers/dri/r300/r300_texstate.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/radeon_screen.c b/src/mesa/drivers/dri/r300/radeon_screen.c
index 7b66ce78ef1..b169b7e26d6 100644
--- a/src/mesa/drivers/dri/r300/radeon_screen.c
+++ b/src/mesa/drivers/dri/r300/radeon_screen.c
@@ -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[];