mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-01 03:48:06 +02:00
mesa: Switch generate_mipmaps_compressed() to using TexImage2D to upload.
The code was playing fast and loose with rowstrides, which meant that if a driver chose anything different for its alignment requirements, the generated mipmaps came out garbage. Unlike the uncompressed case, we can't generate mipmaps directly into image->Data, so by using TexImage2D we cut out most of the weird logic that existed to generate in-place into ->Data. The up/downside is that the driver recovery code for the fact that _mesa_generate_mipmaps whacked ->Data has to be turned off for compressed now. Fixes 6 piglit tests about compressed mipmap gen.
This commit is contained in:
parent
b0c4db68b2
commit
10e418f381
4 changed files with 52 additions and 69 deletions
|
|
@ -75,6 +75,7 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target,
|
|||
/* sw path: need to map texture images */
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_object *intelObj = intel_texture_object(texObj);
|
||||
struct gl_texture_image *first_image = texObj->Image[0][texObj->BaseLevel];
|
||||
|
||||
fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
|
||||
|
||||
|
|
@ -82,7 +83,7 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target,
|
|||
_mesa_generate_mipmap(ctx, target, texObj);
|
||||
intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel);
|
||||
|
||||
{
|
||||
if (!_mesa_is_format_compressed(first_image->TexFormat)) {
|
||||
GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
||||
GLuint face, i;
|
||||
/* Update the level information in our private data in the new images,
|
||||
|
|
|
|||
|
|
@ -688,8 +688,10 @@ nouveau_generate_mipmap(struct gl_context *ctx, GLenum target,
|
|||
_mesa_generate_mipmap(ctx, target, t);
|
||||
nouveau_teximage_unmap(ctx, base);
|
||||
|
||||
store_mipmap(ctx, target, t->BaseLevel + 1,
|
||||
get_last_level(t), t);
|
||||
if (!_mesa_is_format_compressed(base->TexFormat)) {
|
||||
store_mipmap(ctx, target, t->BaseLevel + 1,
|
||||
get_last_level(t), t);
|
||||
}
|
||||
|
||||
} else {
|
||||
_mesa_meta_GenerateMipmap(ctx, target, t);
|
||||
|
|
|
|||
|
|
@ -249,6 +249,7 @@ static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target,
|
|||
radeonTexObj* t = radeon_tex_obj(texObj);
|
||||
GLuint nr_faces = (t->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
||||
int i, face;
|
||||
struct gl_texture_image *first_image;
|
||||
|
||||
radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
|
||||
"%s(%p, tex %p) Target type %s.\n",
|
||||
|
|
@ -257,6 +258,13 @@ static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target,
|
|||
|
||||
_mesa_generate_mipmap(ctx, target, texObj);
|
||||
|
||||
/* For the compressed case, we don't need to do the
|
||||
* non-TexImage recovery path below.
|
||||
*/
|
||||
first_image = texObj->Image[0][texObj->BaseLevel];
|
||||
if (_mesa_is_format_compressed(first_image->TexFormat))
|
||||
return;
|
||||
|
||||
for (face = 0; face < nr_faces; face++) {
|
||||
for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
|
||||
radeon_texture_image *image;
|
||||
|
|
|
|||
|
|
@ -1971,13 +1971,12 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
|
|||
{
|
||||
GLint level;
|
||||
gl_format temp_format;
|
||||
const GLubyte *srcData = NULL;
|
||||
GLubyte *dstData = NULL;
|
||||
GLenum datatype, temp_base_format;
|
||||
GLenum datatype;
|
||||
GLuint comps;
|
||||
GLuint row;
|
||||
GLint components, size;
|
||||
GLchan *dst;
|
||||
GLint components;
|
||||
GLuint temp_src_stride, temp_dst_stride; /* in bytes */
|
||||
GLchan *temp_src = NULL, *temp_dst = NULL;
|
||||
|
||||
/* Choose the format we will do _mesa_generate_mipmap_level() in,
|
||||
* and uncompress the firstImage into a temporary of that format.
|
||||
|
|
@ -2009,25 +2008,18 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
|
|||
}
|
||||
|
||||
/* allocate storage for uncompressed GL_RGB or GL_RGBA images */
|
||||
size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE)
|
||||
* srcImage->Width * srcImage->Height * srcImage->Depth + 20;
|
||||
temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width);
|
||||
/* 20 extra bytes, just be safe when calling last FetchTexel */
|
||||
srcData = (GLubyte *) malloc(size);
|
||||
if (!srcData) {
|
||||
temp_src = (GLubyte *) malloc(temp_src_stride * srcImage->Height + 20);
|
||||
if (!temp_src) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
|
||||
return;
|
||||
}
|
||||
dstData = (GLubyte *) malloc(size / 2); /* 1/4 would probably be OK */
|
||||
if (!dstData) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
|
||||
free((void *) srcData);
|
||||
return;
|
||||
}
|
||||
|
||||
/* decompress base image here */
|
||||
dst = (GLchan *) srcData;
|
||||
/* decompress base image to the temporary */
|
||||
for (row = 0; row < srcImage->Height; row++) {
|
||||
GLuint col;
|
||||
GLchan *dst = (GLchan *) temp_src + temp_src_stride * row;
|
||||
for (col = 0; col < srcImage->Width; col++) {
|
||||
srcImage->FetchTexelc(srcImage, col, row, 0, dst);
|
||||
dst += components;
|
||||
|
|
@ -2035,7 +2027,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
|
|||
}
|
||||
|
||||
_mesa_format_to_type_and_comps(temp_format, &datatype, &comps);
|
||||
temp_base_format = _mesa_get_format_base_format(temp_format);
|
||||
|
||||
for (level = texObj->BaseLevel; level < maxLevel; level++) {
|
||||
/* generate image[level+1] from image[level] */
|
||||
|
|
@ -2057,11 +2048,16 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
|
|||
nextLevel = next_mipmap_level_size(target, border,
|
||||
srcWidth, srcHeight, srcDepth,
|
||||
&dstWidth, &dstHeight, &dstDepth);
|
||||
if (!nextLevel) {
|
||||
/* all done */
|
||||
free((void *) srcData);
|
||||
free(dstData);
|
||||
return;
|
||||
if (!nextLevel)
|
||||
break;
|
||||
|
||||
temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth);
|
||||
if (!temp_dst) {
|
||||
temp_dst = (GLubyte *) malloc(temp_dst_stride * dstHeight);
|
||||
if (!temp_dst) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get dest gl_texture_image */
|
||||
|
|
@ -2071,60 +2067,36 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Free old image data */
|
||||
if (dstImage->Data)
|
||||
ctx->Driver.FreeTexImageData(ctx, dstImage);
|
||||
_mesa_generate_mipmap_level(target, datatype, comps, border,
|
||||
srcWidth, srcHeight, srcDepth,
|
||||
temp_src, temp_src_stride / components,
|
||||
dstWidth, dstHeight, dstDepth,
|
||||
temp_dst, temp_dst_stride / components);
|
||||
|
||||
/* initialize new image */
|
||||
_mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
|
||||
dstDepth, border, srcImage->InternalFormat,
|
||||
srcImage->TexFormat);
|
||||
dstImage->DriverData = NULL;
|
||||
dstImage->FetchTexelc = srcImage->FetchTexelc;
|
||||
dstImage->FetchTexelf = srcImage->FetchTexelf;
|
||||
|
||||
/* Alloc new teximage data buffer */
|
||||
{
|
||||
GLuint size = _mesa_format_image_size(dstImage->TexFormat,
|
||||
dstWidth, dstHeight, dstDepth);
|
||||
dstImage->Data = _mesa_alloc_texmemory(size);
|
||||
if (!dstImage->Data) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(dstImage->TexFormat);
|
||||
ASSERT(dstImage->FetchTexelc);
|
||||
ASSERT(dstImage->FetchTexelf);
|
||||
|
||||
_mesa_generate_mipmap_level(target, datatype, comps, border,
|
||||
srcWidth, srcHeight, srcDepth,
|
||||
srcData, srcImage->RowStride,
|
||||
dstWidth, dstHeight, dstDepth,
|
||||
dstData, dstImage->RowStride);
|
||||
|
||||
/* compress image from dstData into dstImage->Data */
|
||||
_mesa_texstore(ctx, 2, dstImage->_BaseFormat,
|
||||
dstImage->TexFormat,
|
||||
dstImage->Data,
|
||||
0, 0, 0, /* dstX/Y/Zoffset */
|
||||
_mesa_format_row_stride(dstImage->TexFormat, dstWidth),
|
||||
NULL,
|
||||
dstWidth, dstHeight, 1, /* size */
|
||||
temp_base_format, CHAN_TYPE,
|
||||
dstData, /* src data, actually */
|
||||
&ctx->DefaultPacking);
|
||||
ctx->Driver.TexImage2D(ctx, target, level + 1,
|
||||
srcImage->InternalFormat,
|
||||
dstWidth, dstHeight, border,
|
||||
_mesa_get_format_base_format(temp_format),
|
||||
GL_UNSIGNED_BYTE,
|
||||
temp_dst, &ctx->DefaultPacking, texObj, dstImage);
|
||||
|
||||
/* swap src and dest pointers */
|
||||
{
|
||||
GLubyte *temp;
|
||||
temp = (GLubyte *) srcData;
|
||||
srcData = dstData;
|
||||
dstData = temp;
|
||||
}
|
||||
GLchan *temp = temp_src;
|
||||
temp_src = temp_dst;
|
||||
temp_dst = temp;
|
||||
|
||||
temp_src_stride = temp_dst_stride;
|
||||
}
|
||||
} /* loop over mipmap levels */
|
||||
|
||||
free((void *) temp_src);
|
||||
free(temp_dst);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue