diff options
author | Brian Paul <[email protected]> | 2004-04-22 00:27:31 +0000 |
---|---|---|
committer | Brian Paul <[email protected]> | 2004-04-22 00:27:31 +0000 |
commit | f959f6e1dc27c71fc0ccc56e09b29101b3bf3b97 (patch) | |
tree | 15b4171c2b3396e3a05f2776cc24d90cb37c8f84 /src/mesa/main/texstore.c | |
parent | 05a6f2fd484bab59c6e6a381f58808adc26619f1 (diff) |
New glTexImage code.
The gl_texture_format struct now has a StoreTexImageFunc that's called
by glTex[Sub]Image[123]D to convert the user's texture data into the
specific texture format layout. Now it's much easier to add new texture
formats (like the 16/32-bit floating point formats).
The texutil.[ch] and texutil_tmp.h files are obsolete.
Diffstat (limited to 'src/mesa/main/texstore.c')
-rw-r--r-- | src/mesa/main/texstore.c | 1912 |
1 files changed, 1893 insertions, 19 deletions
diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index 4ed7d38beb9..cd23f3c77d4 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -66,6 +66,1578 @@ #include "texutil.h" + +/*** NEWTEXSTORE ***********************************************************/ + +static const GLint ZERO = 1000, ONE = 1001; + +/** + * When promoting texture formats (see below) we need to compute the + * mapping of dest components back to source components. + * This function does that. + * \param logicalBaseFormat the logical format of the texture + * \param textureBaseFormat the final texture format + * \return map[4] the four mapping values + */ +static void +compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat, + GLint map[4]) +{ + /* 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) + 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; + default: + _mesa_problem(NULL, "Unexpected logicalBaseFormat"); + map[0] = map[1] = map[2] = map[3] = 0; + } +} + + +/** + * Make a temporary (color) texture image with GLfloat components. + * Apply all needed pixel unpacking and pixel transfer operations. + * Note that there are both logicalBaseFormat and textureBaseFormat parameters. + * Suppose the user specifies GL_LUMINANCE as the internal texture format + * but the graphics hardware doesn't support luminance textures. So, might + * use an RGB hardware format instead. + * If logicalBaseFormat != textureBaseFormat we have some extra work to do. + * + * \param ctx the rendering context + * \param dims image dimensions: 1, 2 or 3 + * \param logicalBaseFormat basic texture derived from the user's + * internal texture format value + * \param textureBaseFormat the actual basic format of the texture + * \param srcWidth source image width + * \param srcHeight source image height + * \param srcDepth source image depth + * \param srcFormat source image format + * \param srcType source image type + * \param srcAddr source image address + * \param srcPacking source image pixel packing + * \return resulting image with format = textureBaseFormat and type = GLfloat. + */ +static GLfloat * +make_temp_float_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; + GLfloat *tempImage; + + ASSERT(dims >= 1 && dims <= 3); + + ASSERT(logicalBaseFormat == GL_RGBA || + logicalBaseFormat == GL_RGB || + logicalBaseFormat == GL_LUMINANCE_ALPHA || + logicalBaseFormat == GL_LUMINANCE || + logicalBaseFormat == GL_ALPHA || + logicalBaseFormat == GL_INTENSITY || + logicalBaseFormat == GL_COLOR_INDEX || + logicalBaseFormat == GL_DEPTH_COMPONENT); + + ASSERT(textureBaseFormat == GL_RGBA || + textureBaseFormat == GL_RGB || + textureBaseFormat == GL_LUMINANCE_ALPHA || + textureBaseFormat == GL_LUMINANCE || + textureBaseFormat == GL_ALPHA || + textureBaseFormat == GL_INTENSITY || + textureBaseFormat == GL_COLOR_INDEX || + textureBaseFormat == GL_DEPTH_COMPONENT); + + /* conventional color image */ + + if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) || + (dims >= 2 && ctx->Pixel.Convolution2DEnabled) || + (dims >= 2 && ctx->Pixel.Separable2DEnabled)) { + /* need image convolution */ + const GLuint preConvTransferOps + = (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT; + const GLuint postConvTransferOps + = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT; + GLint img, row; + GLint convWidth, convHeight; + GLfloat *convImage; + + /* pre-convolution image buffer (3D) */ + tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * 4 * sizeof(GLfloat)); + if (!tempImage) + return NULL; + + /* post-convolution image buffer (2D) */ + convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight + * 4 * sizeof(GLfloat)); + if (!convImage) { + _mesa_free(tempImage); + return NULL; + } + + /* loop over 3D image slices */ + for (img = 0; img < srcDepth; img++) { + GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4); + + /* 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, dst, + srcFormat, srcType, src, + srcPacking, + preConvTransferOps); + dst += srcWidth * 4; + } + + /* do convolution */ + { + GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4); + convWidth = srcWidth; + convHeight = srcHeight; + if (dims == 1) { + ASSERT(ctx->Pixel.Convolution1DEnabled); + _mesa_convolve_1d_image(ctx, &convWidth, src, convImage); + } + else { + if (ctx->Pixel.Convolution2DEnabled) { + _mesa_convolve_2d_image(ctx, &convWidth, &convHeight, + src, convImage); + } + else { + ASSERT(ctx->Pixel.Separable2DEnabled); + _mesa_convolve_sep_image(ctx, &convWidth, &convHeight, + src, convImage); + } + } + } + + /* do post-convolution transfer and pack into tempImage */ + { + const GLfloat *src = convImage; + GLfloat *dst = tempImage + img * (convWidth * convHeight * 4); + for (row = 0; row < convHeight; row++) { + _mesa_pack_rgba_span_float(ctx, convWidth, + (const GLfloat (*)[4]) src, + logicalBaseFormat, GL_FLOAT, + dst, &ctx->DefaultPacking, + postConvTransferOps); + src += convWidth * 4; + dst += convWidth * 4; + } + } + } /* loop over 3D image slices */ + + _mesa_free(convImage); + + /* might need these below */ + srcWidth = convWidth; + srcHeight = convHeight; + } + else { + /* no convolution */ + const GLint components = _mesa_components_in_format(logicalBaseFormat); + const GLint srcStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLfloat *dst; + GLint img, row; + + tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * components * sizeof(GLfloat)); + if (!tempImage) + return NULL; + + dst = tempImage; + for (img = 0; img < srcDepth; img++) { + const GLubyte *src + = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr, + srcWidth, srcHeight, + srcFormat, srcType, + img, 0, 0); + for (row = 0; row < srcHeight; row++) { + _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat, + dst, srcFormat, srcType, src, + srcPacking, transferOps); + dst += srcWidth * components; + src += srcStride; + } + } + } + + if (logicalBaseFormat != textureBaseFormat) { + /* more work */ + GLint texComponents = _mesa_components_in_format(textureBaseFormat); + GLint logComponents = _mesa_components_in_format(logicalBaseFormat); + GLfloat *newImage; + GLint i, n; + GLint map[4]; + + /* we only promote up to RGB and RGBA formats for now */ + ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA); + + /* The actual texture format should have at least as many components + * as the logical texture format. + */ + ASSERT(texComponents >= logComponents); + + newImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * texComponents * sizeof(GLfloat)); + if (!newImage) { + _mesa_free(tempImage); + return NULL; + } + + compute_component_mapping(logicalBaseFormat, textureBaseFormat, map); + + n = srcWidth * srcHeight * srcDepth; + for (i = 0; i < n; i++) { + GLint k; + for (k = 0; k < texComponents; k++) { + GLint j = map[k]; + if (j == ZERO) + newImage[i * texComponents + k] = 0.0F; + else if (j == ONE) + newImage[i * texComponents + k] = 1.0F; + else + newImage[i * texComponents + k] = tempImage[i * logComponents + j]; + } + } + + _mesa_free(tempImage); + tempImage = newImage; + } + + return tempImage; +} + + +/** + * Make a temporary (color) texture image with GLchan components. + * Apply all needed pixel unpacking and pixel transfer operations. + * Note that there are both logicalBaseFormat and textureBaseFormat parameters. + * Suppose the user specifies GL_LUMINANCE as the internal texture format + * but the graphics hardware doesn't support luminance textures. So, might + * use an RGB hardware format instead. + * If logicalBaseFormat != textureBaseFormat we have some extra work to do. + * + * \param ctx the rendering context + * \param dims image dimensions: 1, 2 or 3 + * \param logicalBaseFormat basic texture derived from the user's + * internal texture format value + * \param textureBaseFormat the actual basic format of the texture + * \param srcWidth source image width + * \param srcHeight source image height + * \param srcDepth source image depth + * \param srcFormat source image format + * \param srcType source image type + * \param srcAddr source image address + * \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) +{ + GLuint transferOps = ctx->_ImageTransferState; + const GLint components = _mesa_components_in_format(logicalBaseFormat); + GLboolean freeSrcImage = GL_FALSE; + GLint img, row; + GLchan *tempImage, *dst; + + ASSERT(dims >= 1 && dims <= 3); + + ASSERT(logicalBaseFormat == GL_RGBA || + logicalBaseFormat == GL_RGB || + logicalBaseFormat == GL_LUMINANCE_ALPHA || + logicalBaseFormat == GL_LUMINANCE || + logicalBaseFormat == GL_ALPHA || + logicalBaseFormat == GL_INTENSITY); + + ASSERT(textureBaseFormat == GL_RGBA || + textureBaseFormat == GL_RGB || + textureBaseFormat == GL_LUMINANCE_ALPHA || + textureBaseFormat == GL_LUMINANCE || + textureBaseFormat == GL_ALPHA || + textureBaseFormat == GL_INTENSITY); + + if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) || + (dims >= 2 && ctx->Pixel.Convolution2DEnabled) || + (dims >= 2 && ctx->Pixel.Separable2DEnabled)) { + /* get convolved image */ + GLfloat *convImage = make_temp_float_image(ctx, dims, + logicalBaseFormat, + logicalBaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, + srcAddr, srcPacking); + if (!convImage) + return NULL; + /* the convolved image is our new source image */ + srcAddr = convImage; + srcFormat = logicalBaseFormat; + srcType = GL_FLOAT; + srcPacking = &ctx->DefaultPacking; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + transferOps = 0; + freeSrcImage = GL_TRUE; + } + + /* unpack and transfer the source image */ + tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * components * sizeof(GLchan)); + if (!tempImage) + return NULL; + + dst = tempImage; + for (img = 0; img < srcDepth; img++) { + const GLint srcStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, + srcType); + const GLubyte *src + = (const GLubyte *) _mesa_image_address(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); + dst += srcWidth * components; + src += srcStride; + } + } + + /* If we made a temporary image for convolution, free it here */ + if (freeSrcImage) { + _mesa_free((void *) srcAddr); + } + + if (logicalBaseFormat != textureBaseFormat) { + /* one more conversion step */ + GLint texComponents = _mesa_components_in_format(textureBaseFormat); + GLint logComponents = _mesa_components_in_format(logicalBaseFormat); + GLchan *newImage; + GLint i, n; + GLint map[4]; + + /* we only promote up to RGB and RGBA formats for now */ + ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA); + + /* The actual texture format should have at least as many components + * as the logical texture format. + */ + ASSERT(texComponents >= logComponents); + + newImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * texComponents * sizeof(GLchan)); + if (!newImage) { + _mesa_free(tempImage); + return NULL; + } + + compute_component_mapping(logicalBaseFormat, textureBaseFormat, map); + + n = srcWidth * srcHeight * srcDepth; + for (i = 0; i < n; i++) { + GLint k; + for (k = 0; k < texComponents; k++) { + GLint j = map[k]; + if (j == ZERO) + newImage[i * texComponents + k] = 0; + else if (j == ONE) + newImage[i * texComponents + k] = CHAN_MAX; + else + newImage[i * texComponents + k] = tempImage[i * logComponents + j]; + } + } + + _mesa_free(tempImage); + tempImage = newImage; + } + + return tempImage; +} + + + +/** + * Teximage storage routine for when a simple memcpy will do. + * No pixel transfer operations or special texel encodings allowed. + * 1D, 2D and 3D images supported. + */ +static void +memcpy_texture(const struct gl_texture_format *dstFormat, + GLvoid *dstAddr, + GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, + GLint dstRowStride, GLint dstImageStride, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking) +{ + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, + 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 GLint bytesPerRow = srcWidth * dstFormat->TexelBytes; + const GLint bytesPerImage = srcHeight * bytesPerRow; + const GLint bytesPerTexture = srcDepth * bytesPerImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + + if (dstRowStride == srcRowStride && + dstRowStride == bytesPerRow && + ((dstImageStride == srcImageStride && + dstImageStride == bytesPerImage) || + (srcDepth == 1))) { + /* one big memcpy */ + _mesa_memcpy(dstImage, srcImage, bytesPerTexture); + } + else { + GLint img, row; + for (img = 0; img < srcDepth; img++) { + const GLubyte *srcRow = srcImage; + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + _mesa_memcpy(dstRow, srcRow, bytesPerRow); + dstRow += dstRowStride; + srcRow += srcRowStride; + } + srcImage += srcImageStride; + dstImage += dstImageStride; + } + } +} + + + +/** + * Store an image in any of the formats: + * _mesa_texformat_rgba + * _mesa_texformat_rgb + * _mesa_texformat_alpha + * _mesa_texformat_luminance + * _mesa_texformat_luminance_alpha + * _mesa_texformat_intensity + * + * \param dims either 1 or 2 or 3 + * \param baseInternalFormat user-specified base internal format + * \param dstFormat destination Mesa texture format + * \param dstAddr destination image address + * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels + * \param dstRowStride destination image row stride, in bytes + * \param dstImageStride destination image layer stride, in bytes + * \param srcWidth/Height/Depth source image size, in pixels + * \param srcFormat incoming image format + * \param srcType incoming image data type + * \param srcAddr source image address + * \param srcPacking source image packing parameters + */ +GLboolean +_mesa_texstore_rgba(GLcontext *ctx, GLuint dims, + GLenum baseInternalFormat, + const struct gl_texture_format *dstFormat, + GLvoid *dstAddr, + GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, + GLint dstRowStride, GLint dstImageStride, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking) +{ + const GLint components = _mesa_components_in_format(baseInternalFormat); + + ASSERT(dstFormat == &_mesa_texformat_rgba || + dstFormat == &_mesa_texformat_rgb || + dstFormat == &_mesa_texformat_alpha || + dstFormat == &_mesa_texformat_luminance || + dstFormat == &_mesa_texformat_luminance_alpha || + dstFormat == &_mesa_texformat_intensity); + ASSERT(baseInternalFormat == GL_RGBA || + baseInternalFormat == GL_RGB || + baseInternalFormat == GL_ALPHA || + baseInternalFormat == GL_LUMINANCE || + baseInternalFormat == GL_LUMINANCE_ALPHA || + baseInternalFormat == GL_INTENSITY); + ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == srcFormat && + srcType == CHAN_TYPE) { + /* simple memcpy path */ + memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_rgb && + srcFormat == GL_RGBA && + srcType == CHAN_TYPE) { + /* extract RGB from RGBA */ + int img, row, col; + GLchan *dstImage = (GLchan *) (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); + GLchan *srcRow = _mesa_image_address(srcPacking, srcAddr, srcWidth, + srcHeight, srcFormat, srcType, + img, 0, 0); + GLchan *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP]; + dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP]; + dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP]; + } + dstRow += dstRowStride; + srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride); + } + dstImage += dstImageStride; + } + } + else { + /* general path */ + const GLchan *tempImage = 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); + 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++) { + _mesa_memcpy(dstRow, src, bytesPerRow); + dstRow += dstRowStride; + src += srcWidth * components; + } + dstImage += dstImageStride; + } + + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +/** + * 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) +{ + ASSERT(dstFormat == &_mesa_texformat_depth_component_float32); + ASSERT(dstFormat->TexelBytes == sizeof(GLfloat)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_DEPTH_COMPONENT && + srcFormat == GL_DEPTH_COMPONENT && + srcType == GL_FLOAT) { + /* 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_depth_span(ctx, srcWidth, (GLfloat *) dstRow, + srcType, src, srcPacking); + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + } + return GL_TRUE; +} + + +/** + * Store a 16-bit integer depth component texture image. + */ +GLboolean +_mesa_texstore_depth_component16(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_depth_component16); + ASSERT(dstFormat->TexelBytes == sizeof(GLushort)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_DEPTH_COMPONENT && + srcFormat == GL_DEPTH_COMPONENT && + srcType == GL_UNSIGNED_SHORT) { + /* 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, col; + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLfloat depthTemp[MAX_WIDTH]; + const GLvoid *src = _mesa_image_address(srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); + GLushort *dst16 = (GLushort *) dstRow; + _mesa_unpack_depth_span(ctx, srcWidth, depthTemp, + srcType, src, srcPacking); + for (col = 0; col < srcWidth; col++) { + dst16[col] = (GLushort) (depthTemp[col] * 65535.0F); + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + } + return GL_TRUE; +} + + + + +/** + * Store an rgb565 texture image. + */ +GLboolean +_mesa_texstore_rgb565(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_rgb565); + ASSERT(dstFormat->TexelBytes == 2); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_SHORT_5_6_5) { + /* simple memcpy path */ + memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_BYTE && + dims == 2) { + /* do optimized tex store */ + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, + srcFormat, srcType); + const GLubyte *src = (const GLubyte *) + _mesa_image_address(srcPacking, srcAddr, srcWidth, srcHeight, + srcFormat, srcType, 0, 0, 0); + GLubyte *dst = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint row, col; + 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; + } + dst += dstRowStride; + src += srcRowStride; + } + } + else { + /* general path */ + const GLchan *tempImage = make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = 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++) { + 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; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_rgba8888(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_rgba8888); + ASSERT(dstFormat->TexelBytes == 4); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + 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))) { + /* simple memcpy path */ + memcpy_texture(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, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = 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++) { + 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; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_argb8888(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_argb8888); + ASSERT(dstFormat->TexelBytes == 4); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + 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, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLchan *tempImage = make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = 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++) { + 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; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + + +GLboolean +_mesa_texstore_rgb888(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_rgb888); + ASSERT(dstFormat->TexelBytes == 3); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_BGR && + srcType == GL_UNSIGNED_BYTE && + littleEndian) { + /* simple memcpy path */ + memcpy_texture(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 = _mesa_image_address(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 + BCOMP]; + dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; + dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP]; + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } + else { + /* general path */ + const GLchan *tempImage = make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = (const GLubyte *) 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++) { +#if 0 + if (littleEndian) { + 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]); + srcUB += 3; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = srcUB[BCOMP]; + dstRow[col * 3 + 1] = srcUB[GCOMP]; + dstRow[col * 3 + 2] = srcUB[RCOMP]; + srcUB += 3; + } + } +#else + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]); + dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); + dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]); + src += 3; + } +#endif + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_argb4444(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_argb4444); + ASSERT(dstFormat->TexelBytes == 2); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + 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))) { + /* simple memcpy path */ + memcpy_texture(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, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = 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++) { + 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; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_argb1555(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_argb1555); + ASSERT(dstFormat->TexelBytes == 2); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + 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))) { + /* simple memcpy path */ + memcpy_texture(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, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src =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++) { + 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; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_al88(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_al88); + ASSERT(dstFormat->TexelBytes == 2); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_LUMINANCE_ALPHA && + srcFormat == GL_LUMINANCE_ALPHA && + srcType == GL_UNSIGNED_BYTE && + littleEndian) { + /* simple memcpy path */ + memcpy_texture(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, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = 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++) { + 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; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_rgb332(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_rgb332); + ASSERT(dstFormat->TexelBytes == 1); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) { + /* simple memcpy path */ + memcpy_texture(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, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = 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] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 3; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + + +/** + * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8. + */ +GLboolean +_mesa_texstore_a8(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_a8 || + dstFormat == &_mesa_texformat_l8 || + dstFormat == &_mesa_texformat_i8); + ASSERT(dstFormat->TexelBytes == 1); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == srcFormat && + srcType == GL_UNSIGNED_BYTE) { + /* simple memcpy path */ + memcpy_texture(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, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = 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] = CHAN_TO_UBYTE(src[col]); + } + dstRow += dstRowStride; + src += srcWidth; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + + +GLboolean +_mesa_texstore_ci8(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_ci8); + ASSERT(dstFormat->TexelBytes == 1); + ASSERT(baseInternalFormat == GL_COLOR_INDEX); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + srcFormat == GL_COLOR_INDEX && + srcType == GL_UNSIGNED_BYTE) { + /* 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, GL_UNSIGNED_BYTE, dstRow, + srcType, src, srcPacking, + ctx->_ImageTransferState); + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + } + return GL_TRUE; +} + + +/** + * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev. + */ +GLboolean +_mesa_texstore_ycbcr(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT((dstFormat == &_mesa_texformat_ycbcr) || + (dstFormat == &_mesa_texformat_ycbcr_rev)); + ASSERT(dstFormat->TexelBytes == 2); + ASSERT(ctx->Extensions.MESA_ycbcr_texture); + ASSERT(srcFormat == GL_YCBCR_MESA); + ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) || + (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA)); + ASSERT(baseInternalFormat == GL_YCBCR_MESA); + + /* always just memcpy since no pixel transfer ops apply */ + memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + + /* Check if we need byte swapping */ + /* XXX the logic here _might_ be wrong */ + if (srcPacking->SwapBytes ^ + (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^ + (dstFormat == &_mesa_texformat_ycbcr_rev) ^ + !littleEndian) { + GLushort *pImage = (GLushort *) ((GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes); + GLint img, row; + for (img = 0; img < srcDepth; img++) { + GLushort *pRow = pImage; + for (row = 0; row < srcHeight; row++) { + _mesa_swap2(pRow, srcWidth); + pRow += dstRowStride; + } + pImage += dstImageStride; + } + } + return GL_TRUE; +} + + + + +/** + * Store an image in any of the formats: + * _mesa_texformat_rgba_float32 + * _mesa_texformat_rgb_float32 + * _mesa_texformat_alpha_float32 + * _mesa_texformat_luminance_float32 + * _mesa_texformat_luminance_alpha_float32 + * _mesa_texformat_intensity_float32 + */ +GLboolean +_mesa_texstore_rgba_float32(STORE_PARAMS) +{ + const GLint components = _mesa_components_in_format(baseInternalFormat); + + ASSERT(dstFormat == &_mesa_texformat_rgba_float32 || + dstFormat == &_mesa_texformat_rgb_float32 || + dstFormat == &_mesa_texformat_alpha_float32 || + dstFormat == &_mesa_texformat_luminance_float32 || + dstFormat == &_mesa_texformat_luminance_alpha_float32 || + dstFormat == &_mesa_texformat_intensity_float32); + ASSERT(baseInternalFormat == GL_RGBA || + baseInternalFormat == GL_RGB || + baseInternalFormat == GL_ALPHA || + baseInternalFormat == GL_LUMINANCE || + baseInternalFormat == GL_LUMINANCE_ALPHA || + baseInternalFormat == GL_INTENSITY); + ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == srcFormat && + srcType == GL_FLOAT) { + /* 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; + const GLint bytesPerRow = srcWidth * components * sizeof(GLfloat); + 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 *dst = dstImage; + for (row = 0; row < srcHeight; row++) { + _mesa_memcpy(dst, src, bytesPerRow); + dst += dstRowStride; + src += srcWidth * components; + } + dstImage += dstImageStride; + } + + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +/** + * As above, but store 16-bit floats. + */ +GLboolean +_mesa_texstore_rgba_float16(STORE_PARAMS) +{ + const GLint components = _mesa_components_in_format(baseInternalFormat); + + ASSERT(dstFormat == &_mesa_texformat_rgba_float16 || + dstFormat == &_mesa_texformat_rgb_float16 || + dstFormat == &_mesa_texformat_alpha_float16 || + dstFormat == &_mesa_texformat_luminance_float16 || + dstFormat == &_mesa_texformat_luminance_alpha_float16 || + dstFormat == &_mesa_texformat_intensity_float16); + ASSERT(baseInternalFormat == GL_RGBA || + baseInternalFormat == GL_RGB || + baseInternalFormat == GL_ALPHA || + baseInternalFormat == GL_LUMINANCE || + 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, @@ -741,6 +2313,11 @@ transfer_compressed_teximage(GLcontext *ctx, GLuint dimensions, } +#endif /************************************************************/ + + + + /** * Validate acces to a PBO for texture data. * @@ -796,10 +2373,7 @@ validate_pbo_compressed_teximage(GLsizei imageSize, const GLvoid *pixels, /* * This is the software fallback for Driver.TexImage1D() - * and Driver.CopyTexImage2D(). - * The texture image type will be GLchan. - * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY, - * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA. + * and Driver.CopyTexImage1D(). */ void _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, @@ -811,7 +2385,7 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage) { GLint postConvWidth = width; - GLint texelBytes, sizeInBytes; + GLint sizeInBytes; if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); @@ -819,19 +2393,17 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, /* choose the texture format */ assert(ctx->Driver.ChooseTextureFormat); - texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, - internalFormat, format, type); + texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + format, type); assert(texImage->TexFormat); texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; - texelBytes = texImage->TexFormat->TexelBytes; - /* allocate memory */ if (texImage->IsCompressed) sizeInBytes = texImage->CompressedSize; else - sizeInBytes = postConvWidth * texelBytes; + sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes; texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes); if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); @@ -842,6 +2414,24 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, if (!pixels) return; +#if NEWTEXSTORE + { + const GLint dstRowStride = 0, dstImageStride = 0; + GLboolean success; + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 1, texImage->Format, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, dstImageStride, + width, 1, 1, + 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, @@ -861,6 +2451,7 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, 0, /* dstImageStride */ format, type, pixels, packing); } +#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -874,9 +2465,10 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, /* * This is the software fallback for Driver.TexImage2D() * and Driver.CopyTexImage2D(). - * The texture image type will be GLchan. - * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY, - * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA. + * Reasons why a driver might override this function: + * - Special memory allocation needs + * - Unusual row/image strides + * - Special housekeeping */ void _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, @@ -921,6 +2513,30 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, if (!pixels) return; +#if NEWTEXSTORE + { + GLint dstRowStride, dstImageStride = 0; + GLboolean success; + if (texImage->IsCompressed) { + dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width); + } + else { + dstRowStride = width * texImage->TexFormat->TexelBytes; + } + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, dstImageStride, + width, height, 1, + 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, @@ -940,6 +2556,7 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, 0, /* dstImageStride */ format, type, pixels, packing); } +#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -954,9 +2571,6 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, /* * This is the software fallback for Driver.TexImage3D() * and Driver.CopyTexImage3D(). - * The texture image type will be GLchan. - * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY, - * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA. */ void _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, @@ -996,6 +2610,32 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, return; /* unpack image, apply transfer ops and store in texImage->Data */ +#if NEWTEXSTORE + { + GLint dstRowStride, dstImageStride; + GLboolean success; + if (texImage->IsCompressed) { + dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width); + dstImageStride = 0; + } + else { + dstRowStride = width * texImage->TexFormat->TexelBytes; + dstImageStride = dstRowStride * height; + } + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 3, texImage->Format, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, dstImageStride, + width, height, depth, + 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); @@ -1014,6 +2654,7 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, texImage->Width * texImage->Height * texelBytes, format, type, pixels, packing); } +#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -1043,6 +2684,24 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, if (!pixels) return; +#if NEWTEXSTORE + { + const GLint dstRowStride = 0, dstImageStride = 0; + GLboolean success; + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 1, texImage->Format, + texImage->TexFormat, + texImage->Data, + xoffset, 0, 0, /* offsets */ + dstRowStride, dstImageStride, + width, 1, 1, + 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); @@ -1068,6 +2727,7 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, 0, /* dstImageStride */ format, type, pixels, packing); } +#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -1079,7 +2739,7 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, -/* +/** * This is the software fallback for Driver.TexSubImage2D() * and Driver.CopyTexSubImage2D(). */ @@ -1097,6 +2757,32 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, if (!pixels) return; +#if NEWTEXSTORE + { + GLint dstRowStride = 0, dstImageStride = 0; + GLboolean success; + if (texImage->IsCompressed) { + dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + } + else { + dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes; + } + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + texImage->TexFormat, + texImage->Data, + xoffset, yoffset, 0, + dstRowStride, dstImageStride, + width, height, 1, + 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); @@ -1113,6 +2799,7 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, dest, dstRowStride); } else { + /* old path */ _mesa_transfer_teximage(ctx, 2, texImage->Format, texImage->TexFormat, texImage->Data, @@ -1122,6 +2809,7 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, 0, /* dstImageStride */ format, type, pixels, packing); } +#endif /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { @@ -1145,6 +2833,38 @@ _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); + if (!pixels) + return; + +#if NEWTEXSTORE + { + GLint dstRowStride, dstImageStride; + GLboolean success; + if (texImage->IsCompressed) { + dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + dstImageStride = 0; /* XXX fix */ + } + else { + dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes; + dstImageStride = dstRowStride * texImage->Height; + } + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 3, texImage->Format, + texImage->TexFormat, + texImage->Data, + xoffset, yoffset, zoffset, + dstRowStride, dstImageStride, + width, height, depth, + 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); @@ -1171,7 +2891,7 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, 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, @@ -1428,7 +3148,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, } } return; - case MESA_FORMAT_DEPTH_COMPONENT: + case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32: { GLuint i, j, k; const GLfloat *rowA = (const GLfloat *) srcRowA; @@ -1440,6 +3160,18 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, } } return; + case MESA_FORMAT_DEPTH_COMPONENT16: + { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; + } + } + return; /* Begin hardware formats */ case MESA_FORMAT_RGBA8888: case MESA_FORMAT_ARGB8888: @@ -1626,6 +3358,148 @@ do_row(const struct gl_texture_format *format, GLint srcWidth, } } return; + case MESA_FORMAT_RGBA_FLOAT32: + { + GLuint i, j, k; + const GLfloat (*rowA)[4] = (const GLfloat (*)[4]) srcRowA; + const GLfloat (*rowB)[4] = (const GLfloat (*)[4]) srcRowB; + GLfloat (*dst)[4] = (GLfloat (*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) * 0.25F; + dst[i][3] = (rowA[j][3] + rowA[k][3] + + rowB[j][3] + rowB[k][3]) * 0.25F; + } + } + return; + case MESA_FORMAT_RGBA_FLOAT16: + { + GLuint i, j, k, comp; + const GLhalfARB (*rowA)[4] = (const GLhalfARB (*)[4]) srcRowA; + const GLhalfARB (*rowB)[4] = (const GLhalfARB (*)[4]) srcRowB; + GLhalfARB (*dst)[4] = (GLhalfARB (*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 4; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + return; + case MESA_FORMAT_RGB_FLOAT32: + { + GLuint i, j, k; + const GLfloat (*rowA)[3] = (const GLfloat (*)[3]) srcRowA; + const GLfloat (*rowB)[3] = (const GLfloat (*)[3]) srcRowB; + GLfloat (*dst)[3] = (GLfloat (*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) * 0.25F; + } + } + return; + case MESA_FORMAT_RGB_FLOAT16: + { + GLuint i, j, k, comp; + const GLhalfARB (*rowA)[3] = (const GLhalfARB (*)[3]) srcRowA; + const GLhalfARB (*rowB)[3] = (const GLhalfARB (*)[3]) srcRowB; + GLhalfARB (*dst)[3] = (GLhalfARB (*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 3; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + return; + case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32: + { + GLuint i, j, k; + const GLfloat (*rowA)[2] = (const GLfloat (*)[2]) srcRowA; + const GLfloat (*rowB)[2] = (const GLfloat (*)[2]) srcRowB; + GLfloat (*dst)[2] = (GLfloat (*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + } + } + return; + case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16: + { + GLuint i, j, k, comp; + const GLhalfARB (*rowA)[2] = (const GLhalfARB (*)[2]) srcRowA; + const GLhalfARB (*rowB)[2] = (const GLhalfARB (*)[2]) srcRowB; + GLhalfARB (*dst)[2] = (GLhalfARB (*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 2; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + return; + case MESA_FORMAT_ALPHA_FLOAT32: + case MESA_FORMAT_LUMINANCE_FLOAT32: + case MESA_FORMAT_INTENSITY_FLOAT32: + { + GLuint i, j, k; + const GLfloat *rowA = (const GLfloat *) srcRowA; + const GLfloat *rowB = (const GLfloat *) srcRowB; + GLfloat *dst = (GLfloat *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; + } + } + return; + case MESA_FORMAT_ALPHA_FLOAT16: + case MESA_FORMAT_LUMINANCE_FLOAT16: + case MESA_FORMAT_INTENSITY_FLOAT16: + { + GLuint i, j, k; + const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; + const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; + GLhalfARB *dst = (GLhalfARB *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j]); + ak = _mesa_half_to_float(rowA[k]); + bj = _mesa_half_to_float(rowB[j]); + bk = _mesa_half_to_float(rowB[k]); + dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + return; + default: _mesa_problem(NULL, "bad format in do_row()"); } |