📄 mipmap.c
字号:
bytesPerDstImage = dstWidth * dstHeight * bpt; bytesPerSrcRow = srcWidth * bpt; bytesPerDstRow = dstWidth * bpt; /* Offset between adjacent src images to be averaged together */ srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage; /* Offset between adjacent src rows to be averaged together */ srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt; /* * Need to average together up to 8 src pixels for each dest pixel. * Break that down into 3 operations: * 1. take two rows from source image and average them together. * 2. take two rows from next source image and average them together. * 3. take the two averaged rows and average them for the final dst row. */ /* _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n", srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); */ for (img = 0; img < dstDepthNB; img++) { /* first source image pointer, skipping border */ const GLubyte *imgSrcA = srcPtr + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border + img * (bytesPerSrcImage + srcImageOffset); /* second source image pointer, skipping border */ const GLubyte *imgSrcB = imgSrcA + srcImageOffset; /* address of the dest image, skipping border */ GLubyte *imgDst = dstPtr + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border + img * bytesPerDstImage; /* setup the four source row pointers and the dest row pointer */ const GLubyte *srcImgARowA = imgSrcA; const GLubyte *srcImgARowB = imgSrcA + srcRowOffset; const GLubyte *srcImgBRowA = imgSrcB; const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset; GLubyte *dstImgRow = imgDst; for (row = 0; row < dstHeightNB; row++) { /* Average together two rows from first src image */ do_row(format, srcWidthNB, srcImgARowA, srcImgARowB, srcWidthNB, tmpRowA); /* Average together two rows from second src image */ do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB, srcWidthNB, tmpRowB); /* Average together the temp rows to make the final row */ do_row(format, srcWidthNB, tmpRowA, tmpRowB, dstWidthNB, dstImgRow); /* advance to next rows */ srcImgARowA += bytesPerSrcRow + srcRowOffset; srcImgARowB += bytesPerSrcRow + srcRowOffset; srcImgBRowA += bytesPerSrcRow + srcRowOffset; srcImgBRowB += bytesPerSrcRow + srcRowOffset; dstImgRow += bytesPerDstRow; } } _mesa_free(tmpRowA); _mesa_free(tmpRowB); /* Luckily we can leverage the make_2d_mipmap() function here! */ if (border > 0) { /* do front border image */ make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr, srcRowStride, dstWidth, dstHeight, dstPtr, dstRowStride); /* do back border image */ make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride, dstWidth, dstHeight, dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride); /* do four remaining border edges that span the image slices */ if (srcDepth == dstDepth) { /* just copy border pixels from src to dst */ for (img = 0; img < dstDepthNB; img++) { const GLubyte *src; GLubyte *dst; /* do border along [img][row=0][col=0] */ src = srcPtr + (img + 1) * bytesPerSrcImage; dst = dstPtr + (img + 1) * bytesPerDstImage; 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; 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; 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); MEMCPY(dst, src, bpt); } } else { /* average border pixels from adjacent src image pairs */ ASSERT(srcDepthNB == 2 * dstDepthNB); for (img = 0; img < dstDepthNB; img++) { const GLubyte *src; GLubyte *dst; /* do border along [img][row=0][col=0] */ src = srcPtr + (img * 2 + 1) * bytesPerSrcImage; dst = dstPtr + (img + 1) * bytesPerDstImage; do_row(format, 1, src, src + srcImageOffset, 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(format, 1, src, src + srcImageOffset, 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(format, 1, src, src + srcImageOffset, 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(format, 1, src, src + srcImageOffset, 1, dst); } } }}static voidmake_1d_stack_mipmap(const struct gl_texture_format *format, GLint border, GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride, GLint dstWidth, GLint dstHeight, GLubyte *dstPtr, GLuint dstRowStride ){ const GLint bpt = format->TexelBytes; 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; /* Compute src and dst pointers, skipping any border */ src = srcPtr + border * ((srcWidth + 1) * bpt); dst = dstPtr + border * ((dstWidth + 1) * bpt); for (row = 0; row < dstHeightNB; row++) { do_row(format, srcWidthNB, src, src, dstWidthNB, dst); src += srcRowBytes; dst += dstRowBytes; } if (border) { /* copy left-most pixel from source */ MEMCPY(dstPtr, srcPtr, bpt); /* copy right-most pixel from source */ MEMCPY(dstPtr + (dstWidth - 1) * bpt, srcPtr + (srcWidth - 1) * bpt, bpt); }}/** * \bugs * There is quite a bit of refactoring that could be done with this function * and \c make_2d_mipmap. */static voidmake_2d_stack_mipmap(const struct gl_texture_format *format, GLint border, GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr, GLint srcRowStride, GLint dstWidth, GLint dstHeight, GLint dstDepth, GLubyte *dstPtr, GLint dstRowStride){ const GLint bpt = format->TexelBytes; 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++) { for (row = 0; row < dstHeightNB; row++) { do_row(format, srcWidthNB, srcA, srcB, dstWidthNB, dst); srcA += 2 * srcRowBytes; srcB += 2 * srcRowBytes; dst += dstRowBytes; } /* This is ugly but probably won't be used much */ if (border > 0) { /* fill in dest border */ /* lower-left border pixel */ MEMCPY(dstPtr, srcPtr, bpt); /* lower-right border pixel */ MEMCPY(dstPtr + (dstWidth - 1) * bpt, srcPtr + (srcWidth - 1) * bpt, bpt); /* upper-left border pixel */ MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt, srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); /* upper-right border pixel */ MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt, srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); /* lower border */ do_row(format, srcWidthNB, srcPtr + bpt, srcPtr + bpt, dstWidthNB, dstPtr + bpt); /* upper border */ do_row(format, srcWidthNB, srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, dstWidthNB, dstPtr + (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); } } else { /* average two src pixels each dest pixel */ for (row = 0; row < dstHeightNB; row += 2) { do_row(format, 1, srcPtr + (srcWidth * (row * 2 + 1)) * bpt, srcPtr + (srcWidth * (row * 2 + 2)) * bpt, 1, dstPtr + (dstWidth * row + 1) * bpt); do_row(format, 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); } } } }}/** * For GL_SGIX_generate_mipmap: * Generate a complete set of mipmaps from texObj's base-level image. * Stop at texObj's MaxLevel or when we get to the 1x1 texture. */void_mesa_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj){ const struct gl_texture_image *srcImage; const struct gl_texture_format *convertFormat; const GLubyte *srcData = NULL; GLubyte *dstData = NULL; GLint level, maxLevels; ASSERT(texObj); /* XXX choose cube map face here??? */ srcImage = texObj->Image[0][texObj->BaseLevel]; ASSERT(srcImage); maxLevels = _mesa_max_texture_levels(ctx, texObj->Target); ASSERT(maxLevels > 0); /* bad target */ /* Find convertFormat - the format that do_row() will process */ if (srcImage->IsCompressed) { /* setup for compressed textures */ GLuint row; GLint components, size; GLchan *dst; assert(texObj->Target == GL_TEXTURE_2D || texObj->Target == GL_TEXTURE_CUBE_MAP_ARB); if (srcImage->_BaseFormat == GL_RGB) { convertFormat = &_mesa_texformat_rgb; components = 3; } else if (srcImage->_BaseFormat == GL_RGBA) { convertFormat = &_mesa_texformat_rgba; components = 4; } else { _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps"); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -