From fa1bc0d7d600b25ec1b9fce157a8c8ddc6723564 Mon Sep 17 00:00:00 2001 From: Nicolai Haehnle Date: Fri, 6 Jun 2008 23:47:46 +0200 Subject: 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. --- src/mesa/drivers/dri/r300/r300_texmem.c | 2 +- src/mesa/drivers/dri/r300/r300_texstate.c | 228 ++++++++++++++++-------------- 2 files changed, 120 insertions(+), 110 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/drivers/dri/r300/r300_texmem.c b/src/mesa/drivers/dri/r300/r300_texmem.c index e0fda86ac8..69847a4022 100644 --- a/src/mesa/drivers/dri/r300/r300_texmem.c +++ b/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; diff --git a/src/mesa/drivers/dri/r300/r300_texstate.c b/src/mesa/drivers/dri/r300/r300_texstate.c index 131d958005..2589ec572e 100644 --- a/src/mesa/drivers/dri/r300/r300_texstate.c +++ b/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; -- cgit v1.2.3