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;
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 {
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 */
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 */
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;
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;
/* 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 */
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);
}
}
/* 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);
}
}
}
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;
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) {
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);
}
}
}
/**
* 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:
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,
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,
/* 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;
}
}
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);
/* 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);
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,
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;
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);
_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,
GLubyte *temp = temp_src;
temp_src = temp_dst;
temp_dst = temp;
-
temp_src_stride = temp_dst_stride;
}
} /* loop over mipmap levels */
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/
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 */