diff options
Diffstat (limited to 'dist/Mesa/src/mesa/main/texstore.c')
-rw-r--r-- | dist/Mesa/src/mesa/main/texstore.c | 1771 |
1 files changed, 509 insertions, 1262 deletions
diff --git a/dist/Mesa/src/mesa/main/texstore.c b/dist/Mesa/src/mesa/main/texstore.c index 7471934b4..2ac458b45 100644 --- a/dist/Mesa/src/mesa/main/texstore.c +++ b/dist/Mesa/src/mesa/main/texstore.c @@ -27,7 +27,7 @@ * Brian Paul */ -/* +/** * The GL texture image functions in teximage.c basically just do * error checking and data structure allocation. They in turn call * device driver functions which actually copy/convert/store the user's @@ -58,16 +58,27 @@ #include "convolve.h" #include "image.h" #include "macros.h" +#include "mipmap.h" #include "imports.h" #include "texcompress.h" #include "texformat.h" #include "teximage.h" #include "texstore.h" +#include "enums.h" -static const GLint ZERO = 4, ONE = 5; +enum { + ZERO = 4, + ONE = 5 +}; -static GLboolean can_swizzle(GLenum logicalBaseFormat) + +/** + * Return GL_TRUE if the given image format is one that be converted + * to another format by swizzling. + */ +static GLboolean +can_swizzle(GLenum logicalBaseFormat) { switch (logicalBaseFormat) { case GL_RGBA: @@ -76,6 +87,12 @@ static GLboolean can_swizzle(GLenum logicalBaseFormat) case GL_INTENSITY: case GL_ALPHA: case GL_LUMINANCE: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_BGR: + case GL_BGRA: + case GL_ABGR_EXT: return GL_TRUE; default: return GL_FALSE; @@ -83,89 +100,172 @@ static GLboolean can_swizzle(GLenum logicalBaseFormat) } + +enum { + IDX_LUMINANCE = 0, + IDX_ALPHA, + IDX_INTENSITY, + IDX_LUMINANCE_ALPHA, + IDX_RGB, + IDX_RGBA, + IDX_RED, + IDX_GREEN, + IDX_BLUE, + IDX_BGR, + IDX_BGRA, + IDX_ABGR, + MAX_IDX +}; + +#define MAP1(x) MAP4(x, ZERO, ZERO, ZERO) +#define MAP2(x,y) MAP4(x, y, ZERO, ZERO) +#define MAP3(x,y,z) MAP4(x, y, z, ZERO) +#define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE } + + +static const struct { + GLubyte format_idx; + GLubyte to_rgba[6]; + GLubyte from_rgba[6]; +} mappings[MAX_IDX] = +{ + { + IDX_LUMINANCE, + MAP4(0,0,0,ONE), + MAP1(0) + }, + + { + IDX_ALPHA, + MAP4(ZERO, ZERO, ZERO, 0), + MAP1(3) + }, + + { + IDX_INTENSITY, + MAP4(0, 0, 0, 0), + MAP1(0), + }, + + { + IDX_LUMINANCE_ALPHA, + MAP4(0,0,0,1), + MAP2(0,3) + }, + + { + IDX_RGB, + MAP4(0,1,2,ONE), + MAP3(0,1,2) + }, + + { + IDX_RGBA, + MAP4(0,1,2,3), + MAP4(0,1,2,3), + }, + + + { + IDX_RED, + MAP4(0, ZERO, ZERO, ONE), + MAP1(0), + }, + + { + IDX_GREEN, + MAP4(ZERO, 0, ZERO, ONE), + MAP1(1), + }, + + { + IDX_BLUE, + MAP4(ZERO, ZERO, 0, ONE), + MAP1(2), + }, + + { + IDX_BGR, + MAP4(2,1,0,ONE), + MAP3(2,1,0) + }, + + { + IDX_BGRA, + MAP4(2,1,0,3), + MAP4(2,1,0,3) + }, + + { + IDX_ABGR, + MAP4(3,2,1,0), + MAP4(3,2,1,0) + }, +}; + + + +/** + * Convert a GL image format enum to an IDX_* value (see above). + */ +static int +get_map_idx(GLenum value) +{ + switch (value) { + case GL_LUMINANCE: return IDX_LUMINANCE; + case GL_ALPHA: return IDX_ALPHA; + case GL_INTENSITY: return IDX_INTENSITY; + case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA; + case GL_RGB: return IDX_RGB; + case GL_RGBA: return IDX_RGBA; + case GL_RED: return IDX_RED; + case GL_GREEN: return IDX_GREEN; + case GL_BLUE: return IDX_BLUE; + case GL_BGR: return IDX_BGR; + case GL_BGRA: return IDX_BGRA; + case GL_ABGR_EXT: return IDX_ABGR; + default: + _mesa_problem(NULL, "Unexpected inFormat"); + return 0; + } +} + + /** * When promoting texture formats (see below) we need to compute the * mapping of dest components back to source components. * This function does that. - * \param logicalBaseFormat the logical format of the texture - * \param textureBaseFormat the final texture format - * \return map[4] the four mapping values + * \param inFormat the incoming format of the texture + * \param outFormat the final texture format + * \return map[6] a full 6-component map */ static void -compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat, - GLubyte map[6]) +compute_component_mapping(GLenum inFormat, GLenum outFormat, + GLubyte *map) { + const int inFmt = get_map_idx(inFormat); + const int outFmt = get_map_idx(outFormat); + const GLubyte *in2rgba = mappings[inFmt].to_rgba; + const GLubyte *rgba2out = mappings[outFmt].from_rgba; + int i; + + for (i = 0; i < 4; i++) + map[i] = in2rgba[rgba2out[i]]; + map[ZERO] = ZERO; - map[ONE] = ONE; + map[ONE] = ONE; - /* compute mapping from dest components back to src components */ - switch (textureBaseFormat) { - case GL_RGB: - case GL_RGBA: - switch (logicalBaseFormat) { - case GL_LUMINANCE: - map[0] = map[1] = map[2] = 0; - if (textureBaseFormat == GL_RGBA) - map[3] = ONE; - break; - case GL_ALPHA: - ASSERT(textureBaseFormat == GL_RGBA); - map[0] = map[1] = map[2] = ZERO; - map[3] = 0; - break; - case GL_INTENSITY: - map[0] = map[1] = map[2] = 0; - if (textureBaseFormat == GL_RGBA) - map[3] = 0; - break; - case GL_LUMINANCE_ALPHA: - ASSERT(textureBaseFormat == GL_RGBA); - map[0] = map[1] = map[2] = 0; - map[3] = 1; - break; - case GL_RGB: - ASSERT(textureBaseFormat == GL_RGBA); - map[0] = 0; - map[1] = 1; - map[2] = 2; - map[3] = ONE; - break; - case GL_RGBA: - ASSERT(textureBaseFormat == GL_RGBA); - map[0] = 0; - map[1] = 1; - map[2] = 2; - map[3] = 3; - break; - default: - _mesa_problem(NULL, "Unexpected logicalBaseFormat"); - map[0] = map[1] = map[2] = map[3] = 0; - } - break; - case GL_LUMINANCE_ALPHA: - switch (logicalBaseFormat) { - case GL_LUMINANCE: - map[0] = 0; - map[1] = ONE; - break; - case GL_ALPHA: - map[0] = ZERO; - map[1] = 0; - break; - case GL_INTENSITY: - map[0] = 0; - map[1] = 0; - break; - default: - _mesa_problem(NULL, "Unexpected logicalBaseFormat"); - map[0] = map[1] = 0; - } - break; - default: - _mesa_problem(NULL, "Unexpected textureBaseFormat"); - map[0] = map[1] = 0; - break; - } +/* + _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n", + inFormat, _mesa_lookup_enum_by_nr(inFormat), + outFormat, _mesa_lookup_enum_by_nr(outFormat), + map[0], + map[1], + map[2], + map[3], + map[4], + map[5]); +*/ } @@ -298,7 +398,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, GLfloat *dst = tempImage + img * (convWidth * convHeight * 4); for (row = 0; row < convHeight; row++) { _mesa_pack_rgba_span_float(ctx, convWidth, - (const GLfloat (*)[4]) src, + (GLfloat (*)[4]) src, logicalBaseFormat, GL_FLOAT, dst, &ctx->DefaultPacking, postConvTransferOps); @@ -552,14 +652,16 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, * \param dstComponents number of color components in destination pixels * \param src source pixels * \param srcComponents number of color components in source pixels - * \param map the swizzle mapping + * \param map the swizzle mapping. map[X] says where to find the X component + * in the source image's pixels. For example, if the source image + * is GL_BGRA and X = red, map[0] yields 2. * \param count number of pixels to copy/swizzle. */ static void swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src, GLuint srcComponents, const GLubyte *map, GLuint count) { - GLubyte tmp[8]; + GLubyte tmp[6]; GLuint i; tmp[ZERO] = 0x0; @@ -596,10 +698,61 @@ swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src, dst += 2; } break; + case 1: + /* XXX investigate valgrind invalid read when running demos/texenv.c */ + for (i = 0; i < count; i++) { + COPY_4UBV(tmp, src); + src += srcComponents; + dst[0] = tmp[map[0]]; + dst += 1; + } + break; } } +static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE }; +static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE }; + +/* Deal with the _REV input types: + */ +static const GLubyte * +type_mapping( GLenum srcType ) +{ + switch (srcType) { + case GL_UNSIGNED_BYTE: + return map_identity; + case GL_UNSIGNED_INT_8_8_8_8: + return _mesa_little_endian() ? map_3210 : map_identity; + case GL_UNSIGNED_INT_8_8_8_8_REV: + return _mesa_little_endian() ? map_identity : map_3210; + default: + return NULL; + } +} + +/* Mapping required if input type is + */ +static const GLubyte * +byteswap_mapping( GLboolean swapBytes, + GLenum srcType ) +{ + if (!swapBytes) + return map_identity; + + switch (srcType) { + case GL_UNSIGNED_BYTE: + return map_identity; + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + return map_3210; + default: + return NULL; + } +} + + + /** * Transfer a GLubyte texture image with component swizzling. */ @@ -607,7 +760,12 @@ static void _mesa_swizzle_ubyte_image(GLcontext *ctx, GLuint dimensions, GLenum srcFormat, - const GLubyte *dstmap, GLint dstComponents, + GLenum srcType, + + GLenum baseInternalFormat, + + const GLubyte *rgba2dst, + GLuint dstComponents, GLvoid *dstAddr, GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, @@ -619,9 +777,9 @@ _mesa_swizzle_ubyte_image(GLcontext *ctx, const struct gl_pixelstore_attrib *srcPacking ) { GLint srcComponents = _mesa_components_in_format(srcFormat); - GLubyte srcmap[6], map[4]; + const GLubyte *srctype2ubyte, *swap; + GLubyte map[4], src2base[6], base2rgba[6]; GLint i; - const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, GL_UNSIGNED_BYTE); @@ -635,12 +793,24 @@ _mesa_swizzle_ubyte_image(GLcontext *ctx, (void) ctx; - compute_component_mapping(srcFormat, GL_RGBA, srcmap); + /* Translate from src->baseInternal->GL_RGBA->dst. This will + * correctly deal with RGBA->RGB->RGBA conversions where the final + * A value must be 0xff regardless of the incoming alpha values. + */ + compute_component_mapping(srcFormat, baseInternalFormat, src2base); + compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba); + swap = byteswap_mapping(srcPacking->SwapBytes, srcType); + srctype2ubyte = type_mapping(srcType); + for (i = 0; i < 4; i++) - map[i] = srcmap[dstmap[i]]; + map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]]; - if (srcRowStride == srcWidth * srcComponents && +/* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */ + + if (srcRowStride == dstRowStride && + srcComponents == dstComponents && + srcRowStride == srcWidth * srcComponents && dimensions < 3) { /* 1 and 2D images only */ GLubyte *dstImage = (GLubyte *) dstAddr @@ -817,6 +987,58 @@ _mesa_texstore_rgba(TEXSTORE_PARAMS) } } } + else if (!ctx->_ImageTransferState && + CHAN_TYPE == GL_UNSIGNED_BYTE && + (srcType == GL_UNSIGNED_BYTE || + srcType == GL_UNSIGNED_INT_8_8_8_8 || + srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && + can_swizzle(baseInternalFormat) && + can_swizzle(srcFormat)) { + + const GLubyte *dstmap; + GLuint components; + + /* dstmap - how to swizzle from RGBA to dst format: + */ + if (dstFormat == &_mesa_texformat_rgba) { + dstmap = mappings[IDX_RGBA].from_rgba; + components = 4; + } + else if (dstFormat == &_mesa_texformat_rgb) { + dstmap = mappings[IDX_RGB].from_rgba; + components = 3; + } + else if (dstFormat == &_mesa_texformat_alpha) { + dstmap = mappings[IDX_ALPHA].from_rgba; + components = 1; + } + else if (dstFormat == &_mesa_texformat_luminance) { + dstmap = mappings[IDX_LUMINANCE].from_rgba; + components = 1; + } + else if (dstFormat == &_mesa_texformat_luminance_alpha) { + dstmap = mappings[IDX_LUMINANCE_ALPHA].from_rgba; + components = 2; + } + else if (dstFormat == &_mesa_texformat_intensity) { + dstmap = mappings[IDX_INTENSITY].from_rgba; + components = 1; + } + else { + _mesa_problem(ctx, "Unexpected dstFormat in _mesa_texstore_rgba"); + return GL_FALSE; + } + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + srcType, + baseInternalFormat, + dstmap, components, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageOffsets, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } else { /* general path */ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, @@ -1050,13 +1272,14 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS) } +/** + * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV. + */ GLboolean _mesa_texstore_rgba8888(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); - (void)littleEndian; ASSERT(dstFormat == &_mesa_texformat_rgba8888 || dstFormat == &_mesa_texformat_rgba8888_rev); ASSERT(dstFormat->TexelBytes == 4); @@ -1093,40 +1316,41 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS) srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } -#if 0 - /* broken? */ else if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - srcType == GL_UNSIGNED_BYTE && - dstFormat == &_mesa_texformat_rgba8888 && - littleEndian && - /* Three texture formats involved: srcFormat, - * baseInternalFormat and destFormat (GL_RGBA). Only two - * may differ. _mesa_swizzle_ubyte_image can't handle two - * propagations at once correctly. */ - (srcFormat == baseInternalFormat || - baseInternalFormat == GL_RGBA) && + (srcType == GL_UNSIGNED_BYTE || + srcType == GL_UNSIGNED_INT_8_8_8_8 || + srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && + can_swizzle(baseInternalFormat) && can_swizzle(srcFormat)) { + GLubyte dstmap[4]; - /* dstmap - how to swizzle from GL_RGBA to dst format: - * - * FIXME - add !litteEndian and _rev varients: + /* dstmap - how to swizzle from RGBA to dst format: */ - dstmap[3] = 0; - dstmap[2] = 1; - dstmap[1] = 2; - dstmap[0] = 3; + if ((littleEndian && dstFormat == &_mesa_texformat_rgba8888) || + (!littleEndian && dstFormat == &_mesa_texformat_rgba8888_rev)) { + dstmap[3] = 0; + dstmap[2] = 1; + dstmap[1] = 2; + dstmap[0] = 3; + } + else { + dstmap[3] = 3; + dstmap[2] = 2; + dstmap[1] = 1; + dstmap[0] = 0; + } _mesa_swizzle_ubyte_image(ctx, dims, srcFormat, + srcType, + baseInternalFormat, dstmap, 4, dstAddr, dstXoffset, dstYoffset, dstZoffset, - dstRowStride, dstImageStride, + dstRowStride, dstImageOffsets, srcWidth, srcHeight, srcDepth, srcAddr, srcPacking); } -#endif else { /* general path */ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, @@ -1177,8 +1401,7 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS) GLboolean _mesa_texstore_argb8888(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); ASSERT(dstFormat == &_mesa_texformat_argb8888 || dstFormat == &_mesa_texformat_argb8888_rev); @@ -1218,6 +1441,8 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) !srcPacking->SwapBytes && dstFormat == &_mesa_texformat_argb8888 && srcFormat == GL_RGB && + (baseInternalFormat == GL_RGBA || + baseInternalFormat == GL_RGB) && srcType == GL_UNSIGNED_BYTE) { int img, row, col; @@ -1246,6 +1471,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) !srcPacking->SwapBytes && dstFormat == &_mesa_texformat_argb8888 && srcFormat == GL_RGBA && + baseInternalFormat == GL_RGBA && (srcType == GL_UNSIGNED_BYTE && littleEndian)) { GLint img, row, col; /* For some reason, streaming copies to write-combined regions @@ -1280,6 +1506,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) !srcPacking->SwapBytes && dstFormat == &_mesa_texformat_argb8888 && srcFormat == GL_RGBA && + baseInternalFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { GLint img, row, col; @@ -1305,29 +1532,37 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) } } else if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - dstFormat == &_mesa_texformat_argb8888 && - srcType == GL_UNSIGNED_BYTE && - littleEndian && - /* Three texture formats involved: srcFormat, - * baseInternalFormat and destFormat (GL_RGBA). Only two - * may differ. _mesa_swizzle_ubyte_image can't handle two - * propagations at once correctly. */ - (srcFormat == baseInternalFormat || - baseInternalFormat == GL_RGBA) && + (srcType == GL_UNSIGNED_BYTE || + srcType == GL_UNSIGNED_INT_8_8_8_8 || + srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && + can_swizzle(baseInternalFormat) && can_swizzle(srcFormat)) { GLubyte dstmap[4]; - /* dstmap - how to swizzle from GL_RGBA to dst format: + /* dstmap - how to swizzle from RGBA to dst format: */ - dstmap[3] = 3; /* alpha */ - dstmap[2] = 0; /* red */ - dstmap[1] = 1; /* green */ - dstmap[0] = 2; /* blue */ + if ((littleEndian && dstFormat == &_mesa_texformat_argb8888) || + (!littleEndian && dstFormat == &_mesa_texformat_argb8888_rev)) { + dstmap[3] = 3; /* alpha */ + dstmap[2] = 0; /* red */ + dstmap[1] = 1; /* green */ + dstmap[0] = 2; /* blue */ + } + else { + assert((littleEndian && dstFormat == &_mesa_texformat_argb8888_rev) || + (!littleEndian && dstFormat == &_mesa_texformat_argb8888)); + dstmap[3] = 2; + dstmap[2] = 1; + dstmap[1] = 0; + dstmap[0] = 3; + } _mesa_swizzle_ubyte_image(ctx, dims, srcFormat, + srcType, + + baseInternalFormat, dstmap, 4, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, @@ -1385,8 +1620,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) GLboolean _mesa_texstore_rgb888(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); ASSERT(dstFormat == &_mesa_texformat_rgb888); ASSERT(dstFormat->TexelBytes == 3); @@ -1431,6 +1665,30 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS) } } } + else if (!ctx->_ImageTransferState && + srcType == GL_UNSIGNED_BYTE && + can_swizzle(baseInternalFormat) && + can_swizzle(srcFormat)) { + + GLubyte dstmap[4]; + + /* dstmap - how to swizzle from RGBA to dst format: + */ + dstmap[0] = 2; + dstmap[1] = 1; + dstmap[2] = 0; + dstmap[3] = ONE; /* ? */ + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + srcType, + baseInternalFormat, + dstmap, 3, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageOffsets, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } else { /* general path */ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, @@ -1487,8 +1745,7 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS) GLboolean _mesa_texstore_bgr888(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); ASSERT(dstFormat == &_mesa_texformat_bgr888); ASSERT(dstFormat->TexelBytes == 3); @@ -1533,6 +1790,30 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS) } } } + else if (!ctx->_ImageTransferState && + srcType == GL_UNSIGNED_BYTE && + can_swizzle(baseInternalFormat) && + can_swizzle(srcFormat)) { + + GLubyte dstmap[4]; + + /* dstmap - how to swizzle from RGBA to dst format: + */ + dstmap[0] = 0; + dstmap[1] = 1; + dstmap[2] = 2; + dstmap[3] = ONE; /* ? */ + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + srcType, + baseInternalFormat, + dstmap, 3, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageOffsets, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } else { /* general path */ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, @@ -1707,8 +1988,7 @@ _mesa_texstore_argb1555(TEXSTORE_PARAMS) GLboolean _mesa_texstore_al88(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); ASSERT(dstFormat == &_mesa_texformat_al88 || dstFormat == &_mesa_texformat_al88_rev); @@ -1729,6 +2009,38 @@ _mesa_texstore_al88(TEXSTORE_PARAMS) srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } + else if (!ctx->_ImageTransferState && + littleEndian && + srcType == GL_UNSIGNED_BYTE && + can_swizzle(baseInternalFormat) && + can_swizzle(srcFormat)) { + + GLubyte dstmap[4]; + + /* dstmap - how to swizzle from RGBA to dst format: + */ + if ((littleEndian && dstFormat == &_mesa_texformat_al88) || + (!littleEndian && dstFormat == &_mesa_texformat_al88_rev)) { + dstmap[0] = 0; + dstmap[1] = 3; + } + else { + dstmap[0] = 3; + dstmap[1] = 0; + } + dstmap[2] = ZERO; /* ? */ + dstmap[3] = ONE; /* ? */ + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + srcType, + baseInternalFormat, + dstmap, 2, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageOffsets, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } else { /* general path */ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, @@ -1849,6 +2161,35 @@ _mesa_texstore_a8(TEXSTORE_PARAMS) srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } + else if (!ctx->_ImageTransferState && + srcType == GL_UNSIGNED_BYTE && + can_swizzle(baseInternalFormat) && + can_swizzle(srcFormat)) { + + GLubyte dstmap[4]; + + /* dstmap - how to swizzle from RGBA to dst format: + */ + if (dstFormat == &_mesa_texformat_a8) { + dstmap[0] = 3; + } + else { + dstmap[0] = 0; + } + dstmap[1] = ZERO; /* ? */ + dstmap[2] = ZERO; /* ? */ + dstmap[3] = ONE; /* ? */ + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + srcType, + baseInternalFormat, + dstmap, 1, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageOffsets, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } else { /* general path */ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, @@ -1930,8 +2271,7 @@ _mesa_texstore_ci8(TEXSTORE_PARAMS) GLboolean _mesa_texstore_ycbcr(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); (void) ctx; (void) dims; (void) baseInternalFormat; ASSERT((dstFormat == &_mesa_texformat_ycbcr) || @@ -2186,8 +2526,7 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS) GLboolean _mesa_texstore_srgb8(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); const struct gl_texture_format *newDstFormat; StoreTexImageFunc store; GLboolean k; @@ -2218,8 +2557,7 @@ _mesa_texstore_srgb8(TEXSTORE_PARAMS) GLboolean _mesa_texstore_srgba8(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); const struct gl_texture_format *newDstFormat; GLboolean k; @@ -2267,8 +2605,7 @@ _mesa_texstore_sl8(TEXSTORE_PARAMS) GLboolean _mesa_texstore_sla8(TEXSTORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); + const GLboolean littleEndian = _mesa_little_endian(); const struct gl_texture_format *newDstFormat; GLboolean k; @@ -2386,8 +2723,8 @@ _mesa_unmap_teximage_pbo(GLcontext *ctx, * Adaptor for fetching a GLchan texel from a float-valued texture. */ static void -FetchTexelFloatToChan( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLchan *texelOut ) +fetch_texel_float_to_chan(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texelOut) { GLfloat temp[4]; ASSERT(texImage->FetchTexelf); @@ -2411,8 +2748,8 @@ FetchTexelFloatToChan( const struct gl_texture_image *texImage, * Adaptor for fetching a float texel from a GLchan-valued texture. */ static void -FetchTexelChanToFloat( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texelOut ) +fetch_texel_chan_to_float(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texelOut) { GLchan temp[4]; ASSERT(texImage->FetchTexelc); @@ -2435,8 +2772,8 @@ FetchTexelChanToFloat( const struct gl_texture_image *texImage, /** * Initialize the texture image's FetchTexelc and FetchTexelf methods. */ -static void -set_fetch_functions(struct gl_texture_image *texImage, GLuint dims) +void +_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims) { ASSERT(dims == 1 || dims == 2 || dims == 3); ASSERT(texImage->TexFormat); @@ -2460,10 +2797,10 @@ set_fetch_functions(struct gl_texture_image *texImage, GLuint dims) /* now check if we need to use a float/chan adaptor */ if (!texImage->FetchTexelc) { - texImage->FetchTexelc = FetchTexelFloatToChan; + texImage->FetchTexelc = fetch_texel_float_to_chan; } else if (!texImage->FetchTexelf) { - texImage->FetchTexelf = FetchTexelChanToFloat; + texImage->FetchTexelf = fetch_texel_chan_to_float; } @@ -2496,7 +2833,7 @@ choose_texture_format(GLcontext *ctx, struct gl_texture_image *texImage, ASSERT(texImage->TexFormat); - set_fetch_functions(texImage, dims); + _mesa_set_fetch_functions(texImage, dims); if (texImage->TexFormat->TexelBytes == 0) { /* must be a compressed format */ @@ -3119,1114 +3456,6 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, } -/* - * Average together two rows of a source image to produce a single new - * row in the dest image. It's legal for the two source rows to point - * to the same data. The source width must be equal to either the - * dest width or two times the dest width. - */ -static void -do_row(const struct gl_texture_format *format, GLint srcWidth, - const GLvoid *srcRowA, const GLvoid *srcRowB, - GLint dstWidth, GLvoid *dstRow) -{ - const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; - const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; - - /* This assertion is no longer valid with non-power-of-2 textures - assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); - */ - - switch (format->MesaFormat) { - case MESA_FORMAT_RGBA: - { - GLuint i, j, k; - const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA; - const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB; - GLchan (*dst)[4] = (GLchan (*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + - rowB[j][2] + rowB[k][2]) / 4; - dst[i][3] = (rowA[j][3] + rowA[k][3] + - rowB[j][3] + rowB[k][3]) / 4; - } - } - return; - case MESA_FORMAT_RGB: - { - GLuint i, j, k; - const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA; - const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB; - GLchan (*dst)[3] = (GLchan (*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + - rowB[j][2] + rowB[k][2]) / 4; - } - } - return; - case MESA_FORMAT_ALPHA: - case MESA_FORMAT_LUMINANCE: - case MESA_FORMAT_INTENSITY: - { - GLuint i, j, k; - const GLchan *rowA = (const GLchan *) srcRowA; - const GLchan *rowB = (const GLchan *) srcRowB; - GLchan *dst = (GLchan *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; - } - } - return; - case MESA_FORMAT_LUMINANCE_ALPHA: - { - GLuint i, j, k; - const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA; - const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB; - GLchan (*dst)[2] = (GLchan (*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) / 4; - } - } - return; - case MESA_FORMAT_Z32: - { - GLuint i, j, k; - const GLuint *rowA = (const GLuint *) srcRowA; - const GLuint *rowB = (const GLuint *) srcRowB; - GLfloat *dst = (GLfloat *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4; - } - } - return; - case MESA_FORMAT_Z16: - { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; - } - } - return; - /* Begin hardware formats */ - case MESA_FORMAT_RGBA8888: - case MESA_FORMAT_RGBA8888_REV: - case MESA_FORMAT_ARGB8888: - case MESA_FORMAT_ARGB8888_REV: -#if FEATURE_EXT_texture_sRGB - case MESA_FORMAT_SRGBA8: -#endif - { - GLuint i, j, k; - const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA; - const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB; - GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + - rowB[j][2] + rowB[k][2]) / 4; - dst[i][3] = (rowA[j][3] + rowA[k][3] + - rowB[j][3] + rowB[k][3]) / 4; - } - } - return; - case MESA_FORMAT_RGB888: - case MESA_FORMAT_BGR888: -#if FEATURE_EXT_texture_sRGB - case MESA_FORMAT_SRGB8: -#endif - { - GLuint i, j, k; - const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA; - const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB; - GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) / 4; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) / 4; - dst[i][2] = (rowA[j][2] + rowA[k][2] + - rowB[j][2] + rowB[k][2]) / 4; - } - } - return; - case MESA_FORMAT_RGB565: - case MESA_FORMAT_RGB565_REV: - { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x1f; - const GLint rowAr1 = rowA[k] & 0x1f; - const GLint rowBr0 = rowB[j] & 0x1f; - const GLint rowBr1 = rowB[k] & 0x1f; - const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; - const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; - const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; - const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; - const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; - const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; - const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; - const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - dst[i] = (blue << 11) | (green << 5) | red; - } - } - return; - case MESA_FORMAT_ARGB4444: - case MESA_FORMAT_ARGB4444_REV: - { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0xf; - const GLint rowAr1 = rowA[k] & 0xf; - const GLint rowBr0 = rowB[j] & 0xf; - const GLint rowBr1 = rowB[k] & 0xf; - const GLint rowAg0 = (rowA[j] >> 4) & 0xf; - const GLint rowAg1 = (rowA[k] >> 4) & 0xf; - const GLint rowBg0 = (rowB[j] >> 4) & 0xf; - const GLint rowBg1 = (rowB[k] >> 4) & 0xf; - const GLint rowAb0 = (rowA[j] >> 8) & 0xf; - const GLint rowAb1 = (rowA[k] >> 8) & 0xf; - const GLint rowBb0 = (rowB[j] >> 8) & 0xf; - const GLint rowBb1 = (rowB[k] >> 8) & 0xf; - const GLint rowAa0 = (rowA[j] >> 12) & 0xf; - const GLint rowAa1 = (rowA[k] >> 12) & 0xf; - const GLint rowBa0 = (rowB[j] >> 12) & 0xf; - const GLint rowBa1 = (rowB[k] >> 12) & 0xf; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; - dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; - } - } - return; - case MESA_FORMAT_ARGB1555: - case MESA_FORMAT_ARGB1555_REV: /* XXX broken? */ - { - GLuint i, j, k; - const GLushort *rowA = (const GLushort *) srcRowA; - const GLushort *rowB = (const GLushort *) srcRowB; - GLushort *dst = (GLushort *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x1f; - const GLint rowAr1 = rowA[k] & 0x1f; - const GLint rowBr0 = rowB[j] & 0x1f; - const GLint rowBr1 = rowB[k] & 0xf; - const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; - const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; - const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; - const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; - const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; - const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; - const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; - const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; - const GLint rowAa0 = (rowA[j] >> 15) & 0x1; - const GLint rowAa1 = (rowA[k] >> 15) & 0x1; - const GLint rowBa0 = (rowB[j] >> 15) & 0x1; - const GLint rowBa1 = (rowB[k] >> 15) & 0x1; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; - dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; - } - } - return; - case MESA_FORMAT_AL88: - case MESA_FORMAT_AL88_REV: -#if FEATURE_EXT_texture_sRGB - case MESA_FORMAT_SLA8: -#endif - { - GLuint i, j, k; - const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA; - const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB; - GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) >> 2; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) >> 2; - } - } - return; - case MESA_FORMAT_RGB332: - { - GLuint i, j, k; - const GLubyte *rowA = (const GLubyte *) srcRowA; - const GLubyte *rowB = (const GLubyte *) srcRowB; - GLubyte *dst = (GLubyte *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - const GLint rowAr0 = rowA[j] & 0x3; - const GLint rowAr1 = rowA[k] & 0x3; - const GLint rowBr0 = rowB[j] & 0x3; - const GLint rowBr1 = rowB[k] & 0x3; - const GLint rowAg0 = (rowA[j] >> 2) & 0x7; - const GLint rowAg1 = (rowA[k] >> 2) & 0x7; - const GLint rowBg0 = (rowB[j] >> 2) & 0x7; - const GLint rowBg1 = (rowB[k] >> 2) & 0x7; - const GLint rowAb0 = (rowA[j] >> 5) & 0x7; - const GLint rowAb1 = (rowA[k] >> 5) & 0x7; - const GLint rowBb0 = (rowB[j] >> 5) & 0x7; - const GLint rowBb1 = (rowB[k] >> 5) & 0x7; - const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; - const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; - const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; - dst[i] = (blue << 5) | (green << 2) | red; - } - } - return; - case MESA_FORMAT_A8: - case MESA_FORMAT_L8: - case MESA_FORMAT_I8: - case MESA_FORMAT_CI8: -#if FEATURE_EXT_texture_sRGB - case MESA_FORMAT_SL8: -#endif - { - GLuint i, j, k; - const GLubyte *rowA = (const GLubyte *) srcRowA; - const GLubyte *rowB = (const GLubyte *) srcRowB; - GLubyte *dst = (GLubyte *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; - } - } - return; - case MESA_FORMAT_RGBA_FLOAT32: - { - GLuint i, j, k; - const GLfloat (*rowA)[4] = (const GLfloat (*)[4]) srcRowA; - const GLfloat (*rowB)[4] = (const GLfloat (*)[4]) srcRowB; - GLfloat (*dst)[4] = (GLfloat (*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) * 0.25F; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) * 0.25F; - dst[i][2] = (rowA[j][2] + rowA[k][2] + - rowB[j][2] + rowB[k][2]) * 0.25F; - dst[i][3] = (rowA[j][3] + rowA[k][3] + - rowB[j][3] + rowB[k][3]) * 0.25F; - } - } - return; - case MESA_FORMAT_RGBA_FLOAT16: - { - GLuint i, j, k, comp; - const GLhalfARB (*rowA)[4] = (const GLhalfARB (*)[4]) srcRowA; - const GLhalfARB (*rowB)[4] = (const GLhalfARB (*)[4]) srcRowB; - GLhalfARB (*dst)[4] = (GLhalfARB (*)[4]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - for (comp = 0; comp < 4; comp++) { - GLfloat aj, ak, bj, bk; - aj = _mesa_half_to_float(rowA[j][comp]); - ak = _mesa_half_to_float(rowA[k][comp]); - bj = _mesa_half_to_float(rowB[j][comp]); - bk = _mesa_half_to_float(rowB[k][comp]); - dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); - } - } - } - return; - case MESA_FORMAT_RGB_FLOAT32: - { - GLuint i, j, k; - const GLfloat (*rowA)[3] = (const GLfloat (*)[3]) srcRowA; - const GLfloat (*rowB)[3] = (const GLfloat (*)[3]) srcRowB; - GLfloat (*dst)[3] = (GLfloat (*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) * 0.25F; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) * 0.25F; - dst[i][2] = (rowA[j][2] + rowA[k][2] + - rowB[j][2] + rowB[k][2]) * 0.25F; - } - } - return; - case MESA_FORMAT_RGB_FLOAT16: - { - GLuint i, j, k, comp; - const GLhalfARB (*rowA)[3] = (const GLhalfARB (*)[3]) srcRowA; - const GLhalfARB (*rowB)[3] = (const GLhalfARB (*)[3]) srcRowB; - GLhalfARB (*dst)[3] = (GLhalfARB (*)[3]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - for (comp = 0; comp < 3; comp++) { - GLfloat aj, ak, bj, bk; - aj = _mesa_half_to_float(rowA[j][comp]); - ak = _mesa_half_to_float(rowA[k][comp]); - bj = _mesa_half_to_float(rowB[j][comp]); - bk = _mesa_half_to_float(rowB[k][comp]); - dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); - } - } - } - return; - case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32: - { - GLuint i, j, k; - const GLfloat (*rowA)[2] = (const GLfloat (*)[2]) srcRowA; - const GLfloat (*rowB)[2] = (const GLfloat (*)[2]) srcRowB; - GLfloat (*dst)[2] = (GLfloat (*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i][0] = (rowA[j][0] + rowA[k][0] + - rowB[j][0] + rowB[k][0]) * 0.25F; - dst[i][1] = (rowA[j][1] + rowA[k][1] + - rowB[j][1] + rowB[k][1]) * 0.25F; - } - } - return; - case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16: - { - GLuint i, j, k, comp; - const GLhalfARB (*rowA)[2] = (const GLhalfARB (*)[2]) srcRowA; - const GLhalfARB (*rowB)[2] = (const GLhalfARB (*)[2]) srcRowB; - GLhalfARB (*dst)[2] = (GLhalfARB (*)[2]) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - for (comp = 0; comp < 2; comp++) { - GLfloat aj, ak, bj, bk; - aj = _mesa_half_to_float(rowA[j][comp]); - ak = _mesa_half_to_float(rowA[k][comp]); - bj = _mesa_half_to_float(rowB[j][comp]); - bk = _mesa_half_to_float(rowB[k][comp]); - dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); - } - } - } - return; - case MESA_FORMAT_ALPHA_FLOAT32: - case MESA_FORMAT_LUMINANCE_FLOAT32: - case MESA_FORMAT_INTENSITY_FLOAT32: - { - GLuint i, j, k; - const GLfloat *rowA = (const GLfloat *) srcRowA; - const GLfloat *rowB = (const GLfloat *) srcRowB; - GLfloat *dst = (GLfloat *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; - } - } - return; - case MESA_FORMAT_ALPHA_FLOAT16: - case MESA_FORMAT_LUMINANCE_FLOAT16: - case MESA_FORMAT_INTENSITY_FLOAT16: - { - GLuint i, j, k; - const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; - const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; - GLhalfARB *dst = (GLhalfARB *) dstRow; - for (i = j = 0, k = k0; i < (GLuint) dstWidth; - i++, j += colStride, k += colStride) { - GLfloat aj, ak, bj, bk; - aj = _mesa_half_to_float(rowA[j]); - ak = _mesa_half_to_float(rowA[k]); - bj = _mesa_half_to_float(rowB[j]); - bk = _mesa_half_to_float(rowB[k]); - dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); - } - } - return; - - default: - _mesa_problem(NULL, "bad format in do_row()"); - } -} - - -/* - * These functions generate a 1/2-size mipmap image from a source image. - * Texture borders are handled by copying or averaging the source image's - * border texels, depending on the scale-down factor. - */ - -static void -make_1d_mipmap(const struct gl_texture_format *format, GLint border, - GLint srcWidth, const GLubyte *srcPtr, - GLint dstWidth, GLubyte *dstPtr) -{ - const GLint bpt = format->TexelBytes; - const GLubyte *src; - GLubyte *dst; - - /* skip the border pixel, if any */ - src = srcPtr + border * bpt; - dst = dstPtr + border * bpt; - - /* we just duplicate the input row, kind of hack, saves code */ - do_row(format, srcWidth - 2 * border, src, src, - dstWidth - 2 * border, dst); - - 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); - } -} - - -/** - * XXX need to use the tex image's row stride! - */ -static void -make_2d_mipmap(const struct gl_texture_format *format, GLint border, - GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr, - GLint dstWidth, GLint dstHeight, GLubyte *dstPtr) -{ - 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 srcRowStride = bpt * srcWidth; - const GLint dstRowStride = bpt * dstWidth; - const GLubyte *srcA, *srcB; - GLubyte *dst; - GLint row; - - /* Compute src and dst pointers, skipping any border */ - srcA = srcPtr + border * ((srcWidth + 1) * bpt); - if (srcHeight > 1) - srcB = srcA + srcRowStride; - else - srcB = srcA; - dst = dstPtr + border * ((dstWidth + 1) * bpt); - - for (row = 0; row < dstHeightNB; row++) { - do_row(format, srcWidthNB, srcA, srcB, - dstWidthNB, dst); - 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 */ - 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); - } - } - } -} - - -static void -make_3d_mipmap(const struct gl_texture_format *format, GLint border, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - const GLubyte *srcPtr, - GLint dstWidth, GLint dstHeight, GLint dstDepth, - GLubyte *dstPtr) -{ - const GLint bpt = format->TexelBytes; - const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ - const GLint srcDepthNB = srcDepth - 2 * border; - const GLint dstWidthNB = dstWidth - 2 * border; - const GLint dstHeightNB = dstHeight - 2 * border; - const GLint dstDepthNB = dstDepth - 2 * border; - GLvoid *tmpRowA, *tmpRowB; - GLint img, row; - GLint bytesPerSrcImage, bytesPerDstImage; - GLint bytesPerSrcRow, bytesPerDstRow; - GLint srcImageOffset, srcRowOffset; - - (void) srcDepthNB; /* silence warnings */ - - /* Need two temporary row buffers */ - tmpRowA = _mesa_malloc(srcWidth * bpt); - if (!tmpRowA) - return; - tmpRowB = _mesa_malloc(srcWidth * bpt); - if (!tmpRowB) { - _mesa_free(tmpRowA); - return; - } - - bytesPerSrcImage = srcWidth * srcHeight * bpt; - 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, - dstWidth, dstHeight, dstPtr); - /* do back border image */ - make_2d_mipmap(format, 1, srcWidth, srcHeight, - srcPtr + bytesPerSrcImage * (srcDepth - 1), - dstWidth, dstHeight, - dstPtr + bytesPerDstImage * (dstDepth - 1)); - /* 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); - } - } - } -} - - -/** - * 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, - const struct gl_texture_unit *texUnit, - 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); - - 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; - } - - /* 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; - /* 20 extra bytes, just be safe when calling last FetchTexel */ - srcData = (GLubyte *) _mesa_malloc(size); - if (!srcData) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); - return; - } - dstData = (GLubyte *) _mesa_malloc(size / 2); /* 1/4 would probably be OK */ - if (!dstData) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); - _mesa_free((void *) srcData); - return; - } - - /* decompress base image here */ - dst = (GLchan *) srcData; - for (row = 0; row < srcImage->Height; row++) { - GLuint col; - for (col = 0; col < srcImage->Width; col++) { - srcImage->FetchTexelc(srcImage, col, row, 0, dst); - dst += components; - } - } - } - else { - /* uncompressed */ - convertFormat = srcImage->TexFormat; - } - - for (level = texObj->BaseLevel; level < texObj->MaxLevel - && level < maxLevels - 1; level++) { - /* generate image[level+1] from image[level] */ - const struct gl_texture_image *srcImage; - struct gl_texture_image *dstImage; - GLint srcWidth, srcHeight, srcDepth; - GLint dstWidth, dstHeight, dstDepth; - GLint border, bytesPerTexel; - - /* get src image parameters */ - srcImage = _mesa_select_tex_image(ctx, texUnit, target, level); - ASSERT(srcImage); - srcWidth = srcImage->Width; - srcHeight = srcImage->Height; - srcDepth = srcImage->Depth; - border = srcImage->Border; - - /* compute next (level+1) image size */ - if (srcWidth - 2 * border > 1) { - dstWidth = (srcWidth - 2 * border) / 2 + 2 * border; - } - else { - dstWidth = srcWidth; /* can't go smaller */ - } - if (srcHeight - 2 * border > 1) { - dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; - } - else { - dstHeight = srcHeight; /* can't go smaller */ - } - if (srcDepth - 2 * border > 1) { - dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; - } - else { - dstDepth = srcDepth; /* can't go smaller */ - } - - if (dstWidth == srcWidth && - dstHeight == srcHeight && - dstDepth == srcDepth) { - /* all done */ - if (srcImage->IsCompressed) { - _mesa_free((void *) srcData); - _mesa_free(dstData); - } - return; - } - - /* get dest gl_texture_image */ - dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1); - if (!dstImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; - } - - /* Free old image data */ - if (dstImage->Data) - ctx->Driver.FreeTexImageData(ctx, dstImage); - - /* initialize new image */ - _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, - dstDepth, border, srcImage->InternalFormat); - dstImage->DriverData = NULL; - dstImage->TexFormat = srcImage->TexFormat; - dstImage->FetchTexelc = srcImage->FetchTexelc; - dstImage->FetchTexelf = srcImage->FetchTexelf; - dstImage->IsCompressed = srcImage->IsCompressed; - if (dstImage->IsCompressed) { - dstImage->CompressedSize - = ctx->Driver.CompressedTextureSize(ctx, dstImage->Width, - dstImage->Height, - dstImage->Depth, - dstImage->TexFormat->MesaFormat); - ASSERT(dstImage->CompressedSize > 0); - } - - ASSERT(dstImage->TexFormat); - ASSERT(dstImage->FetchTexelc); - ASSERT(dstImage->FetchTexelf); - - /* Alloc new teximage data buffer. - * Setup src and dest data pointers. - */ - if (dstImage->IsCompressed) { - dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize); - if (!dstImage->Data) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; - } - /* srcData and dstData are already set */ - ASSERT(srcData); - ASSERT(dstData); - } - else { - bytesPerTexel = dstImage->TexFormat->TexelBytes; - ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0); - dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight - * dstDepth * bytesPerTexel); - if (!dstImage->Data) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; - } - srcData = (const GLubyte *) srcImage->Data; - dstData = (GLubyte *) dstImage->Data; - } - - /* - * We use simple 2x2 averaging to compute the next mipmap level. - */ - switch (target) { - case GL_TEXTURE_1D: - make_1d_mipmap(convertFormat, border, - srcWidth, srcData, - dstWidth, dstData); - break; - case GL_TEXTURE_2D: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - make_2d_mipmap(convertFormat, border, - srcWidth, srcHeight, srcData, - dstWidth, dstHeight, dstData); - break; - case GL_TEXTURE_3D: - make_3d_mipmap(convertFormat, border, - srcWidth, srcHeight, srcDepth, srcData, - dstWidth, dstHeight, dstDepth, dstData); - break; - case GL_TEXTURE_RECTANGLE_NV: - /* no mipmaps, do nothing */ - break; - default: - _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps"); - return; - } - - if (dstImage->IsCompressed) { - GLubyte *temp; - /* compress image from dstData into dstImage->Data */ - const GLenum srcFormat = convertFormat->BaseFormat; - GLint dstRowStride - = _mesa_compressed_row_stride(dstImage->TexFormat->MesaFormat, dstWidth); - ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA); - dstImage->TexFormat->StoreImage(ctx, 2, dstImage->_BaseFormat, - dstImage->TexFormat, - dstImage->Data, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, 0, /* strides */ - dstWidth, dstHeight, 1, /* size */ - srcFormat, CHAN_TYPE, - dstData, /* src data, actually */ - &ctx->DefaultPacking); - /* swap src and dest pointers */ - temp = (GLubyte *) srcData; - srcData = dstData; - dstData = temp; - } - - } /* loop over mipmap levels */ -} - - -/** - * Helper function for drivers which need to rescale texture images to - * certain aspect ratios. - * Nearest filtering only (for broken hardware that can't support - * all aspect ratios). This can be made a lot faster, but I don't - * really care enough... - */ -void -_mesa_rescale_teximage2d (GLuint bytesPerPixel, - GLuint srcStrideInPixels, - GLuint dstRowStride, - GLint srcWidth, GLint srcHeight, - GLint dstWidth, GLint dstHeight, - const GLvoid *srcImage, GLvoid *dstImage) -{ - GLint row, col; - -#define INNER_LOOP( TYPE, HOP, WOP ) \ - for ( row = 0 ; row < dstHeight ; row++ ) { \ - GLint srcRow = row HOP hScale; \ - for ( col = 0 ; col < dstWidth ; col++ ) { \ - GLint srcCol = col WOP wScale; \ - dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \ - } \ - dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \ - } \ - -#define RESCALE_IMAGE( TYPE ) \ -do { \ - const TYPE *src = (const TYPE *)srcImage; \ - TYPE *dst = (TYPE *)dstImage; \ - \ - if ( srcHeight < dstHeight ) { \ - const GLint hScale = dstHeight / srcHeight; \ - if ( srcWidth < dstWidth ) { \ - const GLint wScale = dstWidth / srcWidth; \ - INNER_LOOP( TYPE, /, / ); \ - } \ - else { \ - const GLint wScale = srcWidth / dstWidth; \ - INNER_LOOP( TYPE, /, * ); \ - } \ - } \ - else { \ - const GLint hScale = srcHeight / dstHeight; \ - if ( srcWidth < dstWidth ) { \ - const GLint wScale = dstWidth / srcWidth; \ - INNER_LOOP( TYPE, *, / ); \ - } \ - else { \ - const GLint wScale = srcWidth / dstWidth; \ - INNER_LOOP( TYPE, *, * ); \ - } \ - } \ -} while (0) - - switch ( bytesPerPixel ) { - case 4: - RESCALE_IMAGE( GLuint ); - break; - - case 2: - RESCALE_IMAGE( GLushort ); - break; - - case 1: - RESCALE_IMAGE( GLubyte ); - break; - default: - _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d"); - } -} - - -/** - * Upscale an image by replication, not (typical) stretching. - * We use this when the image width or height is less than a - * certain size (4, 8) and we need to upscale an image. - */ -void -_mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight, - GLsizei outWidth, GLsizei outHeight, - GLint comps, const GLchan *src, GLint srcRowStride, - GLchan *dest ) -{ - GLint i, j, k; - - ASSERT(outWidth >= inWidth); - ASSERT(outHeight >= inHeight); -#if 0 - ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2); - ASSERT((outWidth & 3) == 0); - ASSERT((outHeight & 3) == 0); -#endif - - for (i = 0; i < outHeight; i++) { - const GLint ii = i % inHeight; - for (j = 0; j < outWidth; j++) { - const GLint jj = j % inWidth; - for (k = 0; k < comps; k++) { - dest[(i * outWidth + j) * comps + k] - = src[ii * srcRowStride + jj * comps + k]; - } - } - } -} #if FEATURE_EXT_texture_sRGB @@ -4380,11 +3609,29 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, GLint col; for (col = 0; col < width; col++) { (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]); + if (texImage->TexFormat->BaseFormat == GL_ALPHA) { + rgba[col][RCOMP] = 0.0; + rgba[col][GCOMP] = 0.0; + rgba[col][BCOMP] = 0.0; + } + else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE) { + rgba[col][GCOMP] = 0.0; + rgba[col][BCOMP] = 0.0; + rgba[col][ACOMP] = 1.0; + } + else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE_ALPHA) { + rgba[col][GCOMP] = 0.0; + rgba[col][BCOMP] = 0.0; + } + else if (texImage->TexFormat->BaseFormat == GL_INTENSITY) { + rgba[col][GCOMP] = 0.0; + rgba[col][BCOMP] = 0.0; + rgba[col][ACOMP] = 1.0; + } } - _mesa_pack_rgba_span_float(ctx, width, - (const GLfloat (*)[4]) rgba, - format, type, dest, &ctx->Pack, - 0 /* no image transfer */); + _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, + format, type, dest, + &ctx->Pack, 0x0 /*image xfer ops*/); } /* format */ } /* row */ } /* img */ |