From: Dave Airlie Date: Fri, 13 Feb 2009 12:49:06 +0000 (+1000) Subject: radeon: fix compressed texture upload on all radeons X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9fd8da299b4a62c6baf49f08067d7c1ddebb0ffd;p=mesa.git radeon: fix compressed texture upload on all radeons tested on r200, texcmp works. May need more verification --- diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c index c21d297b22c..45c1d71be59 100644 --- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c +++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c @@ -56,6 +56,29 @@ static GLuint radeon_compressed_texture_size(GLcontext *ctx, return size; } + +static int radeon_compressed_num_bytes(GLuint mesaFormat) +{ + int bytes = 0; + switch(mesaFormat) { + + case MESA_FORMAT_RGB_FXT1: + case MESA_FORMAT_RGBA_FXT1: + case MESA_FORMAT_RGB_DXT1: + case MESA_FORMAT_RGBA_DXT1: + bytes = 2; + break; + + case MESA_FORMAT_RGBA_DXT3: + case MESA_FORMAT_RGBA_DXT5: + bytes = 4; + default: + break; + } + + return bytes; +} + /** * Compute sizes and fill in offset and blit information for the given * image (determined by \p face and \p level). @@ -73,18 +96,14 @@ static void compute_tex_image_offset(radeon_mipmap_tree *mt, /* TODO: Is this correct? Need test cases for compressed textures! */ GLuint align; - if (mt->target == GL_TEXTURE_RECTANGLE_NV) - align = 64 / mt->bpp; - else - align = 32 / mt->bpp; - lvl->rowstride = (lvl->width + align - 1) & ~(align - 1); + lvl->rowstride = (lvl->width * mt->bpp + 63) & ~63; lvl->size = radeon_compressed_texture_size(mt->radeon->glCtx, - lvl->width, lvl->height, lvl->depth, mt->compressed); + lvl->width, lvl->height, lvl->depth, mt->compressed); } else if (mt->target == GL_TEXTURE_RECTANGLE_NV) { lvl->rowstride = (lvl->width * mt->bpp + 63) & ~63; lvl->size = lvl->rowstride * lvl->height; } else if (mt->tilebits & RADEON_TXO_MICRO_TILE) { - /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned, + /* 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 */ lvl->rowstride = (lvl->width * mt->bpp * 2 + 31) & ~31; @@ -160,7 +179,7 @@ radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj * mt->width0 = width0; mt->height0 = height0; mt->depth0 = depth0; - mt->bpp = bpp; + mt->bpp = compressed ? radeon_compressed_num_bytes(compressed) : bpp; mt->tilebits = tilebits; mt->compressed = compressed; @@ -255,7 +274,12 @@ GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt, if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel) return GL_FALSE; - if (texImage->TexFormat->TexelBytes != mt->bpp) + if (texImage->IsCompressed != mt->compressed) + return GL_FALSE; + + if (!texImage->IsCompressed && + !mt->compressed && + texImage->TexFormat->TexelBytes != mt->bpp) return GL_FALSE; lvl = &mt->levels[level - mt->firstLevel]; diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c index beb21e7b431..eb87a0dac5d 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texture.c +++ b/src/mesa/drivers/dri/radeon/radeon_texture.c @@ -32,6 +32,7 @@ #include "main/imports.h" #include "main/context.h" #include "main/mipmap.h" +#include "main/texcompress.h" #include "main/texformat.h" #include "main/texstore.h" #include "main/teximage.h" @@ -453,16 +454,26 @@ static void radeon_teximage( radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObj* t = radeon_tex_obj(texObj); radeon_texture_image* image = get_radeon_texture_image(texImage); + GLuint dstRowStride; + GLint postConvWidth = width; + GLint postConvHeight = height; + GLuint texelBytes; radeon_firevertices(rmesa); t->validated = GL_FALSE; + if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { + _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, + &postConvHeight); + } + /* Choose and fill in the texture format for this image */ texImage->TexFormat = radeonChooseTextureFormat(ctx, internalFormat, format, type); _mesa_set_fetch_functions(texImage, dims); if (texImage->TexFormat->TexelBytes == 0) { + texelBytes = 0; texImage->IsCompressed = GL_TRUE; texImage->CompressedSize = ctx->Driver.CompressedTextureSize(ctx, texImage->Width, @@ -471,6 +482,16 @@ static void radeon_teximage( } else { texImage->IsCompressed = GL_FALSE; texImage->CompressedSize = 0; + + texelBytes = texImage->TexFormat->TexelBytes; + /* Minimum pitch of 32 bytes */ + if (postConvWidth * texelBytes < 32) { + postConvWidth = 32 / texelBytes; + texImage->RowStride = postConvWidth; + } + if (!image->mt) { + assert(texImage->RowStride == postConvWidth); + } } /* Allocate memory for image */ @@ -479,16 +500,22 @@ static void radeon_teximage( if (!t->mt) radeon_try_alloc_miptree(rmesa, t, texImage, face, level); if (t->mt && radeon_miptree_matches_image(t->mt, texImage, face, level)) { + radeon_mipmap_level *lvl; image->mt = t->mt; image->mtlevel = level - t->mt->firstLevel; image->mtface = face; radeon_miptree_reference(t->mt); + lvl = &image->mt->levels[image->mtlevel]; + dstRowStride = lvl->rowstride; } else { int size; if (texImage->IsCompressed) { size = texImage->CompressedSize; + dstRowStride = + _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); } else { size = texImage->Width * texImage->Height * texImage->Depth * texImage->TexFormat->TexelBytes; + dstRowStride = postConvWidth * texelBytes; } texImage->Data = _mesa_alloc_texmemory(size); } @@ -509,13 +536,6 @@ static void radeon_teximage( if (compressed) { memcpy(texImage->Data, pixels, imageSize); } else { - GLuint dstRowStride; - if (image->mt) { - radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel]; - dstRowStride = lvl->rowstride; - } else { - dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes; - } if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, texImage->TexFormat, @@ -534,11 +554,11 @@ static void radeon_teximage( radeon_generate_mipmap(ctx, texObj->Target, texObj); } - if (pixels) - radeon_teximage_unmap(image); - _mesa_unmap_teximage_pbo(ctx, packing); + if (pixels) + radeon_teximage_unmap(image); + } @@ -579,7 +599,7 @@ void radeonCompressedTexImage2D(GLcontext * ctx, GLenum target, GLuint face = radeon_face_for_target(target); radeon_teximage(ctx, 2, face, level, internalFormat, width, height, 1, - imageSize, 0, 0, data, 0, texObj, texImage, 1); + imageSize, 0, 0, data, &ctx->Unpack, texObj, texImage, 1); } void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level, @@ -760,13 +780,22 @@ static void migrate_image_to_miptree(radeon_mipmap_tree *mt, radeon_texture_imag radeon_miptree_unreference(image->mt); } else { - uint srcrowstride = image->base.Width * image->base.TexFormat->TexelBytes; + uint32_t srcrowstride; + uint32_t height; + /* need to confirm this value is correct */ + if (mt->compressed) { + height = image->base.Height / 4; + srcrowstride = image->base.RowStride * mt->bpp; + } else { + height = image->base.Height * image->base.Depth; + srcrowstride = image->base.Width * image->base.TexFormat->TexelBytes; + } // if (mt->tilebits) // WARN_ONCE("%s: tiling not supported yet", __FUNCTION__); copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride, - image->base.Height * image->base.Depth, srcrowstride); + height, srcrowstride); _mesa_free_texmemory(image->base.Data); image->base.Data = 0;