X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmesa%2Fmain%2Ftexstore.c;h=5f30e03d06a7cfc266841c4e78901ac479f2d89b;hb=c1f2f9090bcca309b9aeef7ae57acc280704db81;hp=ef81dd654a93ad5a26848584e6a12c443cb31014;hpb=462183fe4cb6df6d90632d9e2cee881c8d26b1cb;p=mesa.git diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index ef81dd654a9..5f30e03d06a 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -1,6 +1,6 @@ /* * Mesa 3-D graphics library - * Version: 6.1 + * Version: 6.3 * * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * @@ -63,13 +63,25 @@ #include "texformat.h" #include "teximage.h" #include "texstore.h" -#include "texutil.h" +static const GLint ZERO = 4, ONE = 5; -/*** NEWTEXSTORE ***********************************************************/ +static GLboolean can_swizzle(GLenum logicalBaseFormat) +{ + switch (logicalBaseFormat) { + case GL_RGBA: + case GL_RGB: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_ALPHA: + case GL_LUMINANCE: + return GL_TRUE; + default: + return GL_FALSE; + } +} -static const GLint ZERO = 1000, ONE = 1001; /** * When promoting texture formats (see below) we need to compute the @@ -81,41 +93,79 @@ static const GLint ZERO = 1000, ONE = 1001; */ static void compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat, - GLint map[4]) + GLubyte map[6]) { + map[ZERO] = ZERO; + map[ONE] = ONE; + /* compute mapping from dest components back to src components */ - 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) + 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: - 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; + 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 logicalBaseFormat"); - map[0] = map[1] = map[2] = map[3] = 0; - } + map[0] = map[1] = 0; + break; + } } @@ -208,7 +258,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, /* unpack and do transfer ops up to convolution */ for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, + const GLvoid *src = _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst, @@ -242,6 +292,8 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, /* do post-convolution transfer and pack into tempImage */ { + const GLint logComponents + = _mesa_components_in_format(logicalBaseFormat); const GLfloat *src = convImage; GLfloat *dst = tempImage + img * (convWidth * convHeight * 4); for (row = 0; row < convHeight; row++) { @@ -251,7 +303,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, dst, &ctx->DefaultPacking, postConvTransferOps); src += convWidth * 4; - dst += convWidth * 4; + dst += convWidth * logComponents; } } } /* loop over 3D image slices */ @@ -278,7 +330,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, dst = tempImage; for (img = 0; img < srcDepth; img++) { const GLubyte *src - = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr, + = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); @@ -298,10 +350,11 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, GLint logComponents = _mesa_components_in_format(logicalBaseFormat); GLfloat *newImage; GLint i, n; - GLint map[4]; + GLubyte map[6]; - /* we only promote up to RGB and RGBA formats for now */ - ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA); + /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */ + ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA || + textureBaseFormat == GL_LUMINANCE_ALPHA); /* The actual texture format should have at least as many components * as the logical texture format. @@ -362,14 +415,14 @@ make_temp_float_image(GLcontext *ctx, GLuint dims, * \param srcPacking source image pixel packing * \return resulting image with format = textureBaseFormat and type = GLchan. */ -static GLchan * -make_temp_chan_image(GLcontext *ctx, GLuint dims, - GLenum logicalBaseFormat, - GLenum textureBaseFormat, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking) +GLchan * +_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, + GLenum logicalBaseFormat, + GLenum textureBaseFormat, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking) { GLuint transferOps = ctx->_ImageTransferState; const GLint components = _mesa_components_in_format(logicalBaseFormat); @@ -427,14 +480,14 @@ make_temp_chan_image(GLcontext *ctx, GLuint dims, srcWidth, srcFormat, srcType); const GLubyte *src - = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr, + = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); for (row = 0; row < srcHeight; row++) { - _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, - dst, srcFormat, srcType, src, - srcPacking, transferOps); + _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst, + srcFormat, srcType, src, srcPacking, + transferOps); dst += srcWidth * components; src += srcStride; } @@ -451,10 +504,11 @@ make_temp_chan_image(GLcontext *ctx, GLuint dims, GLint logComponents = _mesa_components_in_format(logicalBaseFormat); GLchan *newImage; GLint i, n; - GLint map[4]; + GLubyte map[6]; - /* we only promote up to RGB and RGBA formats for now */ - ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA); + /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */ + ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA || + textureBaseFormat == GL_LUMINANCE_ALPHA); /* The actual texture format should have at least as many components * as the logical texture format. @@ -492,6 +546,114 @@ make_temp_chan_image(GLcontext *ctx, GLuint dims, } +static void swizzle_copy(GLubyte *dst, + GLuint dstComponents, + const GLubyte *src, + GLuint srcComponents, + GLubyte *map, + GLuint count) +{ + GLubyte tmp[8]; + GLint i; + + tmp[ZERO] = 0x0; + tmp[ONE] = 0xff; + + switch (dstComponents) { + case 4: + for (i = 0; i < count; i++) { + COPY_4UBV(tmp, src); + src += srcComponents; + dst[0] = tmp[map[0]]; + dst[1] = tmp[map[1]]; + dst[2] = tmp[map[2]]; + dst[3] = tmp[map[3]]; + dst += 4; + } + break; + case 3: + for (i = 0; i < count; i++) { + COPY_4UBV(tmp, src); + src += srcComponents; + dst[0] = tmp[map[0]]; + dst[1] = tmp[map[1]]; + dst[2] = tmp[map[2]]; + dst += 3; + } + break; + case 2: + for (i = 0; i < count; i++) { + COPY_4UBV(tmp, src); + src += srcComponents; + dst[0] = tmp[map[0]]; + dst[1] = tmp[map[1]]; + dst += 2; + } + break; + } +} + + +static void +_mesa_swizzle_ubyte_image(GLcontext *ctx, + GLuint dimensions, + GLenum srcFormat, + const GLubyte *dstmap, GLint dstComponents, + + GLvoid *dstAddr, + GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, + GLint dstRowStride, GLint dstImageStride, + + GLint srcWidth, GLint srcHeight, GLint srcDepth, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking ) +{ + GLint srcComponents = _mesa_components_in_format(srcFormat); + GLubyte srcmap[6], map[4]; + GLint i; + + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, + srcFormat, GL_UNSIGNED_BYTE); + const GLint srcImageStride = _mesa_image_image_stride(srcPacking, + srcWidth, srcHeight, srcFormat, GL_UNSIGNED_BYTE); + const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions, + srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, GL_UNSIGNED_BYTE, 0, 0, 0); + + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstComponents; + + compute_component_mapping(srcFormat, GL_RGBA, srcmap); + + for (i = 0; i < 4; i++) + map[i] = srcmap[dstmap[i]]; + + if (srcRowStride == srcWidth * srcComponents && + (srcImageStride == srcWidth * srcHeight * srcComponents || + srcDepth == 1)) { + swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, + srcWidth * srcHeight * srcDepth); + } + else { + GLint img, row; + for (img = 0; img < srcDepth; img++) { + const GLubyte *srcRow = srcImage; + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth); + dstRow += dstRowStride; + srcRow += srcRowStride; + } + srcImage += srcImageStride; + dstImage += dstImageStride; + } + } +} + + + + /** * Teximage storage routine for when a simple memcpy will do. @@ -499,7 +661,8 @@ make_temp_chan_image(GLcontext *ctx, GLuint dims, * 1D, 2D and 3D images supported. */ static void -memcpy_texture(const struct gl_texture_format *dstFormat, +memcpy_texture(GLuint dimensions, + const struct gl_texture_format *dstFormat, GLvoid *dstAddr, GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, GLint dstRowStride, GLint dstImageStride, @@ -512,8 +675,8 @@ memcpy_texture(const struct gl_texture_format *dstFormat, srcFormat, srcType); const GLint srcImageStride = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat, srcType); - const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions, + srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes; const GLint bytesPerImage = srcHeight * bytesPerRow; const GLint bytesPerTexture = srcDepth * bytesPerImage; @@ -603,7 +766,8 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims, baseInternalFormat == srcFormat && srcType == CHAN_TYPE) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); @@ -622,9 +786,8 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims, for (img = 0; img < srcDepth; img++) { const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); - GLchan *srcRow = _mesa_image_address(srcPacking, srcAddr, srcWidth, - srcHeight, srcFormat, srcType, - img, 0, 0); + GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); GLchan *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { for (col = 0; col < srcWidth; col++) { @@ -640,14 +803,14 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims, } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); const GLchan *src = tempImage; - const GLint bytesPerRow = srcWidth * components * sizeof(GLchan); + GLint bytesPerRow; GLubyte *dstImage = (GLubyte *) dstAddr + dstZoffset * dstImageStride + dstYoffset * dstRowStride @@ -656,6 +819,7 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims, if (!tempImage) return GL_FALSE; _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + bytesPerRow = srcWidth * components * sizeof(GLchan); for (img = 0; img < srcDepth; img++) { GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { @@ -672,56 +836,13 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims, } -/** - * Store a color index texture image - */ -GLboolean -_mesa_texstore_color_index(STORE_PARAMS) -{ - ASSERT(dstFormat == &_mesa_texformat_color_index); - ASSERT(dstFormat->TexelBytes == 1 * sizeof(GLchan)); - - if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - baseInternalFormat == GL_COLOR_INDEX && - srcFormat == GL_COLOR_INDEX && - srcType == CHAN_TYPE) { - /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, - dstRowStride, dstImageStride, - srcWidth, srcHeight, srcDepth, srcFormat, srcType, - srcAddr, srcPacking); - } - else { - /* general path */ - GLubyte *dstImage = (GLubyte *) dstAddr - + dstZoffset * dstImageStride - + dstYoffset * dstRowStride - + dstXoffset * dstFormat->TexelBytes; - GLint img, row; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstImage; - for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); - _mesa_unpack_index_span(ctx, srcWidth, CHAN_TYPE, dstRow, - srcType, src, srcPacking, - ctx->_ImageTransferState); - dstRow += dstRowStride; - } - dstImage += dstImageStride; - } - } - return GL_TRUE; -} - - /** * Store a floating point depth component texture image. */ GLboolean _mesa_texstore_depth_component_float32(STORE_PARAMS) { + (void) dims; ASSERT(dstFormat == &_mesa_texformat_depth_component_float32); ASSERT(dstFormat->TexelBytes == sizeof(GLfloat)); @@ -731,7 +852,8 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS) srcFormat == GL_DEPTH_COMPONENT && srcType == GL_FLOAT) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); @@ -746,7 +868,7 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS) for (img = 0; img < srcDepth; img++) { GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, + const GLvoid *src = _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) dstRow, srcType, src, srcPacking); @@ -765,6 +887,7 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS) GLboolean _mesa_texstore_depth_component16(STORE_PARAMS) { + (void) dims; ASSERT(dstFormat == &_mesa_texformat_depth_component16); ASSERT(dstFormat->TexelBytes == sizeof(GLushort)); @@ -774,7 +897,8 @@ _mesa_texstore_depth_component16(STORE_PARAMS) srcFormat == GL_DEPTH_COMPONENT && srcType == GL_UNSIGNED_SHORT) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); @@ -790,7 +914,7 @@ _mesa_texstore_depth_component16(STORE_PARAMS) GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { GLfloat depthTemp[MAX_WIDTH]; - const GLvoid *src = _mesa_image_address(srcPacking, + const GLvoid *src = _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); GLushort *dst16 = (GLushort *) dstRow; _mesa_unpack_depth_span(ctx, srcWidth, depthTemp, @@ -807,24 +931,25 @@ _mesa_texstore_depth_component16(STORE_PARAMS) } - - /** - * Store an rgb565 texture image. + * Store an rgb565 or rgb565_rev texture image. */ GLboolean _mesa_texstore_rgb565(STORE_PARAMS) { - ASSERT(dstFormat == &_mesa_texformat_rgb565); + ASSERT(dstFormat == &_mesa_texformat_rgb565 || + dstFormat == &_mesa_texformat_rgb565_rev); ASSERT(dstFormat->TexelBytes == 2); if (!ctx->_ImageTransferState && !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_rgb565 && baseInternalFormat == GL_RGB && srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); @@ -839,7 +964,7 @@ _mesa_texstore_rgb565(STORE_PARAMS) const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); const GLubyte *src = (const GLubyte *) - _mesa_image_address(srcPacking, srcAddr, srcWidth, srcHeight, + _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); GLubyte *dst = (GLubyte *) dstAddr + dstZoffset * dstImageStride @@ -849,9 +974,18 @@ _mesa_texstore_rgb565(STORE_PARAMS) for (row = 0; row < srcHeight; row++) { const GLubyte *srcUB = (const GLubyte *) src; GLushort *dstUS = (GLushort *) dst; - for (col = 0; col < srcWidth; col++) { - dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] ); - srcUB += 3; + /* check for byteswapped format */ + if (dstFormat == &_mesa_texformat_rgb565) { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] ); + srcUB += 3; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] ); + srcUB += 3; + } } dst += dstRowStride; src += srcRowStride; @@ -859,7 +993,7 @@ _mesa_texstore_rgb565(STORE_PARAMS) } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, @@ -878,11 +1012,22 @@ _mesa_texstore_rgb565(STORE_PARAMS) GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { GLushort *dstUS = (GLushort *) dstRow; - for (col = 0; col < srcWidth; col++) { - dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]), - CHAN_TO_UBYTE(src[GCOMP]), - CHAN_TO_UBYTE(src[BCOMP]) ); - src += 3; + /* check for byteswapped format */ + if (dstFormat == &_mesa_texformat_rgb565) { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 3; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 3; + } } dstRow += dstRowStride; } @@ -900,24 +1045,54 @@ _mesa_texstore_rgba8888(STORE_PARAMS) const GLuint ui = 1; const GLubyte littleEndian = *((const GLubyte *) &ui); - ASSERT(dstFormat == &_mesa_texformat_rgba8888); + (void)littleEndian; + ASSERT(dstFormat == &_mesa_texformat_rgba8888 || + dstFormat == &_mesa_texformat_rgba8888_rev); ASSERT(dstFormat->TexelBytes == 4); if (!ctx->_ImageTransferState && !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_rgba8888 && baseInternalFormat == GL_RGBA && - srcFormat == GL_RGBA && - ((srcType == GL_UNSIGNED_INT_8_8_8_8_REV && littleEndian) || - (srcType == GL_UNSIGNED_INT_8_8_8_8 && !littleEndian))) { + ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) || + (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } +#if 0 + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + srcType == GL_UNSIGNED_BYTE && + dstFormat == &_mesa_texformat_rgba8888 && + littleEndian && + can_swizzle(srcFormat)) { + GLubyte dstmap[4]; + + /* dstmap - how to swizzle from GL_RGBA to dst format: + * + * FIXME - add !litteEndian and _rev varients: + */ + dstmap[3] = 0; + dstmap[2] = 1; + dstmap[1] = 2; + dstmap[0] = 3; + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + dstmap, 4, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } +#endif else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, @@ -936,12 +1111,23 @@ _mesa_texstore_rgba8888(STORE_PARAMS) GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { GLuint *dstUI = (GLuint *) dstRow; - for (col = 0; col < srcWidth; col++) { - dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]), - CHAN_TO_UBYTE(src[GCOMP]), - CHAN_TO_UBYTE(src[BCOMP]), - CHAN_TO_UBYTE(src[ACOMP]) ); - src += 4; + if (dstFormat == &_mesa_texformat_rgba8888) { + for (col = 0; col < srcWidth; col++) { + dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]), + CHAN_TO_UBYTE(src[ACOMP]) ); + src += 4; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]), + CHAN_TO_UBYTE(src[ACOMP]) ); + src += 4; + } } dstRow += dstRowStride; } @@ -959,25 +1145,125 @@ _mesa_texstore_argb8888(STORE_PARAMS) const GLuint ui = 1; const GLubyte littleEndian = *((const GLubyte *) &ui); - ASSERT(dstFormat == &_mesa_texformat_argb8888); + ASSERT(dstFormat == &_mesa_texformat_argb8888 || + dstFormat == &_mesa_texformat_argb8888_rev); ASSERT(dstFormat->TexelBytes == 4); if (!ctx->_ImageTransferState && !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && baseInternalFormat == GL_RGBA && srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && littleEndian) || - (srcType == GL_UNSIGNED_INT_8_8_8_8_REV && littleEndian) || - (srcType == GL_UNSIGNED_INT_8_8_8_8 && !littleEndian))) { - /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) { + /* simple memcpy path (little endian) */ + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888_rev && + baseInternalFormat == GL_RGBA && + srcFormat == GL_BGRA && + ((srcType == GL_UNSIGNED_BYTE && !littleEndian) || + srcType == GL_UNSIGNED_INT_8_8_8_8)) { + /* simple memcpy path (big endian) */ + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_BYTE) { + + int img, row, col; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP]; + dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP]; + dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP]; + dstRow[col * 4 + 3] = 0xff; + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && + srcFormat == GL_RGBA && + srcType == GL_UNSIGNED_BYTE) { + + int img, row, col; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP]; + dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP]; + dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP]; + dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP]; + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && + srcType == GL_UNSIGNED_BYTE && + littleEndian && + can_swizzle(srcFormat)) { + + GLubyte dstmap[4]; + + /* dstmap - how to swizzle from GL_RGBA to dst format: + */ + dstmap[3] = 3; /* alpha */ + dstmap[2] = 0; /* red */ + dstmap[1] = 1; /* green */ + dstmap[0] = 2; /* blue */ + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + dstmap, 4, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, @@ -996,12 +1282,23 @@ _mesa_texstore_argb8888(STORE_PARAMS) GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { GLuint *dstUI = (GLuint *) dstRow; - for (col = 0; col < srcWidth; col++) { - dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]), - CHAN_TO_UBYTE(src[RCOMP]), - CHAN_TO_UBYTE(src[GCOMP]), - CHAN_TO_UBYTE(src[BCOMP]) ); - src += 4; + if (dstFormat == &_mesa_texformat_argb8888) { + for (col = 0; col < srcWidth; col++) { + dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } } dstRow += dstRowStride; } @@ -1013,7 +1310,6 @@ _mesa_texstore_argb8888(STORE_PARAMS) } - GLboolean _mesa_texstore_rgb888(STORE_PARAMS) { @@ -1030,7 +1326,8 @@ _mesa_texstore_rgb888(STORE_PARAMS) srcType == GL_UNSIGNED_BYTE && littleEndian) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); @@ -1039,7 +1336,7 @@ _mesa_texstore_rgb888(STORE_PARAMS) !srcPacking->SwapBytes && srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* extract BGR from RGBA */ + /* extract RGB from RGBA */ int img, row, col; GLubyte *dstImage = (GLubyte *) dstAddr + dstZoffset * dstImageStride @@ -1048,9 +1345,8 @@ _mesa_texstore_rgb888(STORE_PARAMS) for (img = 0; img < srcDepth; img++) { const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); - GLubyte *srcRow = _mesa_image_address(srcPacking, srcAddr, srcWidth, - srcHeight, srcFormat, srcType, - img, 0, 0); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { for (col = 0; col < srcWidth; col++) { @@ -1066,13 +1362,13 @@ _mesa_texstore_rgb888(STORE_PARAMS) } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); - const GLchan *src = (const GLubyte *) tempImage; + const GLchan *src = (const GLchan *) tempImage; GLubyte *dstImage = (GLubyte *) dstAddr + dstZoffset * dstImageStride + dstYoffset * dstRowStride @@ -1120,29 +1416,114 @@ _mesa_texstore_rgb888(STORE_PARAMS) GLboolean -_mesa_texstore_argb4444(STORE_PARAMS) +_mesa_texstore_bgr888(STORE_PARAMS) { const GLuint ui = 1; const GLubyte littleEndian = *((const GLubyte *) &ui); - ASSERT(dstFormat == &_mesa_texformat_argb4444); + ASSERT(dstFormat == &_mesa_texformat_bgr888); + ASSERT(dstFormat->TexelBytes == 3); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_BYTE && + littleEndian) { + /* simple memcpy path */ + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + srcFormat == GL_RGBA && + srcType == GL_UNSIGNED_BYTE) { + /* extract BGR from RGBA */ + int img, row, col; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP]; + dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; + dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP]; + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = (const GLchan *) tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]); + dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); + dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]); + src += 3; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_argb4444(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_argb4444 || + dstFormat == &_mesa_texformat_argb4444_rev); ASSERT(dstFormat->TexelBytes == 2); if (!ctx->_ImageTransferState && !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb4444 && baseInternalFormat == GL_RGBA && srcFormat == GL_BGRA && - ((srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV && littleEndian) || - (srcType == GL_UNSIGNED_SHORT_4_4_4_4 && !littleEndian))) { + srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, @@ -1161,12 +1542,23 @@ _mesa_texstore_argb4444(STORE_PARAMS) GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { GLushort *dstUS = (GLushort *) dstRow; - for (col = 0; col < srcWidth; col++) { - dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]), - CHAN_TO_UBYTE(src[RCOMP]), - CHAN_TO_UBYTE(src[GCOMP]), - CHAN_TO_UBYTE(src[BCOMP]) ); - src += 4; + if (dstFormat == &_mesa_texformat_argb4444) { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } } dstRow += dstRowStride; } @@ -1178,30 +1570,30 @@ _mesa_texstore_argb4444(STORE_PARAMS) } + GLboolean _mesa_texstore_argb1555(STORE_PARAMS) { - const GLuint ui = 1; - const GLubyte littleEndian = *((const GLubyte *) &ui); - - ASSERT(dstFormat == &_mesa_texformat_argb1555); + ASSERT(dstFormat == &_mesa_texformat_argb1555 || + dstFormat == &_mesa_texformat_argb1555_rev); ASSERT(dstFormat->TexelBytes == 2); if (!ctx->_ImageTransferState && !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb1555 && baseInternalFormat == GL_RGBA && srcFormat == GL_BGRA && - ((srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV && littleEndian) || - (srcType == GL_UNSIGNED_SHORT_5_5_5_1 && !littleEndian))) { + srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, @@ -1220,12 +1612,23 @@ _mesa_texstore_argb1555(STORE_PARAMS) GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { GLushort *dstUS = (GLushort *) dstRow; - for (col = 0; col < srcWidth; col++) { - dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]), - CHAN_TO_UBYTE(src[RCOMP]), - CHAN_TO_UBYTE(src[GCOMP]), - CHAN_TO_UBYTE(src[BCOMP]) ); - src += 4; + if (dstFormat == &_mesa_texformat_argb1555) { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } } dstRow += dstRowStride; } @@ -1243,24 +1646,27 @@ _mesa_texstore_al88(STORE_PARAMS) const GLuint ui = 1; const GLubyte littleEndian = *((const GLubyte *) &ui); - ASSERT(dstFormat == &_mesa_texformat_al88); + ASSERT(dstFormat == &_mesa_texformat_al88 || + dstFormat == &_mesa_texformat_al88_rev); ASSERT(dstFormat->TexelBytes == 2); if (!ctx->_ImageTransferState && !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_al88 && baseInternalFormat == GL_LUMINANCE_ALPHA && srcFormat == GL_LUMINANCE_ALPHA && srcType == GL_UNSIGNED_BYTE && littleEndian) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, @@ -1279,10 +1685,21 @@ _mesa_texstore_al88(STORE_PARAMS) GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { GLushort *dstUS = (GLushort *) dstRow; - for (col = 0; col < srcWidth; col++) { - dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[ACOMP]), - CHAN_TO_UBYTE(src[RCOMP]) ); - src += 2; + if (dstFormat == &_mesa_texformat_al88) { + for (col = 0; col < srcWidth; col++) { + /* src[0] is luminance, src[1] is alpha */ + dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]), + CHAN_TO_UBYTE(src[0]) ); + src += 2; + } + } + else { + for (col = 0; col < srcWidth; col++) { + /* src[0] is luminance, src[1] is alpha */ + dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]), + CHAN_TO_UBYTE(src[0]) ); + src += 2; + } } dstRow += dstRowStride; } @@ -1305,14 +1722,15 @@ _mesa_texstore_rgb332(STORE_PARAMS) baseInternalFormat == GL_RGB && srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, @@ -1346,7 +1764,6 @@ _mesa_texstore_rgb332(STORE_PARAMS) } - /** * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8. */ @@ -1363,14 +1780,15 @@ _mesa_texstore_a8(STORE_PARAMS) baseInternalFormat == srcFormat && srcType == GL_UNSIGNED_BYTE) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); } else { /* general path */ - const GLchan *tempImage = make_temp_chan_image(ctx, dims, + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, @@ -1406,6 +1824,7 @@ _mesa_texstore_a8(STORE_PARAMS) GLboolean _mesa_texstore_ci8(STORE_PARAMS) { + (void) dims; (void) baseInternalFormat; ASSERT(dstFormat == &_mesa_texformat_ci8); ASSERT(dstFormat->TexelBytes == 1); ASSERT(baseInternalFormat == GL_COLOR_INDEX); @@ -1415,7 +1834,8 @@ _mesa_texstore_ci8(STORE_PARAMS) srcFormat == GL_COLOR_INDEX && srcType == GL_UNSIGNED_BYTE) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); @@ -1430,7 +1850,7 @@ _mesa_texstore_ci8(STORE_PARAMS) for (img = 0; img < srcDepth; img++) { GLubyte *dstRow = dstImage; for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, + const GLvoid *src = _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow, srcType, src, srcPacking, @@ -1452,6 +1872,7 @@ _mesa_texstore_ycbcr(STORE_PARAMS) { const GLuint ui = 1; const GLubyte littleEndian = *((const GLubyte *) &ui); + (void) ctx; (void) dims; (void) baseInternalFormat; ASSERT((dstFormat == &_mesa_texformat_ycbcr) || (dstFormat == &_mesa_texformat_ycbcr_rev)); @@ -1463,7 +1884,8 @@ _mesa_texstore_ycbcr(STORE_PARAMS) ASSERT(baseInternalFormat == GL_YCBCR_MESA); /* always just memcpy since no pixel transfer ops apply */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); @@ -1527,7 +1949,8 @@ _mesa_texstore_rgba_float32(STORE_PARAMS) baseInternalFormat == srcFormat && srcType == GL_FLOAT) { /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, dstRowStride, dstImageStride, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); @@ -1541,7 +1964,7 @@ _mesa_texstore_rgba_float32(STORE_PARAMS) srcFormat, srcType, srcAddr, srcPacking); const GLfloat *src = tempImage; - const GLint bytesPerRow = srcWidth * components * sizeof(GLfloat); + GLint bytesPerRow; GLubyte *dstImage = (GLubyte *) dstAddr + dstZoffset * dstImageStride + dstYoffset * dstRowStride @@ -1550,6 +1973,7 @@ _mesa_texstore_rgba_float32(STORE_PARAMS) if (!tempImage) return GL_FALSE; _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + bytesPerRow = srcWidth * components * sizeof(GLfloat); for (img = 0; img < srcDepth; img++) { GLubyte *dst = dstImage; for (row = 0; row < srcHeight; row++) { @@ -1587,793 +2011,147 @@ _mesa_texstore_rgba_float16(STORE_PARAMS) baseInternalFormat == GL_LUMINANCE_ALPHA || baseInternalFormat == GL_INTENSITY); ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB)); - - if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - baseInternalFormat == srcFormat && - srcType == GL_HALF_FLOAT_ARB) { - /* simple memcpy path */ - memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, - dstRowStride, dstImageStride, - srcWidth, srcHeight, srcDepth, srcFormat, srcType, - srcAddr, srcPacking); - } - else { - /* general path */ - const GLfloat *tempImage = make_temp_float_image(ctx, dims, - baseInternalFormat, - dstFormat->BaseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking); - const GLfloat *src = tempImage; - GLubyte *dstImage = (GLubyte *) dstAddr - + dstZoffset * dstImageStride - + dstYoffset * dstRowStride - + dstXoffset * dstFormat->TexelBytes; - GLint img, row; - if (!tempImage) - return GL_FALSE; - _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstImage; - for (row = 0; row < srcHeight; row++) { - GLhalfARB *dstTexel = (GLhalfARB *) dstRow; - GLint i; - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = _mesa_float_to_half(src[i]); - } - dstRow += dstRowStride; - src += srcWidth * components; - } - dstImage += dstImageStride; - } - - _mesa_free((void *) tempImage); - } - return GL_TRUE; -} - - -#if !NEWTEXSTORE /*****************************************************/ - - -/* - * Given an internal texture format enum or 1, 2, 3, 4 return the - * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, - * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the - * number of components for the format. Return -1 if invalid enum. - */ -static GLint -components_in_intformat( GLint format ) -{ - switch (format) { - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - return 1; - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - return 1; - case 2: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - return 2; - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - return 1; - case 3: - case GL_RGB: - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB5: - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - return 3; - case 4: - case GL_RGBA: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - return 4; - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - return 1; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16_SGIX: - case GL_DEPTH_COMPONENT24_SGIX: - case GL_DEPTH_COMPONENT32_SGIX: - return 1; - case GL_YCBCR_MESA: - return 2; /* Y + (Cb or Cr) */ - default: - return -1; /* error */ - } -} - - -/* - * This function is used to transfer the user's image data into a texture - * image buffer. We handle both full texture images and subtexture images. - * We also take care of all image transfer operations here, including - * convolution, scale/bias, colortables, etc. - * - * The destination texel type is always GLchan. - * The destination texel format is one of the 6 basic types. - * - * A hardware driver may use this as a helper routine to unpack and - * apply pixel transfer ops into a temporary image buffer. Then, - * convert the temporary image into the special hardware format. - * - * \param - * dimensions - 1, 2, or 3 - * texDestFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA, - * GL_RGB or GL_RGBA (the destination format) - * texDestAddr - destination image address - * srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images - * dstXoffset, dstYoffset, dstZoffset - position to store the image within - * the destination 3D texture - * dstRowStride, dstImageStride - dest image strides in bytes - * srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc) - * srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc - * srcPacking - describes packing of incoming image. - * transferOps - mask of pixel transfer operations - */ -static void -transfer_teximage(GLcontext *ctx, GLuint dimensions, - GLenum texDestFormat, GLvoid *texDestAddr, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, - GLint dstRowStride, GLint dstImageStride, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking, - GLuint transferOps) -{ - GLint texComponents; - - ASSERT(ctx); - ASSERT(dimensions >= 1 && dimensions <= 3); - ASSERT(texDestFormat == GL_LUMINANCE || - texDestFormat == GL_INTENSITY || - texDestFormat == GL_LUMINANCE_ALPHA || - texDestFormat == GL_ALPHA || - texDestFormat == GL_RGB || - texDestFormat == GL_RGBA || - texDestFormat == GL_COLOR_INDEX || - texDestFormat == GL_DEPTH_COMPONENT); - ASSERT(texDestAddr); - ASSERT(srcWidth >= 0); - ASSERT(srcHeight >= 0); - ASSERT(srcDepth >= 0); - ASSERT(dstXoffset >= 0); - ASSERT(dstYoffset >= 0); - ASSERT(dstZoffset >= 0); - ASSERT(dstRowStride >= 0); - ASSERT(dstImageStride >= 0); - ASSERT(srcAddr); - ASSERT(srcPacking); - - texComponents = components_in_intformat(texDestFormat); - - /* try common 2D texture cases first */ - if (!transferOps && dimensions == 2 && srcType == CHAN_TYPE) { - - if (srcFormat == texDestFormat) { - /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA, - * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy(). - */ - const GLchan *src = (const GLchan *) _mesa_image_address( - srcPacking, srcAddr, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcRowStride = _mesa_image_row_stride(srcPacking, - srcWidth, srcFormat, srcType); - const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan); - GLchan *dst = (GLchan *) texDestAddr - + dstYoffset * (dstRowStride / sizeof(GLchan)) - + dstXoffset * texComponents; - if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) { - MEMCPY(dst, src, srcHeight * widthInBytes); - } - else { - GLint i; - for (i = 0; i < srcHeight; i++) { - MEMCPY(dst, src, widthInBytes); - src += (srcRowStride / sizeof(GLchan)); - dst += (dstRowStride / sizeof(GLchan)); - } - } - return; /* all done */ - } - else if (srcFormat == GL_RGBA && texDestFormat == GL_RGB) { - /* commonly used by Quake */ - const GLchan *src = (const GLchan *) _mesa_image_address( - srcPacking, srcAddr, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcRowStride = _mesa_image_row_stride(srcPacking, - srcWidth, srcFormat, srcType); - GLchan *dst = (GLchan *) texDestAddr - + dstYoffset * (dstRowStride / sizeof(GLchan)) - + dstXoffset * texComponents; - GLint i, j; - for (i = 0; i < srcHeight; i++) { - const GLchan *s = src; - GLchan *d = dst; - for (j = 0; j < srcWidth; j++) { - *d++ = *s++; /*red*/ - *d++ = *s++; /*green*/ - *d++ = *s++; /*blue*/ - s++; /*alpha*/ - } - src += (srcRowStride / sizeof(GLchan)); - dst += (dstRowStride / sizeof(GLchan)); - } - return; /* all done */ - } - } - - /* - * General case solutions - */ - if (texDestFormat == GL_COLOR_INDEX) { - /* color index texture */ - const GLenum texType = CHAN_TYPE; - GLint img, row; - GLchan *dest = (GLchan *) texDestAddr - + dstZoffset * (dstImageStride / sizeof(GLchan)) - + dstYoffset * (dstRowStride / sizeof(GLchan)) - + dstXoffset * texComponents; - for (img = 0; img < srcDepth; img++) { - GLchan *destRow = dest; - for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); - _mesa_unpack_index_span(ctx, srcWidth, texType, destRow, - srcType, src, srcPacking, transferOps); - destRow += (dstRowStride / sizeof(GLchan)); - } - dest += dstImageStride; - } - } - else if (texDestFormat == GL_YCBCR_MESA) { - /* YCbCr texture */ - GLint img, row; - GLushort *dest = (GLushort *) texDestAddr - + dstZoffset * (dstImageStride / sizeof(GLushort)) - + dstYoffset * (dstRowStride / sizeof(GLushort)) - + dstXoffset * texComponents; - ASSERT(ctx->Extensions.MESA_ycbcr_texture); - for (img = 0; img < srcDepth; img++) { - GLushort *destRow = dest; - for (row = 0; row < srcHeight; row++) { - const GLvoid *srcRow = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, - srcFormat, srcType, img, row, 0); - MEMCPY(destRow, srcRow, srcWidth * sizeof(GLushort)); - destRow += (dstRowStride / sizeof(GLushort)); - } - dest += dstImageStride / sizeof(GLushort); - } - } - else if (texDestFormat == GL_DEPTH_COMPONENT) { - /* Depth texture (shadow maps) */ - GLint img, row; - GLubyte *dest = (GLubyte *) texDestAddr - + dstZoffset * dstImageStride - + dstYoffset * (dstRowStride / sizeof(GLchan)) - + dstXoffset * texComponents; - for (img = 0; img < srcDepth; img++) { - GLubyte *destRow = dest; - for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); - _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) destRow, - srcType, src, srcPacking); - destRow += (dstRowStride / sizeof(GLchan)); - } - dest += dstImageStride; - } - } - else { - /* regular, color texture */ - if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) || - (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) || - (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) { - /* - * Fill texture image with convolution - */ - GLint img, row; - GLint convWidth = srcWidth, convHeight = srcHeight; - GLfloat *tmpImage, *convImage; - tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat)); - if (!tmpImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); - return; - } - convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat)); - if (!convImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); - FREE(tmpImage); - return; - } - - for (img = 0; img < srcDepth; img++) { - const GLfloat *srcf; - GLfloat *dstf = tmpImage; - GLchan *dest; - - /* unpack and do transfer ops up to convolution */ - for (row = 0; row < srcHeight; row++) { - const GLvoid *src = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, - srcFormat, srcType, img, row, 0); - _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dstf, - srcFormat, srcType, src, srcPacking, - (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT); - dstf += srcWidth * 4; - } - - /* convolve */ - if (dimensions == 1) { - ASSERT(ctx->Pixel.Convolution1DEnabled); - _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage); - } - else { - if (ctx->Pixel.Convolution2DEnabled) { - _mesa_convolve_2d_image(ctx, &convWidth, &convHeight, - tmpImage, convImage); - } - else { - ASSERT(ctx->Pixel.Separable2DEnabled); - _mesa_convolve_sep_image(ctx, &convWidth, &convHeight, - tmpImage, convImage); - } - } - - /* packing and transfer ops after convolution */ - srcf = convImage; - dest = (GLchan *) texDestAddr - + (dstZoffset + img) * (dstImageStride / sizeof(GLchan)) - + dstYoffset * (dstRowStride / sizeof(GLchan)); - for (row = 0; row < convHeight; row++) { - _mesa_pack_rgba_span_float(ctx, convWidth, - (const GLfloat (*)[4]) srcf, - texDestFormat, CHAN_TYPE, - dest, &ctx->DefaultPacking, - transferOps - & IMAGE_POST_CONVOLUTION_BITS); - srcf += convWidth * 4; - dest += (dstRowStride / sizeof(GLchan)); - } - } - - FREE(convImage); - FREE(tmpImage); - } - else { - /* - * no convolution - */ - GLint img, row; - GLchan *dest = (GLchan *) texDestAddr - + dstZoffset * (dstImageStride / sizeof(GLchan)) - + dstYoffset * (dstRowStride / sizeof(GLchan)) - + dstXoffset * texComponents; - for (img = 0; img < srcDepth; img++) { - GLchan *destRow = dest; - for (row = 0; row < srcHeight; row++) { - const GLvoid *srcRow = _mesa_image_address(srcPacking, - srcAddr, srcWidth, srcHeight, - srcFormat, srcType, img, row, 0); - _mesa_unpack_color_span_chan(ctx, srcWidth, texDestFormat, - destRow, srcFormat, srcType, srcRow, - srcPacking, transferOps); - destRow += (dstRowStride / sizeof(GLchan)); - } - dest += dstImageStride / sizeof(GLchan); - } - } - } -} - - - -/* - * Transfer a texture image from user space to applying all - * needed image transfer operations and storing the result in the format - * specified by . may be any format from texformat.h. - * \param - * dimensions - 1, 2 or 3 - * baseInternalFormat - base format of the internal texture format - * specified by the user. This is very important, see below. - * dstFormat - destination image format - * dstAddr - destination address - * srcWidth, srcHeight, srcDepth - size of source iamge - * dstX/Y/Zoffset - as specified by glTexSubImage - * dstRowStride - stride between dest rows in bytes - * dstImageStride - stride between dest images in bytes - * srcFormat, srcType - incoming image format and data type - * srcAddr - source image address - * srcPacking - packing params of source image - * - * XXX this function is a bit more complicated than it should be. If - * _mesa_convert_texsubimage[123]d could handle any dest/source formats - * or if transfer_teximage() could store in any MESA_FORMAT_* format, we - * could simplify things here. - */ -void -_mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions, - GLenum baseInternalFormat, - const struct gl_texture_format *dstFormat, - GLvoid *dstAddr, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, - GLint dstRowStride, GLint dstImageStride, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking) -{ - const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes; - const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes; - GLboolean makeTemp; - GLuint transferOps = ctx->_ImageTransferState; - GLboolean freeSourceData = GL_FALSE; - GLint postConvWidth = srcWidth, postConvHeight = srcHeight; - - assert(baseInternalFormat > 0); - ASSERT(baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_INTENSITY || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_YCBCR_MESA || - baseInternalFormat == GL_COLOR_INDEX || - baseInternalFormat == GL_DEPTH_COMPONENT); - - if (transferOps & IMAGE_CONVOLUTION_BIT) { - _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth, - &postConvHeight); - } - - /* - * Consider this scenario: The user's source image is GL_RGB and the - * requested internal format is GL_LUMINANCE. Now suppose the device - * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the - * texture format. In that case we still need to do an intermediate - * conversion to luminance format so that the incoming red channel gets - * replicated into the dest red, green and blue channels. The following - * code takes care of that. - */ - if (dstFormat->BaseFormat != baseInternalFormat) { - /* Allocate storage for temporary image in the baseInternalFormat */ - const GLint texelSize = _mesa_components_in_format(baseInternalFormat) - * sizeof(GLchan); - const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth; - const GLint tmpRowStride = texelSize * postConvWidth; - const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight; - GLvoid *tmpImage = MALLOC(bytes); - if (!tmpImage) - return; - transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage, - srcWidth, srcHeight, srcDepth, - 0, 0, 0, /* x/y/zoffset */ - tmpRowStride, tmpImgStride, - srcFormat, srcType, srcAddr, srcPacking, transferOps); - - /* this is our new source image */ - srcWidth = postConvWidth; - srcHeight = postConvHeight; - srcFormat = baseInternalFormat; - srcType = CHAN_TYPE; - srcAddr = tmpImage; - srcPacking = &ctx->DefaultPacking; - freeSourceData = GL_TRUE; - transferOps = 0; /* image transfer ops were completed */ - } - - /* Let the optimized tex conversion functions take a crack at the - * image conversion if the dest format is a h/w format. - */ - if (_mesa_is_hardware_tex_format(dstFormat)) { - if (transferOps) { - makeTemp = GL_TRUE; - } - else { - if (dimensions == 1) { - makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat, - dstXoffset, - srcWidth, - srcFormat, srcType, - srcPacking, srcAddr, - dstAddr); - } - else if (dimensions == 2) { - makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat, - dstXoffset, dstYoffset, - srcWidth, srcHeight, - dstRowStridePixels, - srcFormat, srcType, - srcPacking, srcAddr, - dstAddr); - } - else { - assert(dimensions == 3); - makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat, - dstXoffset, dstYoffset, dstZoffset, - srcWidth, srcHeight, srcDepth, - dstRowStridePixels, dstImageStridePixels, - srcFormat, srcType, - srcPacking, srcAddr, dstAddr); - } - if (!makeTemp) { - /* all done! */ - if (freeSourceData) - FREE((void *) srcAddr); - return; - } - } + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == srcFormat && + srcType == GL_HALF_FLOAT_ARB) { + /* simple memcpy path */ + memcpy_texture(dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); } else { - /* software texture format */ - makeTemp = GL_FALSE; - } - - if (makeTemp) { - GLint postConvWidth = srcWidth, postConvHeight = srcHeight; - GLenum tmpFormat; - GLuint tmpComps, tmpTexelSize; - GLint tmpRowStride, tmpImageStride; - GLubyte *tmpImage; - - if (transferOps & IMAGE_CONVOLUTION_BIT) { - _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth, - &postConvHeight); - } - - tmpFormat = dstFormat->BaseFormat; - tmpComps = _mesa_components_in_format(tmpFormat); - tmpTexelSize = tmpComps * sizeof(GLchan); - tmpRowStride = postConvWidth * tmpTexelSize; - tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize; - tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight * - srcDepth * tmpTexelSize); - if (!tmpImage) { - if (freeSourceData) - FREE((void *) srcAddr); - return; + /* general path */ + const GLfloat *tempImage = make_temp_float_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLfloat *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLhalfARB *dstTexel = (GLhalfARB *) dstRow; + GLint i; + for (i = 0; i < srcWidth * components; i++) { + dstTexel[i] = _mesa_float_to_half(src[i]); + } + dstRow += dstRowStride; + src += srcWidth * components; + } + dstImage += dstImageStride; } - transfer_teximage(ctx, dimensions, tmpFormat, tmpImage, - srcWidth, srcHeight, srcDepth, - 0, 0, 0, /* x/y/zoffset */ - tmpRowStride, tmpImageStride, - srcFormat, srcType, srcAddr, srcPacking, transferOps); - - if (freeSourceData) - FREE((void *) srcAddr); - - /* the temp image is our new source image */ - srcWidth = postConvWidth; - srcHeight = postConvHeight; - srcFormat = tmpFormat; - srcType = CHAN_TYPE; - srcAddr = tmpImage; - srcPacking = &ctx->DefaultPacking; - freeSourceData = GL_TRUE; - } - - if (_mesa_is_hardware_tex_format(dstFormat)) { - assert(makeTemp); - if (dimensions == 1) { - GLboolean b; - b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat, - dstXoffset, - srcWidth, - srcFormat, srcType, - srcPacking, srcAddr, - dstAddr); - assert(b); - (void) b; - } - else if (dimensions == 2) { - GLboolean b; - b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat, - dstXoffset, dstYoffset, - srcWidth, srcHeight, - dstRowStridePixels, - srcFormat, srcType, - srcPacking, srcAddr, - dstAddr); - assert(b); - (void) b; - } - else { - GLboolean b; - b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat, - dstXoffset, dstYoffset, dstZoffset, - srcWidth, srcHeight, srcDepth, - dstRowStridePixels, dstImageStridePixels, - srcFormat, srcType, - srcPacking, srcAddr, dstAddr); - assert(b); - (void) b; - } - } - else { - /* software format */ - assert(!makeTemp); - transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr, - srcWidth, srcHeight, srcDepth, - dstXoffset, dstYoffset, dstZoffset, - dstRowStride, dstImageStride, - srcFormat, srcType, srcAddr, srcPacking, transferOps); + _mesa_free((void *) tempImage); } - - if (freeSourceData) - FREE((void *) srcAddr); /* the temp image */ + return GL_TRUE; } /** - * Given a user's uncompressed texture image, this function takes care of - * pixel unpacking, pixel transfer, format conversion and compression. + * Check if an unpack PBO is active prior to fetching a texture image. + * If so, do bounds checking and map the buffer into main memory. + * Any errors detected will be recorded. + * The caller _must_ call _mesa_unmap_teximage_pbo() too! */ -static void -transfer_compressed_teximage(GLcontext *ctx, GLuint dimensions, - GLsizei width, GLsizei height, GLsizei depth, - GLenum srcFormat, GLenum srcType, - const struct gl_pixelstore_attrib *unpacking, - const GLvoid *source, - const struct gl_texture_format *dstFormat, - GLubyte *dest, - GLint dstRowStride) +const GLvoid * +_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack, + const char *funcName) { - GLchan *tempImage = NULL; - GLint srcRowStride; - GLenum baseFormat; - - ASSERT(dimensions == 2); - /* TexelBytes is zero if and only if it's a compressed format */ - ASSERT(dstFormat->TexelBytes == 0); - - baseFormat = dstFormat->BaseFormat; + GLubyte *buf; - if (srcFormat != baseFormat || srcType != CHAN_TYPE || - ctx->_ImageTransferState != 0 || unpacking->SwapBytes) { - /* need to convert user's image to texImage->Format, GLchan */ - GLint comps = components_in_intformat(baseFormat); - GLint postConvWidth = width, postConvHeight = height; - - /* XXX convolution untested */ - if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { - _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth, - &postConvHeight); - } - - tempImage = (GLchan*) MALLOC(width * height * comps * sizeof(GLchan)); - if (!tempImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); - return; - } - transfer_teximage(ctx, dimensions, - baseFormat, /* dest format */ - tempImage, /* dst address */ - width, height, depth, /* src size */ - 0, 0, 0, /* x/y/zoffset */ - comps * width, /* dst row stride */ - comps * width * height, /* dst image stride */ - srcFormat, srcType, /* src format, type */ - source, unpacking, /* src and src packing */ - ctx->_ImageTransferState); - source = tempImage; - width = postConvWidth; - height = postConvHeight; - srcRowStride = width; + if (unpack->BufferObj->Name == 0) { + /* no PBO */ + return pixels; } - else { - if (unpacking->RowLength) - srcRowStride = unpacking->RowLength; - else - srcRowStride = width; + if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, + format, type, pixels)) { + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); + return NULL; } - _mesa_compress_teximage(ctx, width, height, baseFormat, - (const GLchan *) source, srcRowStride, - dstFormat, dest, dstRowStride); - if (tempImage) { - FREE(tempImage); + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, unpack->BufferObj); + if (!buf) { + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); + return NULL; } -} - - -#endif /************************************************************/ - + return ADD_POINTERS(buf, pixels); +} /** - * Validate acces to a PBO for texture data. - * - * \todo If the PBO is really resident in VRAM, this won't work; the - * device driver should check for that and do the right thing. + * Check if an unpack PBO is active prior to fetching a compressed texture + * image. + * If so, do bounds checking and map the buffer into main memory. + * Any errors detected will be recorded. + * The caller _must_ call _mesa_unmap_teximage_pbo() too! */ -static const GLvoid * -validate_pbo_teximage( GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *unpack ) +const GLvoid * +_mesa_validate_pbo_compressed_teximage(GLcontext *ctx, + GLsizei imageSize, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + const char *funcName) { - if (unpack->BufferObj->Name == 0) { - /* no PBO */ + GLubyte *buf; + + if (packing->BufferObj->Name == 0) { + /* not using a PBO - return pointer unchanged */ return pixels; } - else if (_mesa_validate_pbo_access(unpack, width, height, depth, format, - type, pixels)) { - return ADD_POINTERS(unpack->BufferObj->Data, pixels); + if ((const GLubyte *) pixels + imageSize > + (const GLubyte *) packing->BufferObj->Size) { + /* out of bounds read! */ + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); + return NULL; + } + + buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, packing->BufferObj); + if (!buf) { + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); + return NULL; } - /* bad access! */ - return NULL; + + return ADD_POINTERS(buf, pixels); } /** - * Validate that unpacking compressed texture image data from a PBO - * won't go out of bounds. - * - * \todo If the PBO is really resident in VRAM, this won't work; the - * device driver should check for that and do the right thing. + * This function must be called after either of the validate_pbo_*_teximage() + * functions. It unmaps the PBO buffer if it was mapped earlier. */ -static const GLvoid * -validate_pbo_compressed_teximage(GLsizei imageSize, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing) +void +_mesa_unmap_teximage_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack) { - if (packing->BufferObj->Name == 0) { - /* not using a PBO - return pointer unchanged */ - return pixels; - } - else { - /* using a PBO */ - if ((const GLubyte *) pixels + imageSize > - (const GLubyte *) packing->BufferObj->Size) { - /* out of bounds read! */ - return NULL; - } - /* OK! */ - return ADD_POINTERS(packing->BufferObj->Data, pixels); + if (unpack->BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + unpack->BufferObj); } } - /* * This is the software fallback for Driver.TexImage1D() * and Driver.CopyTexImage1D(). + * \sa _mesa_store_teximage2d() */ void _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, @@ -2386,6 +2164,7 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, { GLint postConvWidth = width; GLint sizeInBytes; + (void) border; if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); @@ -2410,12 +2189,15 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, return; } - pixels = validate_pbo_teximage(width, 1, 1, format, type, pixels, packing); - if (!pixels) + pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, pixels, + packing, "glTexImage1D"); + if (!pixels) { + /* Note: we check for a NULL image pointer here, _after_ we allocated + * memory for the texture. That's what the GL spec calls for. + */ return; - -#if NEWTEXSTORE - { + } + else { const GLint dstRowStride = 0, dstImageStride = 0; GLboolean success; ASSERT(texImage->TexFormat->StoreImage); @@ -2428,30 +2210,8 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); - return; } } -#else - /* unpack image, apply transfer ops and store in texImage->Data */ - if (texImage->IsCompressed) { - GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, - width); - transfer_compressed_teximage(ctx, 1, width, 1, 1, - format, type, packing, - pixels, texImage->TexFormat, - (GLubyte *) texImage->Data, dstRowStride); - } - else { - _mesa_transfer_teximage(ctx, 1, - texImage->Format, /* base format */ - texImage->TexFormat, texImage->Data, - width, 1, 1, /* src size */ - 0, 0, 0, /* dstX/Y/Zoffset */ - 0, /* dstRowStride */ - 0, /* dstImageStride */ - format, type, pixels, packing); - } -#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -2459,16 +2219,24 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } -/* +/** * This is the software fallback for Driver.TexImage2D() * and Driver.CopyTexImage2D(). + * We store the image in heap memory. We know nothing about on-board + * VRAM here. But since most DRI drivers rely on keeping a copy of all + * textures in main memory, this routine will typically be used by + * hardware drivers too. + * * Reasons why a driver might override this function: - * - Special memory allocation needs - * - Unusual row/image strides + * - Special memory allocation needs (VRAM, AGP, etc) + * - Unusual row/image strides or padding * - Special housekeeping + * - Using VRAM-based Pixel Buffer Objects */ void _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, @@ -2481,6 +2249,7 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, { GLint postConvWidth = width, postConvHeight = height; GLint texelBytes, sizeInBytes; + (void) border; if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, @@ -2508,20 +2277,22 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, return; } - pixels = validate_pbo_teximage(width, height, 1, - format, type, pixels, packing); - if (!pixels) + pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, + pixels, packing, "glTexImage2D"); + if (!pixels) { + /* Note: we check for a NULL image pointer here, _after_ we allocated + * memory for the texture. That's what the GL spec calls for. + */ return; - -#if NEWTEXSTORE - { + } + else { GLint dstRowStride, dstImageStride = 0; GLboolean success; if (texImage->IsCompressed) { dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width); } else { - dstRowStride = width * texImage->TexFormat->TexelBytes; + dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes; } ASSERT(texImage->TexFormat->StoreImage); success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, @@ -2533,30 +2304,8 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); - return; } } -#else - /* unpack image, apply transfer ops and store in texImage->Data */ - if (texImage->IsCompressed) { - GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, - width); - transfer_compressed_teximage(ctx, 2, width, height, 1, - format, type, packing, - pixels, texImage->TexFormat, - (GLubyte *) texImage->Data, dstRowStride); - } - else { - _mesa_transfer_teximage(ctx, 2, - texImage->Format, - texImage->TexFormat, texImage->Data, - width, height, 1, /* src size */ - 0, 0, 0, /* dstX/Y/Zoffset */ - texImage->Width * texelBytes, /* dstRowStride */ - 0, /* dstImageStride */ - format, type, pixels, packing); - } -#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -2564,13 +2313,16 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } -/* +/** * This is the software fallback for Driver.TexImage3D() * and Driver.CopyTexImage3D(). + * \sa _mesa_store_teximage2d() */ void _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, @@ -2582,6 +2334,7 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage) { GLint texelBytes, sizeInBytes; + (void) border; /* choose the texture format */ assert(ctx->Driver.ChooseTextureFormat); @@ -2604,14 +2357,15 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, return; } - pixels = validate_pbo_teximage(width, height, depth, - format, type, pixels, packing); - if (!pixels) + pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, type, + pixels, packing, "glTexImage3D"); + if (!pixels) { + /* Note: we check for a NULL image pointer here, _after_ we allocated + * memory for the texture. That's what the GL spec calls for. + */ return; - - /* unpack image, apply transfer ops and store in texImage->Data */ -#if NEWTEXSTORE - { + } + else { GLint dstRowStride, dstImageStride; GLboolean success; if (texImage->IsCompressed) { @@ -2632,29 +2386,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); - return; } } -#else - if (texImage->IsCompressed) { - GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, - width); - transfer_compressed_teximage(ctx, 3, width, height, depth, - format, type, packing, - pixels, texImage->TexFormat, - (GLubyte *) texImage->Data, dstRowStride); - } - else { - _mesa_transfer_teximage(ctx, 3, - texImage->Format, - texImage->TexFormat, texImage->Data, - width, height, depth, /* src size */ - 0, 0, 0, /* dstX/Y/Zoffset */ - texImage->Width * texelBytes, /* dstRowStride */ - texImage->Width * texImage->Height * texelBytes, - format, type, pixels, packing); - } -#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -2662,6 +2395,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } @@ -2679,12 +2414,11 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - pixels = validate_pbo_teximage(width, 1, 1, - format, type, pixels, packing); + pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, pixels, + packing, "glTexSubImage1D"); if (!pixels) return; -#if NEWTEXSTORE { const GLint dstRowStride = 0, dstImageStride = 0; GLboolean success; @@ -2698,36 +2432,8 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); - return; } } -#else - if (texImage->IsCompressed) { - GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, - texImage->Width); - GLubyte *dest = _mesa_compressed_image_address(xoffset, 0, 0, - texImage->IntFormat, - texImage->Width, - (GLubyte*) texImage->Data); - transfer_compressed_teximage(ctx, 1, /* dimensions */ - width, 1, 1, /* size to replace */ - format, type, /* source format/type */ - packing, /* source packing */ - pixels, /* source data */ - texImage->TexFormat,/* dest format */ - dest, dstRowStride); - } - else { - _mesa_transfer_teximage(ctx, 1, - texImage->Format, - texImage->TexFormat, texImage->Data, - width, 1, 1, /* src size */ - xoffset, 0, 0, /* dest offsets */ - 0, /* dstRowStride */ - 0, /* dstImageStride */ - format, type, pixels, packing); - } -#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -2735,6 +2441,8 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } @@ -2752,12 +2460,11 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - pixels = validate_pbo_teximage(width, height, 1, - format, type, pixels, packing); + pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, + pixels, packing, "glTexSubImage2D"); if (!pixels) return; -#if NEWTEXSTORE { GLint dstRowStride = 0, dstImageStride = 0; GLboolean success; @@ -2778,38 +2485,8 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); - return; } } -#else - - if (texImage->IsCompressed) { - GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, - texImage->Width); - GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, 0, - texImage->IntFormat, - texImage->Width, - (GLubyte*) texImage->Data); - transfer_compressed_teximage(ctx, 2, /* dimensions */ - width, height, 1, /* size to replace */ - format, type, /* source format/type */ - packing, /* source packing */ - pixels, /* source data */ - texImage->TexFormat,/* dest format */ - dest, dstRowStride); - } - else { - /* old path */ - _mesa_transfer_teximage(ctx, 2, - texImage->Format, - texImage->TexFormat, texImage->Data, - width, height, 1, /* src size */ - xoffset, yoffset, 0, /* dest offsets */ - texImage->Width *texImage->TexFormat->TexelBytes, - 0, /* dstImageStride */ - format, type, pixels, packing); - } -#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -2817,6 +2494,8 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } @@ -2833,12 +2512,11 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - pixels = validate_pbo_teximage(width, height, depth, - format, type, pixels, packing); + pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, type, + pixels, packing, "glTexSubImage3D"); if (!pixels) return; -#if NEWTEXSTORE { GLint dstRowStride, dstImageStride; GLboolean success; @@ -2861,43 +2539,17 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, format, type, pixels, packing); if (!success) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); - return; } } -#else - if (texImage->IsCompressed) { - GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, - texImage->Width); - GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, zoffset, - texImage->IntFormat, - texImage->Width, - (GLubyte*) texImage->Data); - transfer_compressed_teximage(ctx, 3, /* dimensions */ - width, height, depth,/* size to replace */ - format, type, /* source format/type */ - packing, /* source packing */ - pixels, /* source data */ - texImage->TexFormat,/* dest format */ - dest, dstRowStride); - } - else { - const GLint texelBytes = texImage->TexFormat->TexelBytes; - _mesa_transfer_teximage(ctx, 3, - texImage->Format, - texImage->TexFormat, texImage->Data, - width, height, depth, /* src size */ - xoffset, yoffset, zoffset, /* dest offsets */ - texImage->Width * texelBytes, /* dst row stride */ - texImage->Width * texImage->Height * texelBytes, - format, type, pixels, packing); - } -#endif + /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { _mesa_generate_mipmap(ctx, target, &ctx->Texture.Unit[ctx->Texture.CurrentUnit], texObj); } + + _mesa_unmap_teximage_pbo(ctx, packing); } @@ -2913,6 +2565,13 @@ _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage) { /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) internalFormat; + (void) width; (void) border; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; } @@ -2928,6 +2587,8 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { + (void) width; (void) height; (void) border; + /* This is pretty simple, basically just do a memcpy without worrying * about the usual image unpacking or image transfer operations. */ @@ -2953,13 +2614,23 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, return; } - data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack); + data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack, + "glCompressedTexImage2D"); if (!data) return; /* copy the data */ ASSERT(texImage->CompressedSize == (GLuint) imageSize); MEMCPY(texImage->Data, data, imageSize); + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); } @@ -2977,6 +2648,14 @@ _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage) { /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) internalFormat; + (void) width; (void) height; (void) depth; + (void) border; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; } @@ -2994,6 +2673,13 @@ _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target, struct gl_texture_image *texImage) { /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) xoffset; (void) width; + (void) format; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; } @@ -3014,6 +2700,7 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, GLint i, rows; GLubyte *dest; const GLubyte *src; + (void) format; /* these should have been caught sooner */ ASSERT((width & 3) == 0 || width == 2 || width == 1); @@ -3021,7 +2708,8 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, ASSERT((xoffset & 3) == 0); ASSERT((yoffset & 3) == 0); - data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack); + data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack, + "glCompressedTexSubImage2D"); if (!data) return; @@ -3043,6 +2731,15 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, dest += destRowStride; src += srcRowStride; } + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); } @@ -3060,6 +2757,14 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, struct gl_texture_image *texImage) { /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) xoffset; (void) yoffset; (void) zoffset; + (void) width; (void) height; (void) depth; + (void) format; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; } @@ -3121,7 +2826,6 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, case MESA_FORMAT_ALPHA: case MESA_FORMAT_LUMINANCE: case MESA_FORMAT_INTENSITY: - case MESA_FORMAT_COLOR_INDEX: { GLuint i, j, k; const GLchan *rowA = (const GLchan *) srcRowA; @@ -3174,7 +2878,9 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, return; /* Begin hardware formats */ case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGBA8888_REV: case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_ARGB8888_REV: { GLuint i, j, k; const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA; @@ -3194,6 +2900,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, } return; case MESA_FORMAT_RGB888: + case MESA_FORMAT_BGR888: { GLuint i, j, k; const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA; @@ -3211,6 +2918,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, } return; case MESA_FORMAT_RGB565: + case MESA_FORMAT_RGB565_REV: { GLuint i, j, k; const GLushort *rowA = (const GLushort *) srcRowA; @@ -3238,6 +2946,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, } return; case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB4444_REV: { GLuint i, j, k; const GLushort *rowA = (const GLushort *) srcRowA; @@ -3270,6 +2979,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, } return; case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_ARGB1555_REV: /* XXX broken? */ { GLuint i, j, k; const GLushort *rowA = (const GLushort *) srcRowA; @@ -3302,6 +3012,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, } return; case MESA_FORMAT_AL88: + case MESA_FORMAT_AL88_REV: { GLuint i, j, k; const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA; @@ -4015,15 +3726,15 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target, GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat, dstWidth); ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA); - _mesa_compress_teximage(ctx, - dstWidth, dstHeight, /* size */ - srcFormat, /* source format */ - (const GLchan *) dstData, /* source buffer */ - dstWidth, /* source row stride */ - dstImage->TexFormat, /* dest format */ - (GLubyte*) dstImage->Data, /* dest buffer */ - dstRowStride ); /* dest row stride */ - + dstImage->TexFormat->StoreImage(ctx, 2, dstImage->Format, + 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; @@ -4032,3 +3743,285 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target, } /* 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]; + } + } + } +} + + + +/** + * This is the software fallback for Driver.GetTexImage(). + * All error checking will have been done before this routine is called. + */ +void +_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage) +{ + GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; + + if (ctx->Pack.BufferObj->Name) { + /* pack texture image into a PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, + texImage->Height, texImage->Depth, + format, type, pixels)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTexImage(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)"); + return; + } + pixels = ADD_POINTERS(buf, pixels); + } + else if (!pixels) { + /* not an error */ + return; + } + + { + const GLint width = texImage->Width; + const GLint height = texImage->Height; + const GLint depth = texImage->Depth; + GLint img, row; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + /* compute destination address in client memory */ + GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels, + width, height, format, type, + img, row, 0); + assert(dest); + + if (format == GL_COLOR_INDEX) { + GLuint indexRow[MAX_WIDTH]; + GLint col; + /* Can't use FetchTexel here because that returns RGBA */ + if (texImage->TexFormat->IndexBits == 8) { + const GLubyte *src = (const GLubyte *) texImage->Data; + for (col = 0; col < width; col++) { + indexRow[col] = src[texImage->Width * + (img * texImage->Height + row) + col]; + } + } + else if (texImage->TexFormat->IndexBits == 16) { + const GLushort *src = (const GLushort *) texImage->Data; + for (col = 0; col < width; col++) { + indexRow[col] = src[texImage->Width * + (img * texImage->Height + row) + col]; + } + } + else { + _mesa_problem(ctx, + "Color index problem in _mesa_GetTexImage"); + } + _mesa_pack_index_span(ctx, width, type, dest, + indexRow, &ctx->Pack, + 0 /* no image transfer */); + } + else if (format == GL_DEPTH_COMPONENT) { + GLfloat depthRow[MAX_WIDTH]; + GLint col; + for (col = 0; col < width; col++) { + (*texImage->FetchTexelf)(texImage, col, row, img, + depthRow + col); + } + _mesa_pack_depth_span(ctx, width, dest, type, + depthRow, &ctx->Pack); + } + else if (format == GL_YCBCR_MESA) { + /* No pixel transfer */ + const GLint rowstride = texImage->RowStride; + MEMCPY(dest, + (const GLushort *) texImage->Data + row * rowstride, + width * sizeof(GLushort)); + /* check for byte swapping */ + if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR + && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || + (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV + && type == GL_UNSIGNED_SHORT_8_8_MESA)) { + if (!ctx->Pack.SwapBytes) + _mesa_swap2((GLushort *) dest, width); + } + else if (ctx->Pack.SwapBytes) { + _mesa_swap2((GLushort *) dest, width); + } + } + else { + /* general case: convert row to RGBA format */ + GLfloat rgba[MAX_WIDTH][4]; + GLint col; + for (col = 0; col < width; col++) { + (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]); + } + _mesa_pack_rgba_span_float(ctx, width, + (const GLfloat (*)[4]) rgba, + format, type, dest, &ctx->Pack, + 0 /* no image transfer */); + } /* format */ + } /* row */ + } /* img */ + } + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +} + + + +/** + * This is the software fallback for Driver.GetCompressedTexImage(). + * All error checking will have been done before this routine is called. + */ +void +_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, + GLvoid *img, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage) +{ + if (ctx->Pack.BufferObj->Name) { + /* pack texture image into a PBO */ + GLubyte *buf; + if ((const GLubyte *) img + texImage->CompressedSize > + (const GLubyte *) ctx->Pack.BufferObj->Size) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetCompressedTexImage(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetCompressedTexImage(PBO is mapped)"); + return; + } + img = ADD_POINTERS(buf, img); + } + else if (!img) { + /* not an error */ + return; + } + + /* just memcpy, no pixelstore or pixel transfer */ + MEMCPY(img, texImage->Data, texImage->CompressedSize); + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +}