瀏覽代碼

r300: Improve texture layout calculations

The texture layout calculations for mipmapped cubemaps used to be completely
wrong, since the GPU expects images to be grouped by miplevel instead of by
face number.

This has been fixed now, though the memory layout is still slightly incorrect
for the smaller miplevels. Unfortunately, the docs are lacking in that area.
tags/mesa_7_1_rc2
Nicolai Haehnle 17 年之前
父節點
當前提交
fa1bc0d7d6
共有 2 個文件被更改,包括 120 次插入110 次删除
  1. 1
    1
      src/mesa/drivers/dri/r300/r300_texmem.c
  2. 119
    109
      src/mesa/drivers/dri/r300/r300_texstate.c

+ 1
- 1
src/mesa/drivers/dri/r300/r300_texmem.c 查看文件

@@ -349,7 +349,7 @@ static void r300UploadSubImage(r300ContextPtr rmesa, r300TexObjPtr t,
imageWidth = texImage->Width;
imageHeight = texImage->Height;

offset = t->bufAddr + t->base.totalSize / 6 * face;
offset = t->bufAddr;

if (RADEON_DEBUG & (DEBUG_TEXTURE | DEBUG_IOCTL)) {
GLint imageX = 0;

+ 119
- 109
src/mesa/drivers/dri/r300/r300_texstate.c 查看文件

@@ -189,6 +189,112 @@ void r300SetDepthTexMode(struct gl_texture_object *tObj)
}


/**
* Compute sizes and fill in offset and blit information for the given
* image (determined by \p face and \p level).
*
* \param curOffset points to the offset at which the image is to be stored
* and is updated by this function according to the size of the image.
*/
static void compute_tex_image_offset(
struct gl_texture_object *tObj,
GLuint face,
GLint level,
GLint* curOffset)
{
r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
const struct gl_texture_image* texImage;
GLuint blitWidth = R300_BLIT_WIDTH_BYTES;
GLuint texelBytes;
GLuint size;

texImage = tObj->Image[0][level + t->base.firstLevel];
if (!texImage)
return;

texelBytes = texImage->TexFormat->TexelBytes;

/* 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 */
WARN_ONCE
("DXT 3/5 suffers from multitexturing problems!\n");
// 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;
blitWidth = 64 / texelBytes;
} else if (t->tile_bits & R300_TXO_MICRO_TILE) {
/* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
though the actual offset may be different (if texture is less than
32 bytes width) to the untiled case */
int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
size =
(w * ((texImage->Height + 1) / 2)) *
texImage->Depth;
blitWidth = MAX2(texImage->Width, 64 / texelBytes);
} else {
int w = (texImage->Width * texelBytes + 31) & ~31;
size = w * texImage->Height * texImage->Depth;
blitWidth = MAX2(texImage->Width, 64 / texelBytes);
}
assert(size > 0);

if (RADEON_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n",
texImage->Width, texImage->Height,
texImage->Depth,
texImage->TexFormat->TexelBytes,
texImage->InternalFormat);

/* All images are aligned to a 32-byte offset */
*curOffset = (*curOffset + 0x1f) & ~0x1f;

if (texelBytes) {
/* fix x and y coords up later together with offset */
t->image[face][level].x = *curOffset;
t->image[face][level].y = 0;
t->image[face][level].width =
MIN2(size / texelBytes, blitWidth);
t->image[face][level].height =
(size / texelBytes) / t->image[face][level].width;
} else {
t->image[face][level].x = *curOffset % R300_BLIT_WIDTH_BYTES;
t->image[face][level].y = *curOffset / R300_BLIT_WIDTH_BYTES;
t->image[face][level].width =
MIN2(size, R300_BLIT_WIDTH_BYTES);
t->image[face][level].height = size / t->image[face][level].width;
}

if (RADEON_DEBUG & DEBUG_TEXTURE)
fprintf(stderr,
"level %d, face %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
level, face, texImage->Width, texImage->Height,
t->image[face][level].x, t->image[face][level].y,
t->image[face][level].width, t->image[face][level].height,
size, *curOffset);

*curOffset += size;
}



/**
* This function computes the number of bytes of storage needed for
* the given texture object (all mipmap levels, all cube faces).
@@ -206,7 +312,7 @@ static void r300SetTexImages(r300ContextPtr rmesa,
r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
const struct gl_texture_image *baseImage =
tObj->Image[0][tObj->BaseLevel];
GLint curOffset, blitWidth;
GLint curOffset;
GLint i, texelBytes;
GLint numLevels;
GLint log2Width, log2Height, log2Depth;
@@ -245,8 +351,6 @@ static void r300SetTexImages(r300ContextPtr rmesa,
* The idea is that we lay out the mipmap levels within a block of
* memory organized as a rectangle of width BLIT_WIDTH_BYTES.
*/
curOffset = 0;
blitWidth = R300_BLIT_WIDTH_BYTES;
t->tile_bits = 0;

/* figure out if this texture is suitable for tiling. */
@@ -276,94 +380,20 @@ static void r300SetTexImages(r300ContextPtr rmesa,
}
#endif

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) {
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 */
WARN_ONCE
("DXT 3/5 suffers from multitexturing problems!\n");
// 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;
blitWidth = 64 / texelBytes;
} else if (t->tile_bits & R300_TXO_MICRO_TILE) {
/* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
though the actual offset may be different (if texture is less than
32 bytes width) to the untiled case */
int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
size =
(w * ((texImage->Height + 1) / 2)) *
texImage->Depth;
blitWidth = MAX2(texImage->Width, 64 / texelBytes);
} else {
int w = (texImage->Width * texelBytes + 31) & ~31;
size = w * texImage->Height * texImage->Depth;
blitWidth = MAX2(texImage->Width, 64 / texelBytes);
}
assert(size > 0);

if (RADEON_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n",
texImage->Width, texImage->Height,
texImage->Depth,
texImage->TexFormat->TexelBytes,
texImage->InternalFormat);

/* Align to 32-byte offset. It is faster to do this unconditionally
* (no branch penalty).
*/
curOffset = 0;

curOffset = (curOffset + 0x1f) & ~0x1f;
if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
ASSERT(log2Width == log2Height);
t->format |= R300_TX_FORMAT_CUBIC_MAP;

if (texelBytes) {
/* fix x and y coords up later together with offset */
t->image[0][i].x = curOffset;
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 % R300_BLIT_WIDTH_BYTES;
t->image[0][i].y = curOffset / R300_BLIT_WIDTH_BYTES;
t->image[0][i].width =
MIN2(size, R300_BLIT_WIDTH_BYTES);
t->image[0][i].height = size / t->image[0][i].width;
for(i = 0; i < numLevels; i++) {
GLuint face;
for(face = 0; face < 6; face++)
compute_tex_image_offset(tObj, face, i, &curOffset);
}

if (RADEON_DEBUG & DEBUG_TEXTURE)
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;
} else {
for (i = 0; i < numLevels; i++)
compute_tex_image_offset(tObj, 0, i, &curOffset);
}

/* Align the total size of texture memory block.
@@ -371,26 +401,6 @@ static void r300SetTexImages(r300ContextPtr rmesa,
t->base.totalSize =
(curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;

/* Setup remaining cube face blits, if needed */
if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
GLuint face;
for (face = 1; face < 6; face++) {
for (i = 0; i < numLevels; i++) {
t->image[face][i].x = t->image[0][i].x;
t->image[face][i].y = t->image[0][i].y;
t->image[face][i].width = t->image[0][i].width;
t->image[face][i].height =
t->image[0][i].height;
}
}
t->base.totalSize *= 6; /* total texmem needed */
}

if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
ASSERT(log2Width == log2Height);
t->format |= R300_TX_FORMAT_CUBIC_MAP;
}

t->size =
(((tObj->Image[0][t->base.firstLevel]->Width -
1) << R300_TX_WIDTHMASK_SHIFT)
@@ -408,7 +418,7 @@ static void r300SetTexImages(r300ContextPtr rmesa,
t->pitch |=
(tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
} else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
unsigned int align = blitWidth - 1;
unsigned int align = (64 / texelBytes) - 1;
t->pitch |= ((tObj->Image[0][t->base.firstLevel]->Width *
texelBytes) + 63) & ~(63);
t->size |= R300_TX_SIZE_TXPITCH_EN;

Loading…
取消
儲存