mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-04 20:38:06 +02:00
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:
parent
310a10b0f2
commit
4aeaff2ae7
6 changed files with 394 additions and 199 deletions
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue