浏览代码

mesa: Convert _mesa_generate_mipmap to MapTexImage()-based access.

Now that we can zero-copy generate the mipmaps into brand new
glTexImage()-generated storage using MapTextureImage(), we no longer
need to allocate image->Data in mipmap generate.  This requires
deleting the drivers' old overrides of the miptree tracking after
calling _mesa_generate_mipmap at the same time, or the drivers
promptly lose our newly-generated data.

Reviewed-by: Eric Anholt <eric@anholt.net>
tags/mesa-8.0-rc1
Brian Paul 14 年前
父节点
当前提交
e0304180c3

+ 1
- 29
src/mesa/drivers/dri/intel/intel_tex.c 查看文件

@@ -163,37 +163,9 @@ intelGenerateMipmap(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj)
{
if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
/* 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__);

if (_mesa_is_format_compressed(first_image->TexFormat)) {
_mesa_generate_mipmap(ctx, target, texObj);
} else {
intel_tex_map_level_images(intel, intelObj, texObj->BaseLevel);
_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;
for (face = 0; face < nr_faces; face++) {
for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(texObj->Image[face][i]);
if (!intelImage)
break;
/* Unreference the miptree to signal that the new Data is a
* bare pointer from mesa.
*/
intel_miptree_release(&intelImage->mt);
}
}
}
_mesa_generate_mipmap(ctx, target, texObj);
}
else {
_mesa_meta_GenerateMipmap(ctx, target, texObj);

+ 0
- 10
src/mesa/drivers/dri/nouveau/nouveau_texture.c 查看文件

@@ -739,17 +739,7 @@ nouveau_generate_mipmap(struct gl_context *ctx, GLenum target,
{
if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, t)) {
struct gl_texture_image *base = t->Image[0][t->BaseLevel];

nouveau_teximage_map(ctx, base, GL_MAP_READ_BIT,
0, 0, base->Width, base->Height);
_mesa_generate_mipmap(ctx, target, t);
nouveau_teximage_unmap(ctx, base);

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);
}

+ 1
- 49
src/mesa/drivers/dri/radeon/radeon_texture.c 查看文件

@@ -324,52 +324,6 @@ radeon_unmap_texture_image(struct gl_context *ctx,
radeon_bo_unmap(image->mt->bo);
}

/**
* Wraps Mesa's implementation to ensure that the base level image is mapped.
*
* This relies on internal details of _mesa_generate_mipmap, in particular
* the fact that the memory for recreated texture images is always freed.
*/
static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj)
{
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",
__func__, ctx, texObj,
_mesa_lookup_enum_by_nr(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;

image = get_radeon_texture_image(texObj->Image[face][i]);

if (image == NULL)
break;

image->mtlevel = i;
image->mtface = face;

radeon_miptree_unreference(&image->mt);
}
}
}

void radeonGenerateMipmap(struct gl_context* ctx, GLenum target, struct gl_texture_object *texObj)
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
@@ -392,9 +346,7 @@ void radeonGenerateMipmap(struct gl_context* ctx, GLenum target, struct gl_textu
}

if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
radeon_teximage_map(baseimage, GL_FALSE);
radeon_generate_mipmap(ctx, target, texObj);
radeon_teximage_unmap(baseimage);
_mesa_generate_mipmap(ctx, target, texObj);
} else {
_mesa_meta_GenerateMipmap(ctx, target, texObj);
}

+ 148
- 122
src/mesa/main/mipmap.c 查看文件

@@ -1414,8 +1414,6 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
const GLint dstWidthNB = dstWidth - 2 * border;
const GLint dstHeightNB = dstHeight - 2 * border;
const GLint srcRowBytes = bpt * srcRowStride;
const GLint dstRowBytes = bpt * dstRowStride;
const GLubyte *srcA, *srcB;
GLubyte *dst;
GLint row, srcRowStep;
@@ -1424,7 +1422,7 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
srcA = srcPtr + border * ((srcWidth + 1) * bpt);
if (srcHeight > 1 && srcHeight > dstHeight) {
/* sample from two source rows */
srcB = srcA + srcRowBytes;
srcB = srcA + srcRowStride;
srcRowStep = 2;
}
else {
@@ -1438,9 +1436,9 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
for (row = 0; row < dstHeightNB; row++) {
do_row(datatype, comps, srcWidthNB, srcA, srcB,
dstWidthNB, dst);
srcA += srcRowStep * srcRowBytes;
srcB += srcRowStep * srcRowBytes;
dst += dstRowBytes;
srcA += srcRowStep * srcRowStride;
srcB += srcRowStep * srcRowStride;
dst += dstRowStride;
}

/* This is ugly but probably won't be used much */
@@ -1500,9 +1498,9 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
static void
make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
GLint srcWidth, GLint srcHeight, GLint srcDepth,
const GLubyte *srcPtr, GLint srcRowStride,
const GLubyte **srcPtr, GLint srcRowStride,
GLint dstWidth, GLint dstHeight, GLint dstDepth,
GLubyte *dstPtr, GLint dstRowStride)
GLubyte **dstPtr, GLint dstRowStride)
{
const GLint bpt = bytes_per_pixel(datatype, comps);
const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
@@ -1525,7 +1523,7 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
bytesPerDstRow = dstWidth * bpt;

/* Offset between adjacent src images to be averaged together */
srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
srcImageOffset = (srcDepth == dstDepth) ? 0 : 1;

/* Offset between adjacent src rows to be averaged together */
srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
@@ -1545,15 +1543,15 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,

for (img = 0; img < dstDepthNB; img++) {
/* first source image pointer, skipping border */
const GLubyte *imgSrcA = srcPtr
+ (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
+ img * (bytesPerSrcImage + srcImageOffset);
const GLubyte *imgSrcA = srcPtr[img * 2 + border]
+ bytesPerSrcRow * border + bpt * border;
/* second source image pointer, skipping border */
const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
const GLubyte *imgSrcB = srcPtr[img * 2 + srcImageOffset + border]
+ bytesPerSrcRow * border + bpt * border;

/* address of the dest image, skipping border */
GLubyte *imgDst = dstPtr
+ (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
+ img * bytesPerDstImage;
GLubyte *imgDst = dstPtr[img + border]
+ bytesPerDstRow * border + bpt * border;

/* setup the four source row pointers and the dest row pointer */
const GLubyte *srcImgARowA = imgSrcA;
@@ -1581,13 +1579,14 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
/* Luckily we can leverage the make_2d_mipmap() function here! */
if (border > 0) {
/* do front border image */
make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride,
dstWidth, dstHeight, dstPtr, dstRowStride);
make_2d_mipmap(datatype, comps, 1,
srcWidth, srcHeight, srcPtr[0], srcRowStride,
dstWidth, dstHeight, dstPtr[0], dstRowStride);
/* do back border image */
make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight,
srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride,
dstWidth, dstHeight,
dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride);
make_2d_mipmap(datatype, comps, 1,
srcWidth, srcHeight, srcPtr[srcDepth - 1], srcRowStride,
dstWidth, dstHeight, dstPtr[dstDepth - 1], dstRowStride);
/* do four remaining border edges that span the image slices */
if (srcDepth == dstDepth) {
/* just copy border pixels from src to dst */
@@ -1596,29 +1595,23 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
GLubyte *dst;

/* do border along [img][row=0][col=0] */
src = srcPtr + (img + 1) * bytesPerSrcImage;
dst = dstPtr + (img + 1) * bytesPerDstImage;
src = srcPtr[img * 2];
dst = dstPtr[img];
memcpy(dst, src, bpt);

/* do border along [img][row=dstHeight-1][col=0] */
src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ (srcHeight - 1) * bytesPerSrcRow;
dst = dstPtr + (img + 1) * bytesPerDstImage
+ (dstHeight - 1) * bytesPerDstRow;
src = srcPtr[img * 2] + (srcHeight - 1) * bytesPerSrcRow;
dst = dstPtr[img] + (dstHeight - 1) * bytesPerDstRow;
memcpy(dst, src, bpt);

/* do border along [img][row=0][col=dstWidth-1] */
src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ (srcWidth - 1) * bpt;
dst = dstPtr + (img + 1) * bytesPerDstImage
+ (dstWidth - 1) * bpt;
src = srcPtr[img * 2] + (srcWidth - 1) * bpt;
dst = dstPtr[img] + (dstWidth - 1) * bpt;
memcpy(dst, src, bpt);

/* do border along [img][row=dstHeight-1][col=dstWidth-1] */
src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ (bytesPerSrcImage - bpt);
dst = dstPtr + (img + 1) * bytesPerDstImage
+ (bytesPerDstImage - bpt);
src = srcPtr[img * 2] + (bytesPerSrcImage - bpt);
dst = dstPtr[img] + (bytesPerDstImage - bpt);
memcpy(dst, src, bpt);
}
}
@@ -1626,34 +1619,34 @@ make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
/* average border pixels from adjacent src image pairs */
ASSERT(srcDepthNB == 2 * dstDepthNB);
for (img = 0; img < dstDepthNB; img++) {
const GLubyte *src;
const GLubyte *srcA, *srcB;
GLubyte *dst;

/* do border along [img][row=0][col=0] */
src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
dst = dstPtr + (img + 1) * bytesPerDstImage;
do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
srcA = srcPtr[img * 2 + 0];
srcB = srcPtr[img * 2 + srcImageOffset];
dst = dstPtr[img];
do_row(datatype, comps, 1, srcA, srcB, 1, dst);

/* do border along [img][row=dstHeight-1][col=0] */
src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ (srcHeight - 1) * bytesPerSrcRow;
dst = dstPtr + (img + 1) * bytesPerDstImage
+ (dstHeight - 1) * bytesPerDstRow;
do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
srcA = srcPtr[img * 2 + 0]
+ (srcHeight - 1) * bytesPerSrcRow;
srcB = srcPtr[img * 2 + srcImageOffset]
+ (srcHeight - 1) * bytesPerSrcRow;
dst = dstPtr[img] + (dstHeight - 1) * bytesPerDstRow;
do_row(datatype, comps, 1, srcA, srcB, 1, dst);

/* do border along [img][row=0][col=dstWidth-1] */
src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ (srcWidth - 1) * bpt;
dst = dstPtr + (img + 1) * bytesPerDstImage
+ (dstWidth - 1) * bpt;
do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
srcA = srcPtr[img * 2 + 0] + (srcWidth - 1) * bpt;
srcB = srcPtr[img * 2 + srcImageOffset] + (srcWidth - 1) * bpt;
dst = dstPtr[img] + (dstWidth - 1) * bpt;
do_row(datatype, comps, 1, srcA, srcB, 1, dst);

/* do border along [img][row=dstHeight-1][col=dstWidth-1] */
src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ (bytesPerSrcImage - bpt);
dst = dstPtr + (img + 1) * bytesPerDstImage
+ (bytesPerDstImage - bpt);
do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
srcA = srcPtr[img * 2 + 0] + (bytesPerSrcImage - bpt);
srcB = srcPtr[img * 2 + srcImageOffset] + (bytesPerSrcImage - bpt);
dst = dstPtr[img] + (bytesPerDstImage - bpt);
do_row(datatype, comps, 1, srcA, srcB, 1, dst);
}
}
}
@@ -1670,8 +1663,6 @@ make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
const GLint dstWidthNB = dstWidth - 2 * border;
const GLint dstHeightNB = dstHeight - 2 * border;
const GLint srcRowBytes = bpt * srcRowStride;
const GLint dstRowBytes = bpt * dstRowStride;
const GLubyte *src;
GLubyte *dst;
GLint row;
@@ -1683,8 +1674,8 @@ make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
for (row = 0; row < dstHeightNB; row++) {
do_row(datatype, comps, srcWidthNB, src, src,
dstWidthNB, dst);
src += srcRowBytes;
dst += dstRowBytes;
src += srcRowStride;
dst += dstRowStride;
}

if (border) {
@@ -1708,87 +1699,86 @@ make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
static void
make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
GLint srcWidth, GLint srcHeight,
const GLubyte *srcPtr, GLint srcRowStride,
const GLubyte **srcPtr, GLint srcRowStride,
GLint dstWidth, GLint dstHeight, GLint dstDepth,
GLubyte *dstPtr, GLint dstRowStride)
GLubyte **dstPtr, GLint dstRowStride)
{
const GLint bpt = bytes_per_pixel(datatype, comps);
const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
const GLint dstWidthNB = dstWidth - 2 * border;
const GLint dstHeightNB = dstHeight - 2 * border;
const GLint dstDepthNB = dstDepth - 2 * border;
const GLint srcRowBytes = bpt * srcRowStride;
const GLint dstRowBytes = bpt * dstRowStride;
const GLubyte *srcA, *srcB;
GLubyte *dst;
GLint layer;
GLint row;

/* Compute src and dst pointers, skipping any border */
srcA = srcPtr + border * ((srcWidth + 1) * bpt);
if (srcHeight > 1)
srcB = srcA + srcRowBytes;
else
srcB = srcA;
dst = dstPtr + border * ((dstWidth + 1) * bpt);

for (layer = 0; layer < dstDepthNB; layer++) {

/* Compute src and dst pointers, skipping any border */
srcA = srcPtr[layer] + border * (srcWidth + 1) * bpt;
if (srcHeight > 1)
srcB = srcA + srcRowStride;
else
srcB = srcA;
dst = dstPtr[layer] + border * (dstWidth + 1) * bpt;

for (row = 0; row < dstHeightNB; row++) {
do_row(datatype, comps, srcWidthNB, srcA, srcB,
dstWidthNB, dst);
srcA += 2 * srcRowBytes;
srcB += 2 * srcRowBytes;
dst += dstRowBytes;
srcA += 2 * srcRowStride;
srcB += 2 * srcRowStride;
dst += dstRowStride;
}

/* This is ugly but probably won't be used much */
if (border > 0) {
/* fill in dest border */
/* lower-left border pixel */
assert(dstPtr);
assert(srcPtr);
memcpy(dstPtr, srcPtr, bpt);
assert(dstPtr[layer]);
assert(srcPtr[layer]);
memcpy(dstPtr[layer], srcPtr[0], bpt);
/* lower-right border pixel */
memcpy(dstPtr + (dstWidth - 1) * bpt,
srcPtr + (srcWidth - 1) * bpt, bpt);
memcpy(dstPtr[layer] + (dstWidth - 1) * bpt,
srcPtr[layer] + (srcWidth - 1) * bpt, bpt);
/* upper-left border pixel */
memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt,
srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
memcpy(dstPtr[layer] + dstWidth * (dstHeight - 1) * bpt,
srcPtr[layer] + srcWidth * (srcHeight - 1) * bpt, bpt);
/* upper-right border pixel */
memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt,
srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
memcpy(dstPtr[layer] + (dstWidth * dstHeight - 1) * bpt,
srcPtr[layer] + (srcWidth * srcHeight - 1) * bpt, bpt);
/* lower border */
do_row(datatype, comps, srcWidthNB,
srcPtr + bpt,
srcPtr + bpt,
dstWidthNB, dstPtr + bpt);
srcPtr[layer] + bpt,
srcPtr[layer] + bpt,
dstWidthNB, dstPtr[layer] + bpt);
/* upper border */
do_row(datatype, comps, srcWidthNB,
srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
srcPtr[layer] + (srcWidth * (srcHeight - 1) + 1) * bpt,
srcPtr[layer] + (srcWidth * (srcHeight - 1) + 1) * bpt,
dstWidthNB,
dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
dstPtr[layer] + (dstWidth * (dstHeight - 1) + 1) * bpt);
/* left and right borders */
if (srcHeight == dstHeight) {
/* copy border pixel from src to dst */
for (row = 1; row < srcHeight; row++) {
memcpy(dstPtr + dstWidth * row * bpt,
srcPtr + srcWidth * row * bpt, bpt);
memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
memcpy(dstPtr[layer] + dstWidth * row * bpt,
srcPtr[layer] + srcWidth * row * bpt, bpt);
memcpy(dstPtr[layer] + (dstWidth * row + dstWidth - 1) * bpt,
srcPtr[layer] + (srcWidth * row + srcWidth - 1) * bpt, bpt);
}
}
else {
/* average two src pixels each dest pixel */
for (row = 0; row < dstHeightNB; row += 2) {
do_row(datatype, comps, 1,
srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
1, dstPtr + (dstWidth * row + 1) * bpt);
srcPtr[layer] + (srcWidth * (row * 2 + 1)) * bpt,
srcPtr[layer] + (srcWidth * (row * 2 + 2)) * bpt,
1, dstPtr[layer] + (dstWidth * row + 1) * bpt);
do_row(datatype, comps, 1,
srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
srcPtr[layer] + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
srcPtr[layer] + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
1, dstPtr[layer] + (dstWidth * row + 1 + dstWidth - 1) * bpt);
}
}
}
@@ -1799,28 +1789,27 @@ make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
/**
* Down-sample a texture image to produce the next lower mipmap level.
* \param comps components per texel (1, 2, 3 or 4)
* \param srcRowStride stride between source rows, in texels
* \param dstRowStride stride between destination rows, in texels
* \param srcData array[slice] of pointers to source image slices
* \param dstData array[slice] of pointers to dest image slices
* \param srcRowStride stride between source rows, in bytes
* \param dstRowStride stride between destination rows, in bytes
*/
void
_mesa_generate_mipmap_level(GLenum target,
GLenum datatype, GLuint comps,
GLint border,
GLint srcWidth, GLint srcHeight, GLint srcDepth,
const GLubyte *srcData,
const GLubyte **srcData,
GLint srcRowStride,
GLint dstWidth, GLint dstHeight, GLint dstDepth,
GLubyte *dstData,
GLubyte **dstData,
GLint dstRowStride)
{
/*
* We use simple 2x2 averaging to compute the next mipmap level.
*/
switch (target) {
case GL_TEXTURE_1D:
make_1d_mipmap(datatype, comps, border,
srcWidth, srcData,
dstWidth, dstData);
srcWidth, srcData[0],
dstWidth, dstData[0]);
break;
case GL_TEXTURE_2D:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
@@ -1830,8 +1819,8 @@ _mesa_generate_mipmap_level(GLenum target,
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
make_2d_mipmap(datatype, comps, border,
srcWidth, srcHeight, srcData, srcRowStride,
dstWidth, dstHeight, dstData, dstRowStride);
srcWidth, srcHeight, srcData[0], srcRowStride,
dstWidth, dstHeight, dstData[0], dstRowStride);
break;
case GL_TEXTURE_3D:
make_3d_mipmap(datatype, comps, border,
@@ -1842,9 +1831,9 @@ _mesa_generate_mipmap_level(GLenum target,
break;
case GL_TEXTURE_1D_ARRAY_EXT:
make_1d_stack_mipmap(datatype, comps, border,
srcWidth, srcData, srcRowStride,
srcWidth, srcData[0], srcRowStride,
dstWidth, dstHeight,
dstData, dstRowStride);
dstData[0], dstRowStride);
break;
case GL_TEXTURE_2D_ARRAY_EXT:
make_2d_stack_mipmap(datatype, comps, border,
@@ -1857,7 +1846,7 @@ _mesa_generate_mipmap_level(GLenum target,
/* no mipmaps, do nothing */
break;
default:
_mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps");
_mesa_problem(NULL, "bad tex target in _mesa_generate_mipmaps");
return;
}
}
@@ -1919,12 +1908,14 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,

for (level = texObj->BaseLevel; level < maxLevel; level++) {
/* generate image[level+1] from image[level] */
const struct gl_texture_image *srcImage;
struct gl_texture_image *dstImage;
struct gl_texture_image *srcImage, *dstImage;
GLint srcRowStride, dstRowStride;
GLint srcWidth, srcHeight, srcDepth;
GLint dstWidth, dstHeight, dstDepth;
GLint border;
GLint slice;
GLboolean nextLevel;
GLubyte **srcMaps, **dstMaps;

/* get src image parameters */
srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
@@ -1950,7 +1941,6 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
/* Free old image data */
ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);

/* initialize new image */
_mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
dstDepth, border, srcImage->InternalFormat,
srcImage->TexFormat);
@@ -1967,15 +1957,47 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,

ASSERT(dstImage->TexFormat);

/* Map src texture image slices */
srcMaps = (GLubyte **) malloc(srcDepth * sizeof(GLubyte *));
for (slice = 0; slice < srcDepth; slice++) {
ctx->Driver.MapTextureImage(ctx, srcImage, slice,
0, 0, srcWidth, srcHeight,
GL_MAP_READ_BIT,
&srcMaps[slice], &srcRowStride);
}

/* Map dst texture image slices */
dstMaps = (GLubyte **) malloc(dstDepth * sizeof(GLubyte *));
for (slice = 0; slice < dstDepth; slice++) {
ctx->Driver.MapTextureImage(ctx, dstImage, slice,
0, 0, dstWidth, dstHeight,
GL_MAP_WRITE_BIT,
&dstMaps[slice], &dstRowStride);
}

/* generate one mipmap level (for 1D/2D/3D/array/etc texture) */
_mesa_generate_mipmap_level(target, datatype, comps, border,
srcWidth, srcHeight, srcDepth,
srcImage->Data, srcImage->RowStride,
(const GLubyte **) srcMaps, srcRowStride,
dstWidth, dstHeight, dstDepth,
dstImage->Data, dstImage->RowStride);
dstMaps, dstRowStride);

/* Unmap src image slices */
for (slice = 0; slice < srcDepth; slice++) {
ctx->Driver.UnmapTextureImage(ctx, srcImage, slice);
}
free(srcMaps);

/* Unmap src image slices */
for (slice = 0; slice < dstDepth; slice++) {
ctx->Driver.UnmapTextureImage(ctx, dstImage, slice);
}
free(dstMaps);

} /* loop over mipmap levels */
}


static void
generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj,
@@ -1985,7 +2007,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
GLint level;
gl_format temp_format;
GLint components;
GLuint temp_src_stride, temp_dst_stride; /* in bytes */
GLuint temp_src_stride; /* in bytes */
GLubyte *temp_src = NULL, *temp_dst = NULL;
GLenum temp_datatype;
GLenum temp_base_format;
@@ -2049,6 +2071,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
GLint dstWidth, dstHeight, dstDepth;
GLint border;
GLboolean nextLevel;
GLuint temp_dst_stride; /* in bytes */

/* get src image parameters */
srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
@@ -2085,15 +2108,19 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,

_mesa_generate_mipmap_level(target, temp_datatype, components, border,
srcWidth, srcHeight, srcDepth,
temp_src, temp_src_stride / components,
(const GLubyte **) &temp_src,
temp_src_stride,
dstWidth, dstHeight, dstDepth,
temp_dst, temp_dst_stride / components);
&temp_dst, temp_dst_stride);

/* initialize new image */
_mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
dstDepth, border, srcImage->InternalFormat,
srcImage->TexFormat);

/* Free old dest texture image buffer */
ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);

ctx->Driver.TexImage2D(ctx, target, level + 1,
srcImage->InternalFormat,
dstWidth, dstHeight, border,
@@ -2105,7 +2132,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
GLubyte *temp = temp_src;
temp_src = temp_dst;
temp_dst = temp;

temp_src_stride = temp_dst_stride;
}
} /* loop over mipmap levels */

+ 2
- 2
src/mesa/main/mipmap.h 查看文件

@@ -34,10 +34,10 @@ _mesa_generate_mipmap_level(GLenum target,
GLenum datatype, GLuint comps,
GLint border,
GLint srcWidth, GLint srcHeight, GLint srcDepth,
const GLubyte *srcData,
const GLubyte **srcData,
GLint srcRowStride,
GLint dstWidth, GLint dstHeight, GLint dstDepth,
GLubyte *dstData,
GLubyte **dstData,
GLint dstRowStride);



+ 1
- 204
src/mesa/state_tracker/st_gen_mipmap.c 查看文件

@@ -106,209 +106,6 @@ st_render_mipmap(struct st_context *st,
return TRUE;
}


/**
* Helper function to decompress an image. The result is a 32-bpp RGBA
* image with stride==width.
*/
static void
decompress_image(enum pipe_format format, int datatype,
const uint8_t *src, void *dst,
unsigned width, unsigned height, unsigned src_stride)
{
const struct util_format_description *desc = util_format_description(format);
const uint bw = util_format_get_blockwidth(format);
const uint bh = util_format_get_blockheight(format);
uint dst_stride = 4 * MAX2(width, bw);

if (datatype == GL_FLOAT) {
desc->unpack_rgba_float((float *)dst, dst_stride * sizeof(GLfloat), src, src_stride, width, height);
if (width < bw || height < bh) {
float *dst_p = (float *)dst;
/* We're decompressing an image smaller than the compression
* block size. We don't want garbage pixel values in the region
* outside (width x height) so replicate pixels from the (width
* x height) region to fill out the (bw x bh) block size.
*/
uint x, y;
for (y = 0; y < bh; y++) {
for (x = 0; x < bw; x++) {
if (x >= width || y >= height) {
uint p = (y * bw + x) * 4;
dst_p[p + 0] = dst_p[0];
dst_p[p + 1] = dst_p[1];
dst_p[p + 2] = dst_p[2];
dst_p[p + 3] = dst_p[3];
}
}
}
}
} else {
desc->unpack_rgba_8unorm((uint8_t *)dst, dst_stride, src, src_stride, width, height);
if (width < bw || height < bh) {
uint8_t *dst_p = (uint8_t *)dst;
/* We're decompressing an image smaller than the compression
* block size. We don't want garbage pixel values in the region
* outside (width x height) so replicate pixels from the (width
* x height) region to fill out the (bw x bh) block size.
*/
uint x, y;
for (y = 0; y < bh; y++) {
for (x = 0; x < bw; x++) {
if (x >= width || y >= height) {
uint p = (y * bw + x) * 4;
dst_p[p + 0] = dst_p[0];
dst_p[p + 1] = dst_p[1];
dst_p[p + 2] = dst_p[2];
dst_p[p + 3] = dst_p[3];
}
}
}
}
}
}

/**
* Helper function to compress an image. The source is a 32-bpp RGBA image
* with stride==width.
*/
static void
compress_image(enum pipe_format format, int datatype,
const void *src, uint8_t *dst,
unsigned width, unsigned height, unsigned dst_stride)
{
const struct util_format_description *desc = util_format_description(format);
const uint src_stride = 4 * width;

if (datatype == GL_FLOAT)
desc->pack_rgba_float(dst, dst_stride, (GLfloat *)src, src_stride * sizeof(GLfloat), width, height);
else
desc->pack_rgba_8unorm(dst, dst_stride, (uint8_t *)src, src_stride, width, height);
}


/**
* Software fallback for generate mipmap levels.
*/
static void
fallback_generate_mipmap(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct pipe_resource *pt = st_get_texobj_resource(texObj);
const uint baseLevel = texObj->BaseLevel;
const uint lastLevel = pt->last_level;
const uint face = _mesa_tex_target_to_face(target);
uint dstLevel;
GLenum datatype;
GLuint comps;
GLboolean compressed;

if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);

assert(target != GL_TEXTURE_3D); /* not done yet */

compressed =
_mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat);

if (compressed) {
GLenum type =
_mesa_get_format_datatype(texObj->Image[face][baseLevel]->TexFormat);

datatype = type == GL_UNSIGNED_NORMALIZED ? GL_UNSIGNED_BYTE : GL_FLOAT;
comps = 4;
}
else {
_mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
&datatype, &comps);
assert(comps > 0 && "bad texture format in fallback_generate_mipmap()");
}

for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
const uint srcWidth = u_minify(pt->width0, srcLevel);
const uint srcHeight = u_minify(pt->height0, srcLevel);
const uint srcDepth = u_minify(pt->depth0, srcLevel);
const uint dstWidth = u_minify(pt->width0, dstLevel);
const uint dstHeight = u_minify(pt->height0, dstLevel);
const uint dstDepth = u_minify(pt->depth0, dstLevel);
struct pipe_transfer *srcTrans, *dstTrans;
const ubyte *srcData;
ubyte *dstData;
int srcStride, dstStride;

srcTrans = pipe_get_transfer(pipe, pt, srcLevel,
face,
PIPE_TRANSFER_READ, 0, 0,
srcWidth, srcHeight);

dstTrans = pipe_get_transfer(pipe, pt, dstLevel,
face,
PIPE_TRANSFER_WRITE, 0, 0,
dstWidth, dstHeight);

srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans);
dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans);

srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format);
dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format);

/* this cannot work correctly for 3d since it does
not respect layerStride. */
if (compressed) {
const enum pipe_format format = pt->format;
const uint bw = util_format_get_blockwidth(format);
const uint bh = util_format_get_blockheight(format);
const uint srcWidth2 = align(srcWidth, bw);
const uint srcHeight2 = align(srcHeight, bh);
const uint dstWidth2 = align(dstWidth, bw);
const uint dstHeight2 = align(dstHeight, bh);
uint8_t *srcTemp, *dstTemp;

assert(comps == 4);

srcTemp = malloc(srcWidth2 * srcHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1));
dstTemp = malloc(dstWidth2 * dstHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1));

/* decompress the src image: srcData -> srcTemp */
decompress_image(format, datatype, srcData, srcTemp, srcWidth2, srcHeight2, srcTrans->stride);

_mesa_generate_mipmap_level(target, datatype, comps,
0 /*border*/,
srcWidth2, srcHeight2, srcDepth,
srcTemp,
srcWidth2, /* stride in texels */
dstWidth2, dstHeight2, dstDepth,
dstTemp,
dstWidth2); /* stride in texels */

/* compress the new image: dstTemp -> dstData */
compress_image(format, datatype, dstTemp, dstData, dstWidth2, dstHeight2, dstTrans->stride);

free(srcTemp);
free(dstTemp);
}
else {
_mesa_generate_mipmap_level(target, datatype, comps,
0 /*border*/,
srcWidth, srcHeight, srcDepth,
srcData,
srcStride, /* stride in texels */
dstWidth, dstHeight, dstDepth,
dstData,
dstStride); /* stride in texels */
}

pipe_transfer_unmap(pipe, srcTrans);
pipe_transfer_unmap(pipe, dstTrans);

pipe->transfer_destroy(pipe, srcTrans);
pipe->transfer_destroy(pipe, dstTrans);
}
}


/**
* Compute the expected number of mipmap levels in the texture given
* the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
@@ -422,7 +219,7 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) {
/* since the util code actually also has a fallback, should
probably make it never fail and kill this */
fallback_generate_mipmap(ctx, target, texObj);
_mesa_generate_mipmap(ctx, target, texObj);
}

/* Fill in the Mesa gl_texture_image fields */

正在加载...
取消
保存