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
This commit is contained in:
Dave Airlie 2005-09-25 10:20:38 +00:00
parent 310a10b0f2
commit 4aeaff2ae7
6 changed files with 394 additions and 199 deletions

View 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 |

View 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);

View 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();

View 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;
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);
}
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);
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;
}
/* 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];
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 ( !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;
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__);
offset = t->bufAddr;
imageWidth = texImage->Width;
imageHeight = texImage->Height;
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);
}
offset = t->bufAddr + t->base.totalSize / 6 * face;
t->image[face][hwlevel].data = texImage->Data;
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 );
}
/* 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)
*/
t->image[face][hwlevel].data = texImage->Data;
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;
/* 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
}
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;
}
}
#if 0
sleep(1);
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 );
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
UNLOCK_HARDWARE( &rmesa->radeon );
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);
}
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 );
}
}
/**

View 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;

View 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[];