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).
/* 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;
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;
}
+/**
+ * Calculate first and last mip levels for the given texture object,
+ * where the dimensions are taken from the given texture image at
+ * the given level.
+ *
+ * Note: level is the OpenGL level number, which is not necessarily the same
+ * as the first level that is actually present.
+ *
+ * The base level image of the given texture face must be non-null,
+ * or this will fail.
+ */
static void calculate_first_last_level(struct gl_texture_object *tObj,
- GLuint *pfirstLevel, GLuint *plastLevel)
+ GLuint *pfirstLevel, GLuint *plastLevel,
+ GLuint face, GLuint level)
{
const struct gl_texture_image * const baseImage =
- tObj->Image[0][tObj->BaseLevel];
+ tObj->Image[face][level];
+ assert(baseImage);
+
/* These must be signed values. MinLod and MaxLod can be negative numbers,
* and having firstLevel and lastLevel as signed prevents the need for
* extra sign checks.
} else {
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
- firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ firstLevel = MIN2(firstLevel, level + baseImage->MaxLog2);
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
- lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, level + baseImage->MaxLog2);
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
}
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];
GLuint numfaces = 1;
GLuint firstLevel, lastLevel;
- calculate_first_last_level(texObj, &firstLevel, &lastLevel);
+ calculate_first_last_level(texObj, &firstLevel, &lastLevel, 0, texObj->BaseLevel);
if (texObj->Target == GL_TEXTURE_CUBE_MAP)
numfaces = 6;
assert(!t->mt);
- calculate_first_last_level(&t->base, &firstLevel, &lastLevel);
+ calculate_first_last_level(&t->base, &firstLevel, &lastLevel, face, level);
if (t->base.Target == GL_TEXTURE_CUBE_MAP)
numfaces = 6;
texImage->Width, texImage->Height, texImage->Depth,
texImage->TexFormat->TexelBytes, t->tile_bits, compressed);
}
+
+/* Although we use the image_offset[] array to store relative offsets
+ * to cube faces, Mesa doesn't know anything about this and expects
+ * each cube face to be treated as a separate image.
+ *
+ * These functions present that view to mesa:
+ */
+const GLuint *
+radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level)
+{
+ static const GLuint zero = 0;
+ if (mt->target != GL_TEXTURE_3D || mt->faces == 1)
+ return &zero;
+ else
+ return mt->levels[level].faces[0].offset;
+}
+
+GLuint
+radeon_miptree_image_offset(radeon_mipmap_tree *mt,
+ GLuint face, GLuint level)
+{
+ if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
+ return (mt->levels[level].faces[face].offset);
+ else
+ return mt->levels[level].faces[0].offset;
+}