| /* |
| * Mesa 3-D graphics library |
| * Version: 7.5 |
| * |
| * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. |
| * Copyright (c) 2008-2009 VMware, Inc. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| /* |
| * Authors: |
| * Brian Paul |
| */ |
| |
| /** |
| * The GL texture image functions in teximage.c basically just do |
| * error checking and data structure allocation. They in turn call |
| * device driver functions which actually copy/convert/store the user's |
| * texture image data. |
| * |
| * However, most device drivers will be able to use the fallback functions |
| * in this file. That is, most drivers will have the following bit of |
| * code: |
| * ctx->Driver.TexImage = _mesa_store_teximage; |
| * ctx->Driver.TexSubImage = _mesa_store_texsubimage; |
| * etc... |
| * |
| * Texture image processing is actually kind of complicated. We have to do: |
| * Format/type conversions |
| * pixel unpacking |
| * pixel transfer (scale, bais, lookup, etc) |
| * |
| * These functions can handle most everything, including processing full |
| * images and sub-images. |
| */ |
| |
| |
| #include "glheader.h" |
| #include "bufferobj.h" |
| #include "colormac.h" |
| #include "format_pack.h" |
| #include "image.h" |
| #include "macros.h" |
| #include "mipmap.h" |
| #include "mfeatures.h" |
| #include "mtypes.h" |
| #include "pack.h" |
| #include "pbo.h" |
| #include "imports.h" |
| #include "texcompress.h" |
| #include "texcompress_fxt1.h" |
| #include "texcompress_rgtc.h" |
| #include "texcompress_s3tc.h" |
| #include "texcompress_etc.h" |
| #include "teximage.h" |
| #include "texstore.h" |
| #include "enums.h" |
| #include "glformats.h" |
| #include "../../gallium/auxiliary/util/u_format_rgb9e5.h" |
| #include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" |
| |
| |
| enum { |
| ZERO = 4, |
| ONE = 5 |
| }; |
| |
| |
| /** |
| * Texture image storage function. |
| */ |
| typedef GLboolean (*StoreTexImageFunc)(TEXSTORE_PARAMS); |
| |
| |
| /** |
| * Return GL_TRUE if the given image format is one that be converted |
| * to another format by swizzling. |
| */ |
| static GLboolean |
| can_swizzle(GLenum logicalBaseFormat) |
| { |
| switch (logicalBaseFormat) { |
| case GL_RGBA: |
| case GL_RGB: |
| case GL_LUMINANCE_ALPHA: |
| case GL_INTENSITY: |
| case GL_ALPHA: |
| case GL_LUMINANCE: |
| case GL_RED: |
| case GL_GREEN: |
| case GL_BLUE: |
| case GL_BGR: |
| case GL_BGRA: |
| case GL_ABGR_EXT: |
| case GL_RG: |
| return GL_TRUE; |
| default: |
| return GL_FALSE; |
| } |
| } |
| |
| |
| |
| enum { |
| IDX_LUMINANCE = 0, |
| IDX_ALPHA, |
| IDX_INTENSITY, |
| IDX_LUMINANCE_ALPHA, |
| IDX_RGB, |
| IDX_RGBA, |
| IDX_RED, |
| IDX_GREEN, |
| IDX_BLUE, |
| IDX_BGR, |
| IDX_BGRA, |
| IDX_ABGR, |
| IDX_RG, |
| MAX_IDX |
| }; |
| |
| #define MAP1(x) MAP4(x, ZERO, ZERO, ZERO) |
| #define MAP2(x,y) MAP4(x, y, ZERO, ZERO) |
| #define MAP3(x,y,z) MAP4(x, y, z, ZERO) |
| #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE } |
| |
| |
| static const struct { |
| GLubyte format_idx; |
| GLubyte to_rgba[6]; |
| GLubyte from_rgba[6]; |
| } mappings[MAX_IDX] = |
| { |
| { |
| IDX_LUMINANCE, |
| MAP4(0,0,0,ONE), |
| MAP1(0) |
| }, |
| |
| { |
| IDX_ALPHA, |
| MAP4(ZERO, ZERO, ZERO, 0), |
| MAP1(3) |
| }, |
| |
| { |
| IDX_INTENSITY, |
| MAP4(0, 0, 0, 0), |
| MAP1(0), |
| }, |
| |
| { |
| IDX_LUMINANCE_ALPHA, |
| MAP4(0,0,0,1), |
| MAP2(0,3) |
| }, |
| |
| { |
| IDX_RGB, |
| MAP4(0,1,2,ONE), |
| MAP3(0,1,2) |
| }, |
| |
| { |
| IDX_RGBA, |
| MAP4(0,1,2,3), |
| MAP4(0,1,2,3), |
| }, |
| |
| { |
| IDX_RED, |
| MAP4(0, ZERO, ZERO, ONE), |
| MAP1(0), |
| }, |
| |
| { |
| IDX_GREEN, |
| MAP4(ZERO, 0, ZERO, ONE), |
| MAP1(1), |
| }, |
| |
| { |
| IDX_BLUE, |
| MAP4(ZERO, ZERO, 0, ONE), |
| MAP1(2), |
| }, |
| |
| { |
| IDX_BGR, |
| MAP4(2,1,0,ONE), |
| MAP3(2,1,0) |
| }, |
| |
| { |
| IDX_BGRA, |
| MAP4(2,1,0,3), |
| MAP4(2,1,0,3) |
| }, |
| |
| { |
| IDX_ABGR, |
| MAP4(3,2,1,0), |
| MAP4(3,2,1,0) |
| }, |
| |
| { |
| IDX_RG, |
| MAP4(0, 1, ZERO, ONE), |
| MAP2(0, 1) |
| }, |
| }; |
| |
| |
| |
| /** |
| * Convert a GL image format enum to an IDX_* value (see above). |
| */ |
| static int |
| get_map_idx(GLenum value) |
| { |
| switch (value) { |
| case GL_LUMINANCE: return IDX_LUMINANCE; |
| case GL_ALPHA: return IDX_ALPHA; |
| case GL_INTENSITY: return IDX_INTENSITY; |
| case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA; |
| case GL_RGB: return IDX_RGB; |
| case GL_RGBA: return IDX_RGBA; |
| case GL_RED: return IDX_RED; |
| case GL_GREEN: return IDX_GREEN; |
| case GL_BLUE: return IDX_BLUE; |
| case GL_BGR: return IDX_BGR; |
| case GL_BGRA: return IDX_BGRA; |
| case GL_ABGR_EXT: return IDX_ABGR; |
| case GL_RG: return IDX_RG; |
| default: |
| _mesa_problem(NULL, "Unexpected inFormat"); |
| return 0; |
| } |
| } |
| |
| |
| /** |
| * When promoting texture formats (see below) we need to compute the |
| * mapping of dest components back to source components. |
| * This function does that. |
| * \param inFormat the incoming format of the texture |
| * \param outFormat the final texture format |
| * \return map[6] a full 6-component map |
| */ |
| static void |
| compute_component_mapping(GLenum inFormat, GLenum outFormat, |
| GLubyte *map) |
| { |
| const int inFmt = get_map_idx(inFormat); |
| const int outFmt = get_map_idx(outFormat); |
| const GLubyte *in2rgba = mappings[inFmt].to_rgba; |
| const GLubyte *rgba2out = mappings[outFmt].from_rgba; |
| int i; |
| |
| for (i = 0; i < 4; i++) |
| map[i] = in2rgba[rgba2out[i]]; |
| |
| map[ZERO] = ZERO; |
| map[ONE] = ONE; |
| |
| #if 0 |
| printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n", |
| inFormat, _mesa_lookup_enum_by_nr(inFormat), |
| outFormat, _mesa_lookup_enum_by_nr(outFormat), |
| map[0], |
| map[1], |
| map[2], |
| map[3], |
| map[4], |
| map[5]); |
| #endif |
| } |
| |
| |
| /** |
| * 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, we 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. |
| */ |
| GLfloat * |
| _mesa_make_temp_float_image(struct gl_context *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, |
| GLbitfield transferOps) |
| { |
| GLfloat *tempImage; |
| const GLint components = _mesa_components_in_format(logicalBaseFormat); |
| const GLint srcStride = |
| _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); |
| GLfloat *dst; |
| GLint img, row; |
| |
| ASSERT(dims >= 1 && dims <= 3); |
| |
| ASSERT(logicalBaseFormat == GL_RGBA || |
| logicalBaseFormat == GL_RGB || |
| logicalBaseFormat == GL_RG || |
| logicalBaseFormat == GL_RED || |
| logicalBaseFormat == GL_LUMINANCE_ALPHA || |
| logicalBaseFormat == GL_LUMINANCE || |
| logicalBaseFormat == GL_ALPHA || |
| logicalBaseFormat == GL_INTENSITY || |
| logicalBaseFormat == GL_DEPTH_COMPONENT); |
| |
| ASSERT(textureBaseFormat == GL_RGBA || |
| textureBaseFormat == GL_RGB || |
| textureBaseFormat == GL_RG || |
| textureBaseFormat == GL_RED || |
| textureBaseFormat == GL_LUMINANCE_ALPHA || |
| textureBaseFormat == GL_LUMINANCE || |
| textureBaseFormat == GL_ALPHA || |
| textureBaseFormat == GL_INTENSITY || |
| textureBaseFormat == GL_DEPTH_COMPONENT); |
| |
| tempImage = (GLfloat *) 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(dims, 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; |
| GLubyte map[6]; |
| |
| /* 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. |
| */ |
| ASSERT(texComponents >= logComponents); |
| |
| newImage = (GLfloat *) malloc(srcWidth * srcHeight * srcDepth |
| * texComponents * sizeof(GLfloat)); |
| if (!newImage) { |
| 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]; |
| } |
| } |
| |
| free(tempImage); |
| tempImage = newImage; |
| } |
| |
| return tempImage; |
| } |
| |
| |
| /** |
| * Make temporary image with uint pixel values. Used for unsigned |
| * integer-valued textures. |
| */ |
| static GLuint * |
| make_temp_uint_image(struct gl_context *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 *tempImage; |
| const GLint components = _mesa_components_in_format(logicalBaseFormat); |
| const GLint srcStride = |
| _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); |
| GLuint *dst; |
| GLint img, row; |
| |
| ASSERT(dims >= 1 && dims <= 3); |
| |
| ASSERT(logicalBaseFormat == GL_RGBA || |
| logicalBaseFormat == GL_RGB || |
| logicalBaseFormat == GL_RG || |
| logicalBaseFormat == GL_RED || |
| logicalBaseFormat == GL_LUMINANCE_ALPHA || |
| logicalBaseFormat == GL_LUMINANCE || |
| logicalBaseFormat == GL_INTENSITY || |
| logicalBaseFormat == GL_ALPHA); |
| |
| ASSERT(textureBaseFormat == GL_RGBA || |
| textureBaseFormat == GL_RGB || |
| textureBaseFormat == GL_RG || |
| textureBaseFormat == GL_RED || |
| textureBaseFormat == GL_LUMINANCE_ALPHA || |
| textureBaseFormat == GL_LUMINANCE || |
| textureBaseFormat == GL_INTENSITY || |
| textureBaseFormat == GL_ALPHA); |
| |
| tempImage = (GLuint *) malloc(srcWidth * srcHeight * srcDepth |
| * components * sizeof(GLuint)); |
| if (!tempImage) |
| return NULL; |
| |
| dst = tempImage; |
| for (img = 0; img < srcDepth; img++) { |
| const GLubyte *src |
| = (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_uint(ctx, srcWidth, logicalBaseFormat, |
| dst, srcFormat, srcType, src, |
| srcPacking); |
| dst += srcWidth * components; |
| src += srcStride; |
| } |
| } |
| |
| if (logicalBaseFormat != textureBaseFormat) { |
| /* more work */ |
| GLint texComponents = _mesa_components_in_format(textureBaseFormat); |
| GLint logComponents = _mesa_components_in_format(logicalBaseFormat); |
| GLuint *newImage; |
| GLint i, n; |
| GLubyte map[6]; |
| |
| /* 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. |
| */ |
| ASSERT(texComponents >= logComponents); |
| |
| newImage = (GLuint *) malloc(srcWidth * srcHeight * srcDepth |
| * texComponents * sizeof(GLuint)); |
| if (!newImage) { |
| 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] = 1; |
| else |
| newImage[i * texComponents + k] = tempImage[i * logComponents + j]; |
| } |
| } |
| |
| free(tempImage); |
| tempImage = newImage; |
| } |
| |
| return tempImage; |
| } |
| |
| |
| |
| /** |
| * Make a temporary (color) texture image with GLubyte 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, we 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 = GLubyte. |
| */ |
| GLubyte * |
| _mesa_make_temp_ubyte_image(struct gl_context *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); |
| GLint img, row; |
| GLubyte *tempImage, *dst; |
| |
| ASSERT(dims >= 1 && dims <= 3); |
| |
| ASSERT(logicalBaseFormat == GL_RGBA || |
| logicalBaseFormat == GL_RGB || |
| logicalBaseFormat == GL_RG || |
| logicalBaseFormat == GL_RED || |
| logicalBaseFormat == GL_LUMINANCE_ALPHA || |
| logicalBaseFormat == GL_LUMINANCE || |
| logicalBaseFormat == GL_ALPHA || |
| logicalBaseFormat == GL_INTENSITY); |
| |
| ASSERT(textureBaseFormat == GL_RGBA || |
| textureBaseFormat == GL_RGB || |
| textureBaseFormat == GL_RG || |
| textureBaseFormat == GL_RED || |
| textureBaseFormat == GL_LUMINANCE_ALPHA || |
| textureBaseFormat == GL_LUMINANCE || |
| textureBaseFormat == GL_ALPHA || |
| textureBaseFormat == GL_INTENSITY); |
| |
| /* unpack and transfer the source image */ |
| tempImage = (GLubyte *) malloc(srcWidth * srcHeight * srcDepth |
| * components * sizeof(GLubyte)); |
| 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(dims, srcPacking, srcAddr, |
| srcWidth, srcHeight, |
| srcFormat, srcType, |
| img, 0, 0); |
| for (row = 0; row < srcHeight; row++) { |
| _mesa_unpack_color_span_ubyte(ctx, srcWidth, logicalBaseFormat, dst, |
| srcFormat, srcType, src, srcPacking, |
| transferOps); |
| dst += srcWidth * components; |
| src += srcStride; |
| } |
| } |
| |
| if (logicalBaseFormat != textureBaseFormat) { |
| /* one more conversion step */ |
| GLint texComponents = _mesa_components_in_format(textureBaseFormat); |
| GLint logComponents = _mesa_components_in_format(logicalBaseFormat); |
| GLubyte *newImage; |
| GLint i, n; |
| GLubyte map[6]; |
| |
| /* 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. |
| */ |
| ASSERT(texComponents >= logComponents); |
| |
| newImage = (GLubyte *) malloc(srcWidth * srcHeight * srcDepth |
| * texComponents * sizeof(GLubyte)); |
| if (!newImage) { |
| 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] = 255; |
| else |
| newImage[i * texComponents + k] = tempImage[i * logComponents + j]; |
| } |
| } |
| |
| free(tempImage); |
| tempImage = newImage; |
| } |
| |
| return tempImage; |
| } |
| |
| |
| /** |
| * Copy GLubyte pixels from <src> to <dst> with swizzling. |
| * \param dst destination pixels |
| * \param dstComponents number of color components in destination pixels |
| * \param src source pixels |
| * \param srcComponents number of color components in source pixels |
| * \param map the swizzle mapping. map[X] says where to find the X component |
| * in the source image's pixels. For example, if the source image |
| * is GL_BGRA and X = red, map[0] yields 2. |
| * \param count number of pixels to copy/swizzle. |
| */ |
| static void |
| swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src, |
| GLuint srcComponents, const GLubyte *map, GLuint count) |
| { |
| #define SWZ_CPY(dst, src, count, dstComps, srcComps) \ |
| do { \ |
| GLuint i; \ |
| for (i = 0; i < count; i++) { \ |
| GLuint j; \ |
| if (srcComps == 4) { \ |
| COPY_4UBV(tmp, src); \ |
| } \ |
| else { \ |
| for (j = 0; j < srcComps; j++) { \ |
| tmp[j] = src[j]; \ |
| } \ |
| } \ |
| src += srcComps; \ |
| for (j = 0; j < dstComps; j++) { \ |
| dst[j] = tmp[map[j]]; \ |
| } \ |
| dst += dstComps; \ |
| } \ |
| } while (0) |
| |
| GLubyte tmp[6]; |
| |
| tmp[ZERO] = 0x0; |
| tmp[ONE] = 0xff; |
| |
| ASSERT(srcComponents <= 4); |
| ASSERT(dstComponents <= 4); |
| |
| switch (dstComponents) { |
| case 4: |
| switch (srcComponents) { |
| case 4: |
| SWZ_CPY(dst, src, count, 4, 4); |
| break; |
| case 3: |
| SWZ_CPY(dst, src, count, 4, 3); |
| break; |
| case 2: |
| SWZ_CPY(dst, src, count, 4, 2); |
| break; |
| case 1: |
| SWZ_CPY(dst, src, count, 4, 1); |
| break; |
| default: |
| ; |
| } |
| break; |
| case 3: |
| switch (srcComponents) { |
| case 4: |
| SWZ_CPY(dst, src, count, 3, 4); |
| break; |
| case 3: |
| SWZ_CPY(dst, src, count, 3, 3); |
| break; |
| case 2: |
| SWZ_CPY(dst, src, count, 3, 2); |
| break; |
| case 1: |
| SWZ_CPY(dst, src, count, 3, 1); |
| break; |
| default: |
| ; |
| } |
| break; |
| case 2: |
| switch (srcComponents) { |
| case 4: |
| SWZ_CPY(dst, src, count, 2, 4); |
| break; |
| case 3: |
| SWZ_CPY(dst, src, count, 2, 3); |
| break; |
| case 2: |
| SWZ_CPY(dst, src, count, 2, 2); |
| break; |
| case 1: |
| SWZ_CPY(dst, src, count, 2, 1); |
| break; |
| default: |
| ; |
| } |
| break; |
| case 1: |
| switch (srcComponents) { |
| case 4: |
| SWZ_CPY(dst, src, count, 1, 4); |
| break; |
| case 3: |
| SWZ_CPY(dst, src, count, 1, 3); |
| break; |
| case 2: |
| SWZ_CPY(dst, src, count, 1, 2); |
| break; |
| case 1: |
| SWZ_CPY(dst, src, count, 1, 1); |
| break; |
| default: |
| ; |
| } |
| break; |
| default: |
| ; |
| } |
| #undef SWZ_CPY |
| } |
| |
| |
| |
| static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE }; |
| static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE }; |
| |
| |
| /** |
| * For 1-byte/pixel formats (or 8_8_8_8 packed formats), return a |
| * mapping array depending on endianness. |
| */ |
| static const GLubyte * |
| type_mapping( GLenum srcType ) |
| { |
| switch (srcType) { |
| case GL_BYTE: |
| case GL_UNSIGNED_BYTE: |
| return map_identity; |
| case GL_UNSIGNED_INT_8_8_8_8: |
| return _mesa_little_endian() ? map_3210 : map_identity; |
| case GL_UNSIGNED_INT_8_8_8_8_REV: |
| return _mesa_little_endian() ? map_identity : map_3210; |
| default: |
| return NULL; |
| } |
| } |
| |
| |
| /** |
| * For 1-byte/pixel formats (or 8_8_8_8 packed formats), return a |
| * mapping array depending on pixelstore byte swapping state. |
| */ |
| static const GLubyte * |
| byteswap_mapping( GLboolean swapBytes, |
| GLenum srcType ) |
| { |
| if (!swapBytes) |
| return map_identity; |
| |
| switch (srcType) { |
| case GL_BYTE: |
| case GL_UNSIGNED_BYTE: |
| return map_identity; |
| case GL_UNSIGNED_INT_8_8_8_8: |
| case GL_UNSIGNED_INT_8_8_8_8_REV: |
| return map_3210; |
| default: |
| return NULL; |
| } |
| } |
| |
| |
| |
| /** |
| * Transfer a GLubyte texture image with component swizzling. |
| */ |
| static void |
| _mesa_swizzle_ubyte_image(struct gl_context *ctx, |
| GLuint dimensions, |
| GLenum srcFormat, |
| GLenum srcType, |
| |
| GLenum baseInternalFormat, |
| |
| const GLubyte *rgba2dst, |
| GLuint dstComponents, |
| |
| GLint dstRowStride, |
| GLubyte **dstSlices, |
| |
| GLint srcWidth, GLint srcHeight, GLint srcDepth, |
| const GLvoid *srcAddr, |
| const struct gl_pixelstore_attrib *srcPacking ) |
| { |
| GLint srcComponents = _mesa_components_in_format(srcFormat); |
| const GLubyte *srctype2ubyte, *swap; |
| GLubyte map[4], src2base[6], base2rgba[6]; |
| GLint i; |
| const GLint srcRowStride = |
| _mesa_image_row_stride(srcPacking, srcWidth, |
| srcFormat, GL_UNSIGNED_BYTE); |
| 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); |
| |
| (void) ctx; |
| |
| /* Translate from src->baseInternal->GL_RGBA->dst. This will |
| * correctly deal with RGBA->RGB->RGBA conversions where the final |
| * A value must be 0xff regardless of the incoming alpha values. |
| */ |
| compute_component_mapping(srcFormat, baseInternalFormat, src2base); |
| compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba); |
| swap = byteswap_mapping(srcPacking->SwapBytes, srcType); |
| srctype2ubyte = type_mapping(srcType); |
| |
| |
| for (i = 0; i < 4; i++) |
| map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]]; |
| |
| /* printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */ |
| |
| if (srcComponents == dstComponents && |
| srcRowStride == dstRowStride && |
| srcRowStride == srcWidth * srcComponents && |
| dimensions < 3) { |
| /* 1 and 2D images only */ |
| GLubyte *dstImage = dstSlices[0]; |
| swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, |
| srcWidth * srcHeight); |
| } |
| else { |
| GLint img, row; |
| for (img = 0; img < srcDepth; img++) { |
| const GLubyte *srcRow = srcImage; |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth); |
| dstRow += dstRowStride; |
| srcRow += srcRowStride; |
| } |
| srcImage += srcImageStride; |
| } |
| } |
| } |
| |
| |
| /** |
| * 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(struct gl_context *ctx, |
| GLuint dimensions, |
| gl_format dstFormat, |
| GLint dstRowStride, |
| GLubyte **dstSlices, |
| 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(dimensions, |
| srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); |
| const GLuint texelBytes = _mesa_get_format_bytes(dstFormat); |
| const GLint bytesPerRow = srcWidth * texelBytes; |
| |
| if (dstRowStride == srcRowStride && |
| dstRowStride == bytesPerRow) { |
| /* memcpy image by image */ |
| GLint img; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstImage = dstSlices[img]; |
| memcpy(dstImage, srcImage, bytesPerRow * srcHeight); |
| srcImage += srcImageStride; |
| } |
| } |
| else { |
| /* memcpy row by row */ |
| GLint img, row; |
| for (img = 0; img < srcDepth; img++) { |
| const GLubyte *srcRow = srcImage; |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| memcpy(dstRow, srcRow, bytesPerRow); |
| dstRow += dstRowStride; |
| srcRow += srcRowStride; |
| } |
| srcImage += srcImageStride; |
| } |
| } |
| } |
| |
| |
| /** |
| * General-case function for storing a color texture images with |
| * components that can be represented with ubytes. Example destination |
| * texture formats are MESA_FORMAT_ARGB888, ARGB4444, RGB565. |
| */ |
| static GLboolean |
| store_ubyte_texture(TEXSTORE_PARAMS) |
| { |
| const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte); |
| GLubyte *tempImage, *src; |
| GLint img; |
| |
| tempImage = _mesa_make_temp_ubyte_image(ctx, dims, |
| baseInternalFormat, |
| GL_RGBA, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking); |
| if (!tempImage) |
| return GL_FALSE; |
| |
| src = tempImage; |
| for (img = 0; img < srcDepth; img++) { |
| _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight, |
| src, srcRowStride, |
| dstSlices[img], dstRowStride); |
| src += srcHeight * srcRowStride; |
| } |
| free(tempImage); |
| |
| return GL_TRUE; |
| } |
| |
| |
| |
| |
| /** |
| * Store a 32-bit integer or float depth component texture image. |
| */ |
| static GLboolean |
| _mesa_texstore_z32(TEXSTORE_PARAMS) |
| { |
| const GLuint depthScale = 0xffffffff; |
| GLenum dstType; |
| (void) dims; |
| ASSERT(dstFormat == MESA_FORMAT_Z32 || |
| dstFormat == MESA_FORMAT_Z32_FLOAT); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == sizeof(GLuint)); |
| |
| if (dstFormat == MESA_FORMAT_Z32) |
| dstType = GL_UNSIGNED_INT; |
| else |
| dstType = GL_FLOAT; |
| |
| if (ctx->Pixel.DepthScale == 1.0f && |
| ctx->Pixel.DepthBias == 0.0f && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == GL_DEPTH_COMPONENT && |
| srcFormat == GL_DEPTH_COMPONENT && |
| srcType == dstType) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| GLint img, row; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| const GLvoid *src = _mesa_image_address(dims, srcPacking, |
| srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); |
| _mesa_unpack_depth_span(ctx, srcWidth, |
| dstType, dstRow, |
| depthScale, srcType, src, srcPacking); |
| dstRow += dstRowStride; |
| } |
| } |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store a 24-bit integer depth component texture image. |
| */ |
| static GLboolean |
| _mesa_texstore_x8_z24(TEXSTORE_PARAMS) |
| { |
| const GLuint depthScale = 0xffffff; |
| |
| (void) dims; |
| ASSERT(dstFormat == MESA_FORMAT_X8_Z24); |
| |
| { |
| /* general path */ |
| GLint img, row; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| const GLvoid *src = _mesa_image_address(dims, srcPacking, |
| srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); |
| _mesa_unpack_depth_span(ctx, srcWidth, |
| GL_UNSIGNED_INT, (GLuint *) dstRow, |
| depthScale, srcType, src, srcPacking); |
| dstRow += dstRowStride; |
| } |
| } |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store a 24-bit integer depth component texture image. |
| */ |
| static GLboolean |
| _mesa_texstore_z24_x8(TEXSTORE_PARAMS) |
| { |
| const GLuint depthScale = 0xffffff; |
| |
| (void) dims; |
| ASSERT(dstFormat == MESA_FORMAT_Z24_X8); |
| |
| { |
| /* general path */ |
| GLint img, row; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| const GLvoid *src = _mesa_image_address(dims, srcPacking, |
| srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); |
| GLuint *dst = (GLuint *) dstRow; |
| GLint i; |
| _mesa_unpack_depth_span(ctx, srcWidth, |
| GL_UNSIGNED_INT, dst, |
| depthScale, srcType, src, srcPacking); |
| for (i = 0; i < srcWidth; i++) |
| dst[i] <<= 8; |
| dstRow += dstRowStride; |
| } |
| } |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store a 16-bit integer depth component texture image. |
| */ |
| static GLboolean |
| _mesa_texstore_z16(TEXSTORE_PARAMS) |
| { |
| const GLuint depthScale = 0xffff; |
| (void) dims; |
| ASSERT(dstFormat == MESA_FORMAT_Z16); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == sizeof(GLushort)); |
| |
| if (ctx->Pixel.DepthScale == 1.0f && |
| ctx->Pixel.DepthBias == 0.0f && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == GL_DEPTH_COMPONENT && |
| srcFormat == GL_DEPTH_COMPONENT && |
| srcType == GL_UNSIGNED_SHORT) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| GLint img, row; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| 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, |
| GL_UNSIGNED_SHORT, dst16, depthScale, |
| srcType, src, srcPacking); |
| dstRow += dstRowStride; |
| } |
| } |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store an rgb565 or rgb565_rev texture image. |
| */ |
| static GLboolean |
| _mesa_texstore_rgb565(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_RGB565 || |
| dstFormat == MESA_FORMAT_RGB565_REV); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 2); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGB && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| 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(dims, srcPacking, srcAddr, srcWidth, srcHeight, |
| srcFormat, srcType, 0, 0, 0); |
| GLubyte *dst = dstSlices[0]; |
| GLint row, col; |
| for (row = 0; row < srcHeight; row++) { |
| const GLubyte *srcUB = (const GLubyte *) src; |
| GLushort *dstUS = (GLushort *) dst; |
| /* check for byteswapped format */ |
| if (dstFormat == MESA_FORMAT_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; |
| } |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV. |
| */ |
| static GLboolean |
| _mesa_texstore_rgba8888(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| |
| ASSERT(dstFormat == MESA_FORMAT_RGBA8888 || |
| dstFormat == MESA_FORMAT_RGBA8888_REV || |
| dstFormat == MESA_FORMAT_RGBX8888 || |
| dstFormat == MESA_FORMAT_RGBX8888_REV); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else if (!ctx->_ImageTransferState && |
| (srcType == GL_UNSIGNED_BYTE || |
| srcType == GL_UNSIGNED_INT_8_8_8_8 || |
| srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && |
| can_swizzle(baseInternalFormat) && |
| can_swizzle(srcFormat)) { |
| |
| GLubyte dstmap[4]; |
| |
| /* dstmap - how to swizzle from RGBA to dst format: |
| */ |
| if ((littleEndian && (dstFormat == MESA_FORMAT_RGBA8888 || |
| dstFormat == MESA_FORMAT_RGBX8888)) || |
| (!littleEndian && (dstFormat == MESA_FORMAT_RGBA8888_REV || |
| dstFormat == MESA_FORMAT_RGBX8888_REV))) { |
| dstmap[3] = 0; |
| dstmap[2] = 1; |
| dstmap[1] = 2; |
| dstmap[0] = 3; |
| } |
| else { |
| dstmap[3] = 3; |
| dstmap[2] = 2; |
| dstmap[1] = 1; |
| dstmap[0] = 0; |
| } |
| |
| _mesa_swizzle_ubyte_image(ctx, dims, |
| srcFormat, |
| srcType, |
| baseInternalFormat, |
| dstmap, 4, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcAddr, |
| srcPacking); |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_argb8888(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| |
| ASSERT(dstFormat == MESA_FORMAT_ARGB8888 || |
| dstFormat == MESA_FORMAT_ARGB8888_REV || |
| dstFormat == MESA_FORMAT_XRGB8888 || |
| dstFormat == MESA_FORMAT_XRGB8888_REV ); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path (big endian) */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| (dstFormat == MESA_FORMAT_ARGB8888 || |
| dstFormat == MESA_FORMAT_XRGB8888) && |
| srcFormat == GL_RGB && |
| (baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB) && |
| srcType == GL_UNSIGNED_BYTE) { |
| int img, row, col; |
| 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 = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *d4 = (GLuint *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| d4[col] = PACK_COLOR_8888(0xff, |
| srcRow[col * 3 + RCOMP], |
| srcRow[col * 3 + GCOMP], |
| srcRow[col * 3 + BCOMP]); |
| } |
| dstRow += dstRowStride; |
| srcRow += srcRowStride; |
| } |
| } |
| } |
| else if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| dstFormat == MESA_FORMAT_ARGB8888 && |
| srcFormat == GL_LUMINANCE_ALPHA && |
| baseInternalFormat == GL_RGBA && |
| srcType == GL_UNSIGNED_BYTE) { |
| /* special case of storing LA -> ARGB8888 */ |
| int img, row, col; |
| const GLint srcRowStride = |
| _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); |
| for (img = 0; img < srcDepth; img++) { |
| const GLubyte *srcRow = (const GLubyte *) |
| _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, |
| srcHeight, srcFormat, srcType, img, 0, 0); |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *d4 = (GLuint *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| GLubyte l = srcRow[col * 2 + 0], a = srcRow[col * 2 + 1]; |
| d4[col] = PACK_COLOR_8888(a, l, l, l); |
| } |
| dstRow += dstRowStride; |
| srcRow += srcRowStride; |
| } |
| } |
| } |
| else if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| dstFormat == MESA_FORMAT_ARGB8888 && |
| srcFormat == GL_RGBA && |
| baseInternalFormat == GL_RGBA && |
| srcType == GL_UNSIGNED_BYTE) { |
| /* same as above case, but src data has alpha too */ |
| GLint img, row, col; |
| /* For some reason, streaming copies to write-combined regions |
| * are extremely sensitive to the characteristics of how the |
| * source data is retrieved. By reordering the source reads to |
| * be in-order, the speed of this operation increases by half. |
| * Strangely the same isn't required for the RGB path, above. |
| */ |
| 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 = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *d4 = (GLuint *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| d4[col] = PACK_COLOR_8888(srcRow[col * 4 + ACOMP], |
| srcRow[col * 4 + RCOMP], |
| srcRow[col * 4 + GCOMP], |
| srcRow[col * 4 + BCOMP]); |
| } |
| dstRow += dstRowStride; |
| srcRow += srcRowStride; |
| } |
| } |
| } |
| else if (!ctx->_ImageTransferState && |
| (srcType == GL_UNSIGNED_BYTE || |
| srcType == GL_UNSIGNED_INT_8_8_8_8 || |
| srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && |
| can_swizzle(baseInternalFormat) && |
| can_swizzle(srcFormat)) { |
| |
| GLubyte dstmap[4]; |
| |
| /* dstmap - how to swizzle from RGBA to dst format: |
| */ |
| if ((littleEndian && dstFormat == MESA_FORMAT_ARGB8888) || |
| (littleEndian && dstFormat == MESA_FORMAT_XRGB8888) || |
| (!littleEndian && dstFormat == MESA_FORMAT_ARGB8888_REV) || |
| (!littleEndian && dstFormat == MESA_FORMAT_XRGB8888_REV)) { |
| dstmap[3] = 3; /* alpha */ |
| dstmap[2] = 0; /* red */ |
| dstmap[1] = 1; /* green */ |
| dstmap[0] = 2; /* blue */ |
| } |
| else { |
| assert((littleEndian && dstFormat == MESA_FORMAT_ARGB8888_REV) || |
| (!littleEndian && dstFormat == MESA_FORMAT_ARGB8888) || |
| (littleEndian && dstFormat == MESA_FORMAT_XRGB8888_REV) || |
| (!littleEndian && dstFormat == MESA_FORMAT_XRGB8888)); |
| dstmap[3] = 2; |
| dstmap[2] = 1; |
| dstmap[1] = 0; |
| dstmap[0] = 3; |
| } |
| |
| _mesa_swizzle_ubyte_image(ctx, dims, |
| srcFormat, |
| srcType, |
| baseInternalFormat, |
| dstmap, 4, |
| dstRowStride, |
| dstSlices, |
| srcWidth, srcHeight, srcDepth, srcAddr, |
| srcPacking); |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_rgb888(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_RGB888); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 3); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGB && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| srcFormat == GL_RGBA && |
| srcType == GL_UNSIGNED_BYTE) { |
| /* extract RGB from RGBA */ |
| GLint img, row, col; |
| 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 = dstSlices[img]; |
| 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; |
| } |
| } |
| } |
| else if (!ctx->_ImageTransferState && |
| srcType == GL_UNSIGNED_BYTE && |
| can_swizzle(baseInternalFormat) && |
| can_swizzle(srcFormat)) { |
| |
| GLubyte dstmap[4]; |
| |
| /* dstmap - how to swizzle from RGBA to dst format: |
| */ |
| dstmap[0] = 2; |
| dstmap[1] = 1; |
| dstmap[2] = 0; |
| dstmap[3] = ONE; /* ? */ |
| |
| _mesa_swizzle_ubyte_image(ctx, dims, |
| srcFormat, |
| srcType, |
| baseInternalFormat, |
| dstmap, 3, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcAddr, |
| srcPacking); |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_bgr888(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_BGR888); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 3); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGB && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| 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; |
| 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 = dstSlices[img]; |
| 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; |
| } |
| } |
| } |
| else if (!ctx->_ImageTransferState && |
| srcType == GL_UNSIGNED_BYTE && |
| can_swizzle(baseInternalFormat) && |
| can_swizzle(srcFormat)) { |
| |
| GLubyte dstmap[4]; |
| |
| /* dstmap - how to swizzle from RGBA to dst format: |
| */ |
| dstmap[0] = 0; |
| dstmap[1] = 1; |
| dstmap[2] = 2; |
| dstmap[3] = ONE; /* ? */ |
| |
| _mesa_swizzle_ubyte_image(ctx, dims, |
| srcFormat, |
| srcType, |
| baseInternalFormat, |
| dstmap, 3, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcAddr, |
| srcPacking); |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_argb4444(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_ARGB4444 || |
| dstFormat == MESA_FORMAT_ARGB4444_REV); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 2); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| _mesa_texstore_rgba5551(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_RGBA5551); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 2); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| _mesa_texstore_argb1555(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_ARGB1555 || |
| dstFormat == MESA_FORMAT_ARGB1555_REV); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 2); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_argb2101010(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_ARGB2101010); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| if (baseInternalFormat == GL_RGBA) { |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *dstUI = (GLuint *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| GLushort a,r,g,b; |
| |
| UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]); |
| UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]); |
| UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]); |
| UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]); |
| dstUI[col] = PACK_COLOR_2101010_US(a, r, g, b); |
| src += 4; |
| } |
| dstRow += dstRowStride; |
| } |
| } else if (baseInternalFormat == GL_RGB) { |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *dstUI = (GLuint *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| GLushort r,g,b; |
| |
| UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]); |
| UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]); |
| UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]); |
| dstUI[col] = PACK_COLOR_2101010_US(0xffff, r, g, b); |
| src += 4; |
| } |
| dstRow += dstRowStride; |
| } |
| } else { |
| ASSERT(0); |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Do texstore for 2-channel, 4-bit/channel, unsigned normalized formats. |
| */ |
| static GLboolean |
| _mesa_texstore_unorm44(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_AL44); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 1); |
| |
| { |
| /* general path */ |
| const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking); |
| const GLubyte *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLubyte *dstUS = (GLubyte *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| /* src[0] is luminance, src[1] is alpha */ |
| dstUS[col] = PACK_COLOR_44( src[1], |
| src[0] ); |
| src += 2; |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Do texstore for 2-channel, 8-bit/channel, unsigned normalized formats. |
| */ |
| static GLboolean |
| _mesa_texstore_unorm88(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_AL88 || |
| dstFormat == MESA_FORMAT_AL88_REV || |
| dstFormat == MESA_FORMAT_GR88 || |
| dstFormat == MESA_FORMAT_RG88); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 2); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| ((dstFormat == MESA_FORMAT_AL88 && |
| baseInternalFormat == GL_LUMINANCE_ALPHA && |
| srcFormat == GL_LUMINANCE_ALPHA) || |
| (dstFormat == MESA_FORMAT_GR88 && |
| baseInternalFormat == srcFormat)) && |
| srcType == GL_UNSIGNED_BYTE && |
| littleEndian) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else if (!ctx->_ImageTransferState && |
| littleEndian && |
| srcType == GL_UNSIGNED_BYTE && |
| can_swizzle(baseInternalFormat) && |
| can_swizzle(srcFormat)) { |
| GLubyte dstmap[4]; |
| |
| /* dstmap - how to swizzle from RGBA to dst format: |
| */ |
| if (dstFormat == MESA_FORMAT_AL88 || dstFormat == MESA_FORMAT_AL88_REV) { |
| if ((littleEndian && dstFormat == MESA_FORMAT_AL88) || |
| (!littleEndian && dstFormat == MESA_FORMAT_AL88_REV)) { |
| dstmap[0] = 0; |
| dstmap[1] = 3; |
| } |
| else { |
| dstmap[0] = 3; |
| dstmap[1] = 0; |
| } |
| } |
| else { |
| if ((littleEndian && dstFormat == MESA_FORMAT_GR88) || |
| (!littleEndian && dstFormat == MESA_FORMAT_RG88)) { |
| dstmap[0] = 0; |
| dstmap[1] = 1; |
| } |
| else { |
| dstmap[0] = 1; |
| dstmap[1] = 0; |
| } |
| } |
| dstmap[2] = ZERO; /* ? */ |
| dstmap[3] = ONE; /* ? */ |
| |
| _mesa_swizzle_ubyte_image(ctx, dims, |
| srcFormat, |
| srcType, |
| baseInternalFormat, |
| dstmap, 2, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcAddr, |
| srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking); |
| const GLubyte *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLushort *dstUS = (GLushort *) dstRow; |
| if (dstFormat == MESA_FORMAT_AL88 || |
| dstFormat == MESA_FORMAT_GR88) { |
| for (col = 0; col < srcWidth; col++) { |
| /* src[0] is luminance (or R), src[1] is alpha (or G) */ |
| dstUS[col] = PACK_COLOR_88( src[1], |
| src[0] ); |
| src += 2; |
| } |
| } |
| else { |
| for (col = 0; col < srcWidth; col++) { |
| /* src[0] is luminance (or R), src[1] is alpha (or G) */ |
| dstUS[col] = PACK_COLOR_88_REV( src[1], |
| src[0] ); |
| src += 2; |
| } |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Do texstore for 2-channel, 16-bit/channel, unsigned normalized formats. |
| */ |
| static GLboolean |
| _mesa_texstore_unorm1616(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_AL1616 || |
| dstFormat == MESA_FORMAT_AL1616_REV || |
| dstFormat == MESA_FORMAT_RG1616 || |
| dstFormat == MESA_FORMAT_RG1616_REV); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| ((dstFormat == MESA_FORMAT_AL1616 && |
| baseInternalFormat == GL_LUMINANCE_ALPHA && |
| srcFormat == GL_LUMINANCE_ALPHA) || |
| (dstFormat == MESA_FORMAT_RG1616 && |
| baseInternalFormat == srcFormat)) && |
| srcType == GL_UNSIGNED_SHORT && |
| littleEndian) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *dstUI = (GLuint *) dstRow; |
| if (dstFormat == MESA_FORMAT_AL1616 || |
| dstFormat == MESA_FORMAT_RG1616) { |
| for (col = 0; col < srcWidth; col++) { |
| GLushort l, a; |
| |
| UNCLAMPED_FLOAT_TO_USHORT(l, src[0]); |
| UNCLAMPED_FLOAT_TO_USHORT(a, src[1]); |
| dstUI[col] = PACK_COLOR_1616(a, l); |
| src += 2; |
| } |
| } |
| else { |
| for (col = 0; col < srcWidth; col++) { |
| GLushort l, a; |
| |
| UNCLAMPED_FLOAT_TO_USHORT(l, src[0]); |
| UNCLAMPED_FLOAT_TO_USHORT(a, src[1]); |
| dstUI[col] = PACK_COLOR_1616_REV(a, l); |
| src += 2; |
| } |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /* Texstore for R16, A16, L16, I16. */ |
| static GLboolean |
| _mesa_texstore_unorm16(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_R16 || |
| dstFormat == MESA_FORMAT_A16 || |
| dstFormat == MESA_FORMAT_L16 || |
| dstFormat == MESA_FORMAT_I16); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 2); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_UNSIGNED_SHORT && |
| littleEndian) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLushort *dstUS = (GLushort *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| GLushort r; |
| |
| UNCLAMPED_FLOAT_TO_USHORT(r, src[0]); |
| dstUS[col] = r; |
| src += 1; |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_rgba_16(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_RGBA_16); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 8); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == GL_RGBA && |
| srcFormat == GL_RGBA && |
| srcType == GL_UNSIGNED_SHORT) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLushort *dstUS = (GLushort *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| GLushort r, g, b, a; |
| |
| UNCLAMPED_FLOAT_TO_USHORT(r, src[0]); |
| UNCLAMPED_FLOAT_TO_USHORT(g, src[1]); |
| UNCLAMPED_FLOAT_TO_USHORT(b, src[2]); |
| UNCLAMPED_FLOAT_TO_USHORT(a, src[3]); |
| dstUS[col*4+0] = r; |
| dstUS[col*4+1] = g; |
| dstUS[col*4+2] = b; |
| dstUS[col*4+3] = a; |
| src += 4; |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGB_16 || |
| dstFormat == MESA_FORMAT_SIGNED_RGBA_16); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == GL_RGBA && |
| dstFormat == MESA_FORMAT_SIGNED_RGBA_16 && |
| srcFormat == GL_RGBA && |
| srcType == GL_SHORT) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| const GLuint comps = _mesa_get_format_bytes(dstFormat) / 2; |
| GLint img, row, col; |
| |
| if (!tempImage) |
| return GL_FALSE; |
| |
| /* Note: tempImage is always float[4] / RGBA. We convert to 1, 2, |
| * 3 or 4 components/pixel here. |
| */ |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLshort *dstRowS = (GLshort *) dstRow; |
| if (dstFormat == MESA_FORMAT_SIGNED_RGBA_16) { |
| for (col = 0; col < srcWidth; col++) { |
| GLuint c; |
| for (c = 0; c < comps; c++) { |
| GLshort p; |
| UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 4 + c]); |
| dstRowS[col * comps + c] = p; |
| } |
| } |
| dstRow += dstRowStride; |
| src += 4 * srcWidth; |
| } else { |
| for (col = 0; col < srcWidth; col++) { |
| GLuint c; |
| for (c = 0; c < comps; c++) { |
| GLshort p; |
| UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 3 + c]); |
| dstRowS[col * comps + c] = p; |
| } |
| } |
| dstRow += dstRowStride; |
| src += 3 * srcWidth; |
| } |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_rgb332(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_RGB332); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 1); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGB && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| return store_ubyte_texture(ctx, dims, baseInternalFormat, |
| dstFormat, dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8. |
| */ |
| static GLboolean |
| _mesa_texstore_unorm8(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_A8 || |
| dstFormat == MESA_FORMAT_L8 || |
| dstFormat == MESA_FORMAT_I8 || |
| dstFormat == MESA_FORMAT_R8); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 1); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_UNSIGNED_BYTE) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else if (!ctx->_ImageTransferState && |
| srcType == GL_UNSIGNED_BYTE && |
| can_swizzle(baseInternalFormat) && |
| can_swizzle(srcFormat)) { |
| GLubyte dstmap[4]; |
| |
| /* dstmap - how to swizzle from RGBA to dst format: |
| */ |
| if (dstFormat == MESA_FORMAT_A8) { |
| dstmap[0] = 3; |
| } |
| else { |
| dstmap[0] = 0; |
| } |
| dstmap[1] = ZERO; /* ? */ |
| dstmap[2] = ZERO; /* ? */ |
| dstmap[3] = ONE; /* ? */ |
| |
| _mesa_swizzle_ubyte_image(ctx, dims, |
| srcFormat, |
| srcType, |
| baseInternalFormat, |
| dstmap, 1, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcAddr, |
| srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking); |
| const GLubyte *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| for (col = 0; col < srcWidth; col++) { |
| dstRow[col] = src[col]; |
| } |
| dstRow += dstRowStride; |
| src += srcWidth; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| |
| /** |
| * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV. |
| */ |
| static GLboolean |
| _mesa_texstore_ycbcr(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| |
| (void) ctx; (void) dims; (void) baseInternalFormat; |
| |
| ASSERT((dstFormat == MESA_FORMAT_YCBCR) || |
| (dstFormat == MESA_FORMAT_YCBCR_REV)); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 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(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| 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_FORMAT_YCBCR_REV) ^ |
| !littleEndian) { |
| GLint img, row; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| _mesa_swap2((GLushort *) dstRow, srcWidth); |
| dstRow += dstRowStride; |
| } |
| } |
| } |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| _mesa_texstore_dudv8(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| const GLuint texelBytes = _mesa_get_format_bytes(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_DUDV8); |
| ASSERT(texelBytes == 2); |
| ASSERT(ctx->Extensions.ATI_envmap_bumpmap); |
| ASSERT((srcFormat == GL_DU8DV8_ATI) || |
| (srcFormat == GL_DUDV_ATI)); |
| ASSERT(baseInternalFormat == GL_DUDV_ATI); |
| |
| if (!srcPacking->SwapBytes && srcType == GL_BYTE && |
| littleEndian) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else if (srcType == GL_BYTE) { |
| GLubyte dstmap[4]; |
| |
| /* dstmap - how to swizzle from RGBA to dst format: |
| */ |
| if (littleEndian) { |
| dstmap[0] = 0; |
| dstmap[1] = 3; |
| } |
| else { |
| dstmap[0] = 3; |
| dstmap[1] = 0; |
| } |
| dstmap[2] = ZERO; /* ? */ |
| dstmap[3] = ONE; /* ? */ |
| |
| _mesa_swizzle_ubyte_image(ctx, dims, |
| GL_LUMINANCE_ALPHA, /* hack */ |
| GL_UNSIGNED_BYTE, /* hack */ |
| GL_LUMINANCE_ALPHA, /* hack */ |
| dstmap, 2, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcAddr, |
| srcPacking); |
| } |
| else { |
| /* general path - note this is defined for 2d textures only */ |
| const GLint components = _mesa_components_in_format(baseInternalFormat); |
| const GLint srcStride = _mesa_image_row_stride(srcPacking, srcWidth, |
| srcFormat, srcType); |
| GLbyte *tempImage, *dst, *src; |
| GLint row; |
| |
| tempImage = (GLbyte *) malloc(srcWidth * srcHeight * srcDepth |
| * components * sizeof(GLbyte)); |
| if (!tempImage) |
| return GL_FALSE; |
| |
| src = (GLbyte *) _mesa_image_address(dims, srcPacking, srcAddr, |
| srcWidth, srcHeight, |
| srcFormat, srcType, |
| 0, 0, 0); |
| |
| dst = tempImage; |
| for (row = 0; row < srcHeight; row++) { |
| _mesa_unpack_dudv_span_byte(ctx, srcWidth, baseInternalFormat, |
| dst, srcFormat, srcType, src, |
| srcPacking, 0); |
| dst += srcWidth * components; |
| src += srcStride; |
| } |
| |
| src = tempImage; |
| dst = (GLbyte *) dstSlices[0]; |
| for (row = 0; row < srcHeight; row++) { |
| memcpy(dst, src, srcWidth * texelBytes); |
| dst += dstRowStride; |
| src += srcWidth * texelBytes; |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store a texture in a signed normalized 8-bit format. |
| */ |
| static GLboolean |
| _mesa_texstore_snorm8(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_SIGNED_A8 || |
| dstFormat == MESA_FORMAT_SIGNED_L8 || |
| dstFormat == MESA_FORMAT_SIGNED_I8 || |
| dstFormat == MESA_FORMAT_SIGNED_R8); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 1); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_BYTE) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLbyte *dstRow = (GLbyte *) dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| for (col = 0; col < srcWidth; col++) { |
| dstRow[col] = FLOAT_TO_BYTE_TEX(src[col]); |
| } |
| dstRow += dstRowStride; |
| src += srcWidth; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store a texture in a signed normalized two-channel 16-bit format. |
| */ |
| static GLboolean |
| _mesa_texstore_snorm88(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL88 || |
| dstFormat == MESA_FORMAT_SIGNED_RG88_REV); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 2); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_BYTE && |
| littleEndian) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLbyte *dstRow = (GLbyte *) dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLbyte *dst = dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| dst[0] = FLOAT_TO_BYTE_TEX(src[0]); |
| dst[1] = FLOAT_TO_BYTE_TEX(src[1]); |
| src += 2; |
| dst += 2; |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| /* Texstore for signed R16, A16, L16, I16. */ |
| static GLboolean |
| _mesa_texstore_snorm16(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_SIGNED_R16 || |
| dstFormat == MESA_FORMAT_SIGNED_A16 || |
| dstFormat == MESA_FORMAT_SIGNED_L16 || |
| dstFormat == MESA_FORMAT_SIGNED_I16); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 2); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_SHORT && |
| littleEndian) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLshort *dstUS = (GLshort *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| GLushort r; |
| |
| UNCLAMPED_FLOAT_TO_SHORT(r, src[0]); |
| dstUS[col] = r; |
| src += 1; |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| /** |
| * Do texstore for 2-channel, 16-bit/channel, signed normalized formats. |
| */ |
| static GLboolean |
| _mesa_texstore_snorm1616(TEXSTORE_PARAMS) |
| { |
| const GLboolean littleEndian = _mesa_little_endian(); |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL1616 || |
| dstFormat == MESA_FORMAT_SIGNED_GR1616); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_SHORT && |
| littleEndian) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLshort *dst = (GLshort *) dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| GLushort l, a; |
| |
| UNCLAMPED_FLOAT_TO_SHORT(l, src[0]); |
| UNCLAMPED_FLOAT_TO_SHORT(a, src[1]); |
| dst[0] = l; |
| dst[1] = a; |
| src += 2; |
| dst += 2; |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| /** |
| * Store a texture in MESA_FORMAT_SIGNED_RGBX8888. |
| */ |
| static GLboolean |
| _mesa_texstore_signed_rgbx8888(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGBX8888); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *srcRow = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLbyte *dstRow = (GLbyte *) dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLbyte *dst = dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]); |
| dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]); |
| dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]); |
| dst[0] = 127; |
| srcRow += 3; |
| dst += 4; |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| |
| /** |
| * Store a texture in MESA_FORMAT_SIGNED_RGBA8888 or |
| * MESA_FORMAT_SIGNED_RGBA8888_REV |
| */ |
| static GLboolean |
| _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGBA8888 || |
| dstFormat == MESA_FORMAT_SIGNED_RGBA8888_REV); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| if (!ctx->_ImageTransferState && |
| baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *srcRow = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLbyte *dstRow = (GLbyte *) dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLbyte *dst = dstRow; |
| if (dstFormat == MESA_FORMAT_SIGNED_RGBA8888) { |
| for (col = 0; col < srcWidth; col++) { |
| dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]); |
| dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]); |
| dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]); |
| dst[0] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]); |
| srcRow += 4; |
| dst += 4; |
| } |
| } |
| else { |
| for (col = 0; col < srcWidth; col++) { |
| dst[0] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]); |
| dst[1] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]); |
| dst[2] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]); |
| dst[3] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]); |
| srcRow += 4; |
| dst += 4; |
| } |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store a combined depth/stencil texture image. |
| */ |
| static GLboolean |
| _mesa_texstore_z24_s8(TEXSTORE_PARAMS) |
| { |
| const GLuint depthScale = 0xffffff; |
| const GLint srcRowStride |
| = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); |
| GLint img, row; |
| |
| ASSERT(dstFormat == MESA_FORMAT_Z24_S8); |
| ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || |
| srcFormat == GL_DEPTH_COMPONENT || |
| srcFormat == GL_STENCIL_INDEX); |
| ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT); |
| |
| if (srcFormat == GL_DEPTH_STENCIL && ctx->Pixel.DepthScale == 1.0f && |
| ctx->Pixel.DepthBias == 0.0f && |
| !srcPacking->SwapBytes) { |
| /* simple path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else if (srcFormat == GL_DEPTH_COMPONENT || |
| srcFormat == GL_STENCIL_INDEX) { |
| GLuint *depth = (GLuint *) malloc(srcWidth * sizeof(GLuint)); |
| GLubyte *stencil = (GLubyte *) malloc(srcWidth * sizeof(GLubyte)); |
| |
| if (!depth || !stencil) { |
| free(depth); |
| free(stencil); |
| return GL_FALSE; |
| } |
| |
| /* In case we only upload depth we need to preserve the stencil */ |
| for (img = 0; img < srcDepth; img++) { |
| GLuint *dstRow = (GLuint *) dstSlices[img]; |
| const GLubyte *src |
| = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, |
| srcWidth, srcHeight, |
| srcFormat, srcType, |
| img, 0, 0); |
| for (row = 0; row < srcHeight; row++) { |
| GLint i; |
| GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE; |
| |
| if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */ |
| keepstencil = GL_TRUE; |
| } |
| else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */ |
| keepdepth = GL_TRUE; |
| } |
| |
| if (keepdepth == GL_FALSE) |
| /* the 24 depth bits will be in the low position: */ |
| _mesa_unpack_depth_span(ctx, srcWidth, |
| GL_UNSIGNED_INT, /* dst type */ |
| keepstencil ? depth : dstRow, /* dst addr */ |
| depthScale, |
| srcType, src, srcPacking); |
| |
| if (keepstencil == GL_FALSE) |
| /* get the 8-bit stencil values */ |
| _mesa_unpack_stencil_span(ctx, srcWidth, |
| GL_UNSIGNED_BYTE, /* dst type */ |
| stencil, /* dst addr */ |
| srcType, src, srcPacking, |
| ctx->_ImageTransferState); |
| |
| for (i = 0; i < srcWidth; i++) { |
| if (keepstencil) |
| dstRow[i] = depth[i] << 8 | (dstRow[i] & 0x000000FF); |
| else |
| dstRow[i] = (dstRow[i] & 0xFFFFFF00) | (stencil[i] & 0xFF); |
| } |
| |
| src += srcRowStride; |
| dstRow += dstRowStride / sizeof(GLuint); |
| } |
| } |
| |
| free(depth); |
| free(stencil); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store a combined depth/stencil texture image. |
| */ |
| static GLboolean |
| _mesa_texstore_s8_z24(TEXSTORE_PARAMS) |
| { |
| const GLuint depthScale = 0xffffff; |
| const GLint srcRowStride |
| = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); |
| GLint img, row; |
| GLuint *depth; |
| GLubyte *stencil; |
| |
| ASSERT(dstFormat == MESA_FORMAT_S8_Z24); |
| ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || |
| srcFormat == GL_DEPTH_COMPONENT || |
| srcFormat == GL_STENCIL_INDEX); |
| ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || |
| srcType == GL_UNSIGNED_INT_24_8_EXT); |
| |
| depth = (GLuint *) malloc(srcWidth * sizeof(GLuint)); |
| stencil = (GLubyte *) malloc(srcWidth * sizeof(GLubyte)); |
| |
| if (!depth || !stencil) { |
| free(depth); |
| free(stencil); |
| return GL_FALSE; |
| } |
| |
| for (img = 0; img < srcDepth; img++) { |
| GLuint *dstRow = (GLuint *) dstSlices[img]; |
| const GLubyte *src |
| = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, |
| srcWidth, srcHeight, |
| srcFormat, srcType, |
| img, 0, 0); |
| for (row = 0; row < srcHeight; row++) { |
| GLint i; |
| GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE; |
| |
| if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */ |
| keepstencil = GL_TRUE; |
| } |
| else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */ |
| keepdepth = GL_TRUE; |
| } |
| |
| if (keepdepth == GL_FALSE) |
| /* the 24 depth bits will be in the low position: */ |
| _mesa_unpack_depth_span(ctx, srcWidth, |
| GL_UNSIGNED_INT, /* dst type */ |
| keepstencil ? depth : dstRow, /* dst addr */ |
| depthScale, |
| srcType, src, srcPacking); |
| |
| if (keepstencil == GL_FALSE) |
| /* get the 8-bit stencil values */ |
| _mesa_unpack_stencil_span(ctx, srcWidth, |
| GL_UNSIGNED_BYTE, /* dst type */ |
| stencil, /* dst addr */ |
| srcType, src, srcPacking, |
| ctx->_ImageTransferState); |
| |
| /* merge stencil values into depth values */ |
| for (i = 0; i < srcWidth; i++) { |
| if (keepstencil) |
| dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000); |
| else |
| dstRow[i] = (dstRow[i] & 0xFFFFFF) | (stencil[i] << 24); |
| |
| } |
| src += srcRowStride; |
| dstRow += dstRowStride / sizeof(GLuint); |
| } |
| } |
| |
| free(depth); |
| free(stencil); |
| |
| return GL_TRUE; |
| } |
| |
| |
| /** |
| * Store simple 8-bit/value stencil texture data. |
| */ |
| static GLboolean |
| _mesa_texstore_s8(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_S8); |
| ASSERT(srcFormat == GL_STENCIL_INDEX); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_UNSIGNED_BYTE) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| const GLint srcRowStride |
| = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); |
| GLint img, row; |
| GLubyte *stencil = (GLubyte *) malloc(srcWidth * sizeof(GLubyte)); |
| |
| if (!stencil) |
| return GL_FALSE; |
| |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| const GLubyte *src |
| = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, |
| srcWidth, srcHeight, |
| srcFormat, srcType, |
| img, 0, 0); |
| for (row = 0; row < srcHeight; row++) { |
| GLint i; |
| |
| /* get the 8-bit stencil values */ |
| _mesa_unpack_stencil_span(ctx, srcWidth, |
| GL_UNSIGNED_BYTE, /* dst type */ |
| stencil, /* dst addr */ |
| srcType, src, srcPacking, |
| ctx->_ImageTransferState); |
| /* merge stencil values into depth values */ |
| for (i = 0; i < srcWidth; i++) |
| dstRow[i] = stencil[i]; |
| |
| src += srcRowStride; |
| dstRow += dstRowStride / sizeof(GLubyte); |
| } |
| } |
| |
| free(stencil); |
| } |
| |
| 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 |
| */ |
| static GLboolean |
| _mesa_texstore_rgba_float32(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| const GLint components = _mesa_components_in_format(baseFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_RGBA_FLOAT32 || |
| dstFormat == MESA_FORMAT_RGB_FLOAT32 || |
| dstFormat == MESA_FORMAT_ALPHA_FLOAT32 || |
| dstFormat == MESA_FORMAT_LUMINANCE_FLOAT32 || |
| dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32 || |
| dstFormat == MESA_FORMAT_INTENSITY_FLOAT32 || |
| dstFormat == MESA_FORMAT_R_FLOAT32 || |
| dstFormat == MESA_FORMAT_RG_FLOAT32); |
| ASSERT(baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB || |
| baseInternalFormat == GL_ALPHA || |
| baseInternalFormat == GL_LUMINANCE || |
| baseInternalFormat == GL_LUMINANCE_ALPHA || |
| baseInternalFormat == GL_INTENSITY || |
| baseInternalFormat == GL_RED || |
| baseInternalFormat == GL_RG); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLfloat)); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| baseInternalFormat == baseFormat && |
| srcType == GL_FLOAT) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *srcRow = tempImage; |
| GLint bytesPerRow; |
| GLint img, row; |
| if (!tempImage) |
| return GL_FALSE; |
| bytesPerRow = srcWidth * components * sizeof(GLfloat); |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| memcpy(dstRow, srcRow, bytesPerRow); |
| dstRow += dstRowStride; |
| srcRow += srcWidth * components; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| |
| /** |
| * As above, but store 16-bit floats. |
| */ |
| static GLboolean |
| _mesa_texstore_rgba_float16(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| const GLint components = _mesa_components_in_format(baseFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_RGBA_FLOAT16 || |
| dstFormat == MESA_FORMAT_RGB_FLOAT16 || |
| dstFormat == MESA_FORMAT_ALPHA_FLOAT16 || |
| dstFormat == MESA_FORMAT_LUMINANCE_FLOAT16 || |
| dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16 || |
| dstFormat == MESA_FORMAT_INTENSITY_FLOAT16 || |
| dstFormat == MESA_FORMAT_R_FLOAT16 || |
| dstFormat == MESA_FORMAT_RG_FLOAT16); |
| ASSERT(baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB || |
| baseInternalFormat == GL_ALPHA || |
| baseInternalFormat == GL_LUMINANCE || |
| baseInternalFormat == GL_LUMINANCE_ALPHA || |
| baseInternalFormat == GL_INTENSITY || |
| baseInternalFormat == GL_RED || |
| baseInternalFormat == GL_RG); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLhalfARB)); |
| |
| if (!ctx->_ImageTransferState && |
| !srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| baseInternalFormat == baseFormat && |
| srcType == GL_HALF_FLOAT_ARB) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *src = tempImage; |
| GLint img, row; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| 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; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /* non-normalized, signed int8 */ |
| static GLboolean |
| _mesa_texstore_rgba_int8(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| const GLint components = _mesa_components_in_format(baseFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_R_INT8 || |
| dstFormat == MESA_FORMAT_RG_INT8 || |
| dstFormat == MESA_FORMAT_RGB_INT8 || |
| dstFormat == MESA_FORMAT_RGBA_INT8 || |
| dstFormat == MESA_FORMAT_ALPHA_INT8 || |
| dstFormat == MESA_FORMAT_INTENSITY_INT8 || |
| dstFormat == MESA_FORMAT_LUMINANCE_INT8 || |
| dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT8); |
| ASSERT(baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB || |
| baseInternalFormat == GL_RG || |
| baseInternalFormat == GL_RED || |
| baseInternalFormat == GL_ALPHA || |
| baseInternalFormat == GL_LUMINANCE || |
| baseInternalFormat == GL_LUMINANCE_ALPHA || |
| baseInternalFormat == GL_INTENSITY); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLbyte)); |
| |
| /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply |
| * to integer formats. |
| */ |
| if (!srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_BYTE) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLuint *tempImage = make_temp_uint_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, |
| srcAddr, |
| srcPacking); |
| const GLuint *src = tempImage; |
| GLint img, row; |
| GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLbyte *dstTexel = (GLbyte *) dstRow; |
| GLint i; |
| if (is_unsigned) { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLbyte) MIN2(src[i], 0x7f); |
| } |
| } else { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLbyte) CLAMP((GLint) src[i], -0x80, 0x7f); |
| } |
| } |
| dstRow += dstRowStride; |
| src += srcWidth * components; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /* non-normalized, signed int16 */ |
| static GLboolean |
| _mesa_texstore_rgba_int16(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| const GLint components = _mesa_components_in_format(baseFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_R_INT16 || |
| dstFormat == MESA_FORMAT_RG_INT16 || |
| dstFormat == MESA_FORMAT_RGB_INT16 || |
| dstFormat == MESA_FORMAT_RGBA_INT16 || |
| dstFormat == MESA_FORMAT_ALPHA_INT16 || |
| dstFormat == MESA_FORMAT_LUMINANCE_INT16 || |
| dstFormat == MESA_FORMAT_INTENSITY_INT16 || |
| dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT16); |
| ASSERT(baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB || |
| baseInternalFormat == GL_RG || |
| baseInternalFormat == GL_RED || |
| baseInternalFormat == GL_ALPHA || |
| baseInternalFormat == GL_LUMINANCE || |
| baseInternalFormat == GL_LUMINANCE_ALPHA || |
| baseInternalFormat == GL_INTENSITY); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLshort)); |
| |
| /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply |
| * to integer formats. |
| */ |
| if (!srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_SHORT) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLuint *tempImage = make_temp_uint_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, |
| srcAddr, |
| srcPacking); |
| const GLuint *src = tempImage; |
| GLint img, row; |
| GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLshort *dstTexel = (GLshort *) dstRow; |
| GLint i; |
| if (is_unsigned) { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLshort) MIN2(src[i], 0x7fff); |
| } |
| } else { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLshort)CLAMP((GLint) src[i], -0x8000, 0x7fff); |
| } |
| } |
| dstRow += dstRowStride; |
| src += srcWidth * components; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /* non-normalized, signed int32 */ |
| static GLboolean |
| _mesa_texstore_rgba_int32(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| const GLint components = _mesa_components_in_format(baseFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_R_INT32 || |
| dstFormat == MESA_FORMAT_RG_INT32 || |
| dstFormat == MESA_FORMAT_RGB_INT32 || |
| dstFormat == MESA_FORMAT_RGBA_INT32 || |
| dstFormat == MESA_FORMAT_ALPHA_INT32 || |
| dstFormat == MESA_FORMAT_INTENSITY_INT32 || |
| dstFormat == MESA_FORMAT_LUMINANCE_INT32 || |
| dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT32); |
| ASSERT(baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB || |
| baseInternalFormat == GL_RG || |
| baseInternalFormat == GL_RED || |
| baseInternalFormat == GL_ALPHA || |
| baseInternalFormat == GL_LUMINANCE || |
| baseInternalFormat == GL_LUMINANCE_ALPHA || |
| baseInternalFormat == GL_INTENSITY); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLint)); |
| |
| /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply |
| * to integer formats. |
| */ |
| if (!srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_INT) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLuint *tempImage = make_temp_uint_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, |
| srcAddr, |
| srcPacking); |
| const GLuint *src = tempImage; |
| GLint img, row; |
| GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLint *dstTexel = (GLint *) dstRow; |
| GLint i; |
| if (is_unsigned) { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLint) MIN2(src[i], 0x7fffffff); |
| } |
| } else { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLint) src[i]; |
| } |
| } |
| dstRow += dstRowStride; |
| src += srcWidth * components; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /* non-normalized, unsigned int8 */ |
| static GLboolean |
| _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| const GLint components = _mesa_components_in_format(baseFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_R_UINT8 || |
| dstFormat == MESA_FORMAT_RG_UINT8 || |
| dstFormat == MESA_FORMAT_RGB_UINT8 || |
| dstFormat == MESA_FORMAT_RGBA_UINT8 || |
| dstFormat == MESA_FORMAT_ALPHA_UINT8 || |
| dstFormat == MESA_FORMAT_INTENSITY_UINT8 || |
| dstFormat == MESA_FORMAT_LUMINANCE_UINT8 || |
| dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT8); |
| ASSERT(baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB || |
| baseInternalFormat == GL_RG || |
| baseInternalFormat == GL_RED || |
| baseInternalFormat == GL_ALPHA || |
| baseInternalFormat == GL_LUMINANCE || |
| baseInternalFormat == GL_LUMINANCE_ALPHA || |
| baseInternalFormat == GL_INTENSITY); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLubyte)); |
| |
| /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply |
| * to integer formats. |
| */ |
| if (!srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_UNSIGNED_BYTE) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLuint *tempImage = |
| make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| const GLuint *src = tempImage; |
| GLint img, row; |
| GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLubyte *dstTexel = (GLubyte *) dstRow; |
| GLint i; |
| if (is_unsigned) { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLubyte) MIN2(src[i], 0xff); |
| } |
| } else { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLubyte) CLAMP((GLint) src[i], 0, 0xff); |
| } |
| } |
| dstRow += dstRowStride; |
| src += srcWidth * components; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /* non-normalized, unsigned int16 */ |
| static GLboolean |
| _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| const GLint components = _mesa_components_in_format(baseFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_R_UINT16 || |
| dstFormat == MESA_FORMAT_RG_UINT16 || |
| dstFormat == MESA_FORMAT_RGB_UINT16 || |
| dstFormat == MESA_FORMAT_RGBA_UINT16 || |
| dstFormat == MESA_FORMAT_ALPHA_UINT16 || |
| dstFormat == MESA_FORMAT_INTENSITY_UINT16 || |
| dstFormat == MESA_FORMAT_LUMINANCE_UINT16 || |
| dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT16); |
| ASSERT(baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB || |
| baseInternalFormat == GL_RG || |
| baseInternalFormat == GL_RED || |
| baseInternalFormat == GL_ALPHA || |
| baseInternalFormat == GL_LUMINANCE || |
| baseInternalFormat == GL_LUMINANCE_ALPHA || |
| baseInternalFormat == GL_INTENSITY); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLushort)); |
| |
| /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply |
| * to integer formats. |
| */ |
| if (!srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_UNSIGNED_SHORT) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLuint *tempImage = |
| make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| const GLuint *src = tempImage; |
| GLint img, row; |
| GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLushort *dstTexel = (GLushort *) dstRow; |
| GLint i; |
| if (is_unsigned) { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLushort) MIN2(src[i], 0xffff); |
| } |
| } else { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = (GLushort) CLAMP((GLint) src[i], 0, 0xffff); |
| } |
| } |
| dstRow += dstRowStride; |
| src += srcWidth * components; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| /* non-normalized, unsigned int32 */ |
| static GLboolean |
| _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| const GLint components = _mesa_components_in_format(baseFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_R_UINT32 || |
| dstFormat == MESA_FORMAT_RG_UINT32 || |
| dstFormat == MESA_FORMAT_RGB_UINT32 || |
| dstFormat == MESA_FORMAT_RGBA_UINT32 || |
| dstFormat == MESA_FORMAT_ALPHA_UINT32 || |
| dstFormat == MESA_FORMAT_INTENSITY_UINT32 || |
| dstFormat == MESA_FORMAT_LUMINANCE_UINT32 || |
| dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT32); |
| ASSERT(baseInternalFormat == GL_RGBA || |
| baseInternalFormat == GL_RGB || |
| baseInternalFormat == GL_RG || |
| baseInternalFormat == GL_RED || |
| baseInternalFormat == GL_ALPHA || |
| baseInternalFormat == GL_LUMINANCE || |
| baseInternalFormat == GL_LUMINANCE_ALPHA || |
| baseInternalFormat == GL_INTENSITY); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLuint)); |
| |
| /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply |
| * to integer formats. |
| */ |
| if (!srcPacking->SwapBytes && |
| baseInternalFormat == srcFormat && |
| srcType == GL_UNSIGNED_INT) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLuint *tempImage = |
| make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| const GLuint *src = tempImage; |
| GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); |
| GLint img, row; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *dstTexel = (GLuint *) dstRow; |
| GLint i; |
| if (is_unsigned) { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = src[i]; |
| } |
| } else { |
| for (i = 0; i < srcWidth * components; i++) { |
| dstTexel[i] = MAX2((GLint) src[i], 0); |
| } |
| } |
| dstRow += dstRowStride; |
| src += srcWidth * components; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| |
| |
| #if FEATURE_EXT_texture_sRGB |
| static GLboolean |
| _mesa_texstore_srgb8(TEXSTORE_PARAMS) |
| { |
| gl_format newDstFormat; |
| GLboolean k; |
| |
| ASSERT(dstFormat == MESA_FORMAT_SRGB8); |
| |
| /* reuse normal rgb texstore code */ |
| newDstFormat = MESA_FORMAT_RGB888; |
| |
| k = _mesa_texstore_rgb888(ctx, dims, baseInternalFormat, |
| newDstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, |
| srcAddr, srcPacking); |
| return k; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_srgba8(TEXSTORE_PARAMS) |
| { |
| gl_format newDstFormat; |
| GLboolean k; |
| |
| ASSERT(dstFormat == MESA_FORMAT_SRGBA8); |
| |
| /* reuse normal rgba texstore code */ |
| newDstFormat = MESA_FORMAT_RGBA8888; |
| k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat, |
| newDstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, |
| srcAddr, srcPacking); |
| return k; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_sargb8(TEXSTORE_PARAMS) |
| { |
| gl_format newDstFormat; |
| GLboolean k; |
| |
| ASSERT(dstFormat == MESA_FORMAT_SARGB8); |
| |
| /* reuse normal rgba texstore code */ |
| newDstFormat = MESA_FORMAT_ARGB8888; |
| |
| k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat, |
| newDstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, |
| srcAddr, srcPacking); |
| return k; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_sl8(TEXSTORE_PARAMS) |
| { |
| gl_format newDstFormat; |
| GLboolean k; |
| |
| ASSERT(dstFormat == MESA_FORMAT_SL8); |
| |
| newDstFormat = MESA_FORMAT_L8; |
| |
| /* _mesa_textore_a8 handles luminance8 too */ |
| k = _mesa_texstore_unorm8(ctx, dims, baseInternalFormat, |
| newDstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, |
| srcAddr, srcPacking); |
| return k; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_sla8(TEXSTORE_PARAMS) |
| { |
| gl_format newDstFormat; |
| GLboolean k; |
| |
| ASSERT(dstFormat == MESA_FORMAT_SLA8); |
| |
| /* reuse normal luminance/alpha texstore code */ |
| newDstFormat = MESA_FORMAT_AL88; |
| |
| k = _mesa_texstore_unorm88(ctx, dims, baseInternalFormat, |
| newDstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, |
| srcAddr, srcPacking); |
| return k; |
| } |
| |
| #else |
| |
| /* these are used only in texstore_funcs[] below */ |
| #define _mesa_texstore_srgb8 NULL |
| #define _mesa_texstore_srgba8 NULL |
| #define _mesa_texstore_sargb8 NULL |
| #define _mesa_texstore_sl8 NULL |
| #define _mesa_texstore_sla8 NULL |
| |
| #endif /* FEATURE_EXT_texture_sRGB */ |
| |
| static GLboolean |
| _mesa_texstore_rgb9_e5(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_RGB9_E5_FLOAT); |
| ASSERT(baseInternalFormat == GL_RGB); |
| |
| if (!ctx->_ImageTransferState && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *srcRow = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *dstUI = (GLuint*)dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| dstUI[col] = float3_to_rgb9e5(&srcRow[col * 3]); |
| } |
| dstRow += dstRowStride; |
| srcRow += srcWidth * 3; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| _mesa_texstore_r11_g11_b10f(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_R11_G11_B10_FLOAT); |
| ASSERT(baseInternalFormat == GL_RGB); |
| |
| if (!ctx->_ImageTransferState && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, |
| srcPacking, |
| ctx->_ImageTransferState); |
| const GLfloat *srcRow = tempImage; |
| GLint img, row, col; |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *dstUI = (GLuint*)dstRow; |
| for (col = 0; col < srcWidth; col++) { |
| dstUI[col] = float3_to_r11g11b10f(&srcRow[col * 3]); |
| } |
| dstRow += dstRowStride; |
| srcRow += srcWidth * 3; |
| } |
| } |
| |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| |
| static GLboolean |
| _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS) |
| { |
| ASSERT(dstFormat == MESA_FORMAT_Z32_FLOAT_X24S8); |
| ASSERT(srcFormat == GL_DEPTH_STENCIL || |
| srcFormat == GL_DEPTH_COMPONENT || |
| srcFormat == GL_STENCIL_INDEX); |
| ASSERT(srcFormat != GL_DEPTH_STENCIL || |
| srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); |
| |
| if (srcFormat == GL_DEPTH_STENCIL && |
| ctx->Pixel.DepthScale == 1.0f && |
| ctx->Pixel.DepthBias == 0.0f && |
| !srcPacking->SwapBytes) { |
| /* simple path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else if (srcFormat == GL_DEPTH_COMPONENT || |
| srcFormat == GL_STENCIL_INDEX) { |
| GLint img, row; |
| const GLint srcRowStride |
| = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) |
| / sizeof(uint64_t); |
| |
| /* In case we only upload depth we need to preserve the stencil */ |
| for (img = 0; img < srcDepth; img++) { |
| uint64_t *dstRow = (uint64_t *) dstSlices[img]; |
| const uint64_t *src |
| = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr, |
| srcWidth, srcHeight, |
| srcFormat, srcType, |
| img, 0, 0); |
| for (row = 0; row < srcHeight; row++) { |
| /* The unpack functions with: |
| * dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV |
| * only write their own dword, so the other dword (stencil |
| * or depth) is preserved. */ |
| if (srcFormat != GL_STENCIL_INDEX) |
| _mesa_unpack_depth_span(ctx, srcWidth, |
| GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ |
| dstRow, /* dst addr */ |
| ~0U, srcType, src, srcPacking); |
| |
| if (srcFormat != GL_DEPTH_COMPONENT) |
| _mesa_unpack_stencil_span(ctx, srcWidth, |
| GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ |
| dstRow, /* dst addr */ |
| srcType, src, srcPacking, |
| ctx->_ImageTransferState); |
| |
| src += srcRowStride; |
| dstRow += dstRowStride / sizeof(uint64_t); |
| } |
| } |
| } |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| _mesa_texstore_argb2101010_uint(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_ARGB2101010_UINT); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| if (baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLuint *tempImage = make_temp_uint_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, |
| srcDepth, srcFormat, |
| srcType, srcAddr, |
| srcPacking); |
| const GLuint *src = tempImage; |
| GLint img, row, col; |
| GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *dstUI = (GLuint *) dstRow; |
| if (is_unsigned) { |
| for (col = 0; col < srcWidth; col++) { |
| GLushort a,r,g,b; |
| r = MIN2(src[RCOMP], 0x3ff); |
| g = MIN2(src[GCOMP], 0x3ff); |
| b = MIN2(src[BCOMP], 0x3ff); |
| a = MIN2(src[ACOMP], 0x003); |
| dstUI[col] = (a << 30) | (r << 20) | (g << 10) | (b); |
| src += 4; |
| } |
| } else { |
| for (col = 0; col < srcWidth; col++) { |
| GLushort a,r,g,b; |
| r = CLAMP((GLint) src[RCOMP], 0, 0x3ff); |
| g = CLAMP((GLint) src[GCOMP], 0, 0x3ff); |
| b = CLAMP((GLint) src[BCOMP], 0, 0x3ff); |
| a = CLAMP((GLint) src[ACOMP], 0, 0x003); |
| dstUI[col] = (a << 30) | (r << 20) | (g << 10) | (b); |
| src += 4; |
| } |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| _mesa_texstore_abgr2101010_uint(TEXSTORE_PARAMS) |
| { |
| const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); |
| |
| ASSERT(dstFormat == MESA_FORMAT_ABGR2101010_UINT); |
| ASSERT(_mesa_get_format_bytes(dstFormat) == 4); |
| |
| if (baseInternalFormat == GL_RGBA && |
| _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType, |
| srcPacking->SwapBytes)) { |
| /* simple memcpy path */ |
| memcpy_texture(ctx, dims, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, srcFormat, srcType, |
| srcAddr, srcPacking); |
| } |
| else { |
| /* general path */ |
| const GLuint *tempImage = make_temp_uint_image(ctx, dims, |
| baseInternalFormat, |
| baseFormat, |
| srcWidth, srcHeight, |
| srcDepth, srcFormat, |
| srcType, srcAddr, |
| srcPacking); |
| const GLuint *src = tempImage; |
| GLint img, row, col; |
| GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); |
| if (!tempImage) |
| return GL_FALSE; |
| for (img = 0; img < srcDepth; img++) { |
| GLubyte *dstRow = dstSlices[img]; |
| |
| for (row = 0; row < srcHeight; row++) { |
| GLuint *dstUI = (GLuint *) dstRow; |
| if (is_unsigned) { |
| for (col = 0; col < srcWidth; col++) { |
| GLushort a,r,g,b; |
| r = MIN2(src[RCOMP], 0x3ff); |
| g = MIN2(src[GCOMP], 0x3ff); |
| b = MIN2(src[BCOMP], 0x3ff); |
| a = MIN2(src[ACOMP], 0x003); |
| dstUI[col] = (a << 30) | (b << 20) | (g << 10) | (r); |
| src += 4; |
| } |
| } else { |
| for (col = 0; col < srcWidth; col++) { |
| GLushort a,r,g,b; |
| r = CLAMP((GLint) src[RCOMP], 0, 0x3ff); |
| g = CLAMP((GLint) src[GCOMP], 0, 0x3ff); |
| b = CLAMP((GLint) src[BCOMP], 0, 0x3ff); |
| a = CLAMP((GLint) src[ACOMP], 0, 0x003); |
| dstUI[col] = (a << 30) | (b << 20) | (g << 10) | (r); |
| src += 4; |
| } |
| } |
| dstRow += dstRowStride; |
| } |
| } |
| free((void *) tempImage); |
| } |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| _mesa_texstore_null(TEXSTORE_PARAMS) |
| { |
| (void) ctx; (void) dims; |
| (void) baseInternalFormat; |
| (void) dstFormat; |
| (void) dstRowStride; (void) dstSlices, |
| (void) srcWidth; (void) srcHeight; (void) srcDepth; |
| (void) srcFormat; (void) srcType; |
| (void) srcAddr; |
| (void) srcPacking; |
| |
| /* should never happen */ |
| _mesa_problem(NULL, "_mesa_texstore_null() is called"); |
| return GL_FALSE; |
| } |
| |
| |
| /** |
| * Return the StoreTexImageFunc pointer to store an image in the given format. |
| */ |
| static StoreTexImageFunc |
| _mesa_get_texstore_func(gl_format format) |
| { |
| static StoreTexImageFunc table[MESA_FORMAT_COUNT]; |
| static GLboolean initialized = GL_FALSE; |
| |
| if (!initialized) { |
| table[MESA_FORMAT_NONE] = _mesa_texstore_null; |
| |
| table[MESA_FORMAT_RGBA8888] = _mesa_texstore_rgba8888; |
| table[MESA_FORMAT_RGBA8888_REV] = _mesa_texstore_rgba8888; |
| table[MESA_FORMAT_ARGB8888] = _mesa_texstore_argb8888; |
| table[MESA_FORMAT_ARGB8888_REV] = _mesa_texstore_argb8888; |
| table[MESA_FORMAT_RGBX8888] = _mesa_texstore_rgba8888; |
| table[MESA_FORMAT_RGBX8888_REV] = _mesa_texstore_rgba8888; |
| table[MESA_FORMAT_XRGB8888] = _mesa_texstore_argb8888; |
| table[MESA_FORMAT_XRGB8888_REV] = _mesa_texstore_argb8888; |
| table[MESA_FORMAT_RGB888] = _mesa_texstore_rgb888; |
| table[MESA_FORMAT_BGR888] = _mesa_texstore_bgr888; |
| table[MESA_FORMAT_RGB565] = _mesa_texstore_rgb565; |
| table[MESA_FORMAT_RGB565_REV] = _mesa_texstore_rgb565; |
| table[MESA_FORMAT_ARGB4444] = _mesa_texstore_argb4444; |
| table[MESA_FORMAT_ARGB4444_REV] = _mesa_texstore_argb4444; |
| table[MESA_FORMAT_RGBA5551] = _mesa_texstore_rgba5551; |
| table[MESA_FORMAT_ARGB1555] = _mesa_texstore_argb1555; |
| table[MESA_FORMAT_ARGB1555_REV] = _mesa_texstore_argb1555; |
| table[MESA_FORMAT_AL44] = _mesa_texstore_unorm44; |
| table[MESA_FORMAT_AL88] = _mesa_texstore_unorm88; |
| table[MESA_FORMAT_AL88_REV] = _mesa_texstore_unorm88; |
| table[MESA_FORMAT_AL1616] = _mesa_texstore_unorm1616; |
| table[MESA_FORMAT_AL1616_REV] = _mesa_texstore_unorm1616; |
| table[MESA_FORMAT_RGB332] = _mesa_texstore_rgb332; |
| table[MESA_FORMAT_A8] = _mesa_texstore_unorm8; |
| table[MESA_FORMAT_A16] = _mesa_texstore_unorm16; |
| table[MESA_FORMAT_L8] = _mesa_texstore_unorm8; |
| table[MESA_FORMAT_L16] = _mesa_texstore_unorm16; |
| table[MESA_FORMAT_I8] = _mesa_texstore_unorm8; |
| table[MESA_FORMAT_I16] = _mesa_texstore_unorm16; |
| table[MESA_FORMAT_YCBCR] = _mesa_texstore_ycbcr; |
| table[MESA_FORMAT_YCBCR_REV] = _mesa_texstore_ycbcr; |
| table[MESA_FORMAT_R8] = _mesa_texstore_unorm8; |
| table[MESA_FORMAT_GR88] = _mesa_texstore_unorm88; |
| table[MESA_FORMAT_RG88] = _mesa_texstore_unorm88; |
| table[MESA_FORMAT_R16] = _mesa_texstore_unorm16; |
| table[MESA_FORMAT_RG1616] = _mesa_texstore_unorm1616; |
| table[MESA_FORMAT_RG1616_REV] = _mesa_texstore_unorm1616; |
| table[MESA_FORMAT_ARGB2101010] = _mesa_texstore_argb2101010; |
| table[MESA_FORMAT_Z24_S8] = _mesa_texstore_z24_s8; |
| table[MESA_FORMAT_S8_Z24] = _mesa_texstore_s8_z24; |
| table[MESA_FORMAT_Z16] = _mesa_texstore_z16; |
| table[MESA_FORMAT_X8_Z24] = _mesa_texstore_x8_z24; |
| table[MESA_FORMAT_Z24_X8] = _mesa_texstore_z24_x8; |
| table[MESA_FORMAT_Z32] = _mesa_texstore_z32; |
| table[MESA_FORMAT_S8] = _mesa_texstore_s8; |
| table[MESA_FORMAT_SRGB8] = _mesa_texstore_srgb8; |
| table[MESA_FORMAT_SRGBA8] = _mesa_texstore_srgba8; |
| table[MESA_FORMAT_SARGB8] = _mesa_texstore_sargb8; |
| table[MESA_FORMAT_SL8] = _mesa_texstore_sl8; |
| table[MESA_FORMAT_SLA8] = _mesa_texstore_sla8; |
| table[MESA_FORMAT_SRGB_DXT1] = _mesa_texstore_rgb_dxt1; |
| table[MESA_FORMAT_SRGBA_DXT1] = _mesa_texstore_rgba_dxt1; |
| table[MESA_FORMAT_SRGBA_DXT3] = _mesa_texstore_rgba_dxt3; |
| table[MESA_FORMAT_SRGBA_DXT5] = _mesa_texstore_rgba_dxt5; |
| table[MESA_FORMAT_RGB_FXT1] = _mesa_texstore_rgb_fxt1; |
| table[MESA_FORMAT_RGBA_FXT1] = _mesa_texstore_rgba_fxt1; |
| table[MESA_FORMAT_RGB_DXT1] = _mesa_texstore_rgb_dxt1; |
| table[MESA_FORMAT_RGBA_DXT1] = _mesa_texstore_rgba_dxt1; |
| table[MESA_FORMAT_RGBA_DXT3] = _mesa_texstore_rgba_dxt3; |
| table[MESA_FORMAT_RGBA_DXT5] = _mesa_texstore_rgba_dxt5; |
| table[MESA_FORMAT_RGBA_FLOAT32] = _mesa_texstore_rgba_float32; |
| table[MESA_FORMAT_RGBA_FLOAT16] = _mesa_texstore_rgba_float16; |
| table[MESA_FORMAT_RGB_FLOAT32] = _mesa_texstore_rgba_float32; |
| table[MESA_FORMAT_RGB_FLOAT16] = _mesa_texstore_rgba_float16; |
| table[MESA_FORMAT_ALPHA_FLOAT32] = _mesa_texstore_rgba_float32; |
| table[MESA_FORMAT_ALPHA_FLOAT16] = _mesa_texstore_rgba_float16; |
| table[MESA_FORMAT_LUMINANCE_FLOAT32] = _mesa_texstore_rgba_float32; |
| table[MESA_FORMAT_LUMINANCE_FLOAT16] = _mesa_texstore_rgba_float16; |
| table[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32] = _mesa_texstore_rgba_float32; |
| table[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16] = _mesa_texstore_rgba_float16; |
| table[MESA_FORMAT_INTENSITY_FLOAT32] = _mesa_texstore_rgba_float32; |
| table[MESA_FORMAT_INTENSITY_FLOAT16] = _mesa_texstore_rgba_float16; |
| table[MESA_FORMAT_R_FLOAT32] = _mesa_texstore_rgba_float32; |
| table[MESA_FORMAT_R_FLOAT16] = _mesa_texstore_rgba_float16; |
| table[MESA_FORMAT_RG_FLOAT32] = _mesa_texstore_rgba_float32; |
| table[MESA_FORMAT_RG_FLOAT16] = _mesa_texstore_rgba_float16; |
| table[MESA_FORMAT_DUDV8] = _mesa_texstore_dudv8; |
| table[MESA_FORMAT_SIGNED_R8] = _mesa_texstore_snorm8; |
| table[MESA_FORMAT_SIGNED_RG88_REV] = _mesa_texstore_snorm88; |
| table[MESA_FORMAT_SIGNED_RGBX8888] = _mesa_texstore_signed_rgbx8888; |
| table[MESA_FORMAT_SIGNED_RGBA8888] = _mesa_texstore_signed_rgba8888; |
| table[MESA_FORMAT_SIGNED_RGBA8888_REV] = _mesa_texstore_signed_rgba8888; |
| table[MESA_FORMAT_SIGNED_R16] = _mesa_texstore_snorm16; |
| table[MESA_FORMAT_SIGNED_GR1616] = _mesa_texstore_snorm1616; |
| table[MESA_FORMAT_SIGNED_RGB_16] = _mesa_texstore_signed_rgba_16; |
| table[MESA_FORMAT_SIGNED_RGBA_16] = _mesa_texstore_signed_rgba_16; |
| table[MESA_FORMAT_RGBA_16] = _mesa_texstore_rgba_16; |
| table[MESA_FORMAT_RED_RGTC1] = _mesa_texstore_red_rgtc1; |
| table[MESA_FORMAT_SIGNED_RED_RGTC1] = _mesa_texstore_signed_red_rgtc1; |
| table[MESA_FORMAT_RG_RGTC2] = _mesa_texstore_rg_rgtc2; |
| table[MESA_FORMAT_SIGNED_RG_RGTC2] = _mesa_texstore_signed_rg_rgtc2; |
| table[MESA_FORMAT_L_LATC1] = _mesa_texstore_red_rgtc1; |
| table[MESA_FORMAT_SIGNED_L_LATC1] = _mesa_texstore_signed_red_rgtc1; |
| table[MESA_FORMAT_LA_LATC2] = _mesa_texstore_rg_rgtc2; |
| table[MESA_FORMAT_SIGNED_LA_LATC2] = _mesa_texstore_signed_rg_rgtc2; |
| table[MESA_FORMAT_ETC1_RGB8] = _mesa_texstore_etc1_rgb8; |
| table[MESA_FORMAT_SIGNED_A8] = _mesa_texstore_snorm8; |
| table[MESA_FORMAT_SIGNED_L8] = _mesa_texstore_snorm8; |
| table[MESA_FORMAT_SIGNED_AL88] = _mesa_texstore_snorm88; |
| table[MESA_FORMAT_SIGNED_I8] = _mesa_texstore_snorm8; |
| table[MESA_FORMAT_SIGNED_A16] = _mesa_texstore_snorm16; |
| table[MESA_FORMAT_SIGNED_L16] = _mesa_texstore_snorm16; |
| table[MESA_FORMAT_SIGNED_AL1616] = _mesa_texstore_snorm1616; |
| table[MESA_FORMAT_SIGNED_I16] = _mesa_texstore_snorm16; |
| table[MESA_FORMAT_RGB9_E5_FLOAT] = _mesa_texstore_rgb9_e5; |
| table[MESA_FORMAT_R11_G11_B10_FLOAT] = _mesa_texstore_r11_g11_b10f; |
| table[MESA_FORMAT_Z32_FLOAT] = _mesa_texstore_z32; |
| table[MESA_FORMAT_Z32_FLOAT_X24S8] = _mesa_texstore_z32f_x24s8; |
| |
| table[MESA_FORMAT_ALPHA_UINT8] = _mesa_texstore_rgba_uint8; |
| table[MESA_FORMAT_ALPHA_UINT16] = _mesa_texstore_rgba_uint16; |
| table[MESA_FORMAT_ALPHA_UINT32] = _mesa_texstore_rgba_uint32; |
| table[MESA_FORMAT_ALPHA_INT8] = _mesa_texstore_rgba_int8; |
| table[MESA_FORMAT_ALPHA_INT16] = _mesa_texstore_rgba_int16; |
| table[MESA_FORMAT_ALPHA_INT32] = _mesa_texstore_rgba_int32; |
| |
| table[MESA_FORMAT_INTENSITY_UINT8] = _mesa_texstore_rgba_uint8; |
| table[MESA_FORMAT_INTENSITY_UINT16] = _mesa_texstore_rgba_uint16; |
| table[MESA_FORMAT_INTENSITY_UINT32] = _mesa_texstore_rgba_uint32; |
| table[MESA_FORMAT_INTENSITY_INT8] = _mesa_texstore_rgba_int8; |
| table[MESA_FORMAT_INTENSITY_INT16] = _mesa_texstore_rgba_int16; |
| table[MESA_FORMAT_INTENSITY_INT32] = _mesa_texstore_rgba_int32; |
| |
| table[MESA_FORMAT_LUMINANCE_UINT8] = _mesa_texstore_rgba_uint8; |
| table[MESA_FORMAT_LUMINANCE_UINT16] = _mesa_texstore_rgba_uint16; |
| table[MESA_FORMAT_LUMINANCE_UINT32] = _mesa_texstore_rgba_uint32; |
| table[MESA_FORMAT_LUMINANCE_INT8] = _mesa_texstore_rgba_int8; |
| table[MESA_FORMAT_LUMINANCE_INT16] = _mesa_texstore_rgba_int16; |
| table[MESA_FORMAT_LUMINANCE_INT32] = _mesa_texstore_rgba_int32; |
| |
| table[MESA_FORMAT_LUMINANCE_ALPHA_UINT8] = _mesa_texstore_rgba_uint8; |
| table[MESA_FORMAT_LUMINANCE_ALPHA_UINT16] = _mesa_texstore_rgba_uint16; |
| table[MESA_FORMAT_LUMINANCE_ALPHA_UINT32] = _mesa_texstore_rgba_uint32; |
| table[MESA_FORMAT_LUMINANCE_ALPHA_INT8] = _mesa_texstore_rgba_int8; |
| table[MESA_FORMAT_LUMINANCE_ALPHA_INT16] = _mesa_texstore_rgba_int16; |
| table[MESA_FORMAT_LUMINANCE_ALPHA_INT32] = _mesa_texstore_rgba_int32; |
| |
| table[MESA_FORMAT_R_INT8] = _mesa_texstore_rgba_int8; |
| table[MESA_FORMAT_RG_INT8] = _mesa_texstore_rgba_int8; |
| table[MESA_FORMAT_RGB_INT8] = _mesa_texstore_rgba_int8; |
| table[MESA_FORMAT_RGBA_INT8] = _mesa_texstore_rgba_int8; |
| table[MESA_FORMAT_R_INT16] = _mesa_texstore_rgba_int16; |
| table[MESA_FORMAT_RG_INT16] = _mesa_texstore_rgba_int16; |
| table[MESA_FORMAT_RGB_INT16] = _mesa_texstore_rgba_int16; |
| table[MESA_FORMAT_RGBA_INT16] = _mesa_texstore_rgba_int16; |
| table[MESA_FORMAT_R_INT32] = _mesa_texstore_rgba_int32; |
| table[MESA_FORMAT_RG_INT32] = _mesa_texstore_rgba_int32; |
| table[MESA_FORMAT_RGB_INT32] = _mesa_texstore_rgba_int32; |
| table[MESA_FORMAT_RGBA_INT32] = _mesa_texstore_rgba_int32; |
| |
| table[MESA_FORMAT_R_UINT8] = _mesa_texstore_rgba_uint8; |
| table[MESA_FORMAT_RG_UINT8] = _mesa_texstore_rgba_uint8; |
| table[MESA_FORMAT_RGB_UINT8] = _mesa_texstore_rgba_uint8; |
| table[MESA_FORMAT_RGBA_UINT8] = _mesa_texstore_rgba_uint8; |
| table[MESA_FORMAT_R_UINT16] = _mesa_texstore_rgba_uint16; |
| table[MESA_FORMAT_RG_UINT16] = _mesa_texstore_rgba_uint16; |
| table[MESA_FORMAT_RGB_UINT16] = _mesa_texstore_rgba_uint16; |
| table[MESA_FORMAT_RGBA_UINT16] = _mesa_texstore_rgba_uint16; |
| table[MESA_FORMAT_R_UINT32] = _mesa_texstore_rgba_uint32; |
| table[MESA_FORMAT_RG_UINT32] = _mesa_texstore_rgba_uint32; |
| table[MESA_FORMAT_RGB_UINT32] = _mesa_texstore_rgba_uint32; |
| table[MESA_FORMAT_RGBA_UINT32] = _mesa_texstore_rgba_uint32; |
| |
| table[MESA_FORMAT_ARGB2101010_UINT] = _mesa_texstore_argb2101010_uint; |
| table[MESA_FORMAT_ABGR2101010_UINT] = _mesa_texstore_abgr2101010_uint; |
| initialized = GL_TRUE; |
| } |
| |
| ASSERT(table[format]); |
| return table[format]; |
| } |
| |
| |
| /** |
| * Store user data into texture memory. |
| * Called via glTex[Sub]Image1/2/3D() |
| */ |
| GLboolean |
| _mesa_texstore(TEXSTORE_PARAMS) |
| { |
| StoreTexImageFunc storeImage; |
| GLboolean success; |
| |
| storeImage = _mesa_get_texstore_func(dstFormat); |
| |
| success = storeImage(ctx, dims, baseInternalFormat, |
| dstFormat, |
| dstRowStride, dstSlices, |
| srcWidth, srcHeight, srcDepth, |
| srcFormat, srcType, srcAddr, srcPacking); |
| return success; |
| } |
| |
| |
| /** |
| * Normally, we'll only _write_ texel data to a texture when we map it. |
| * But if the user is providing depth or stencil values and the texture |
| * image is a combined depth/stencil format, we'll actually read from |
| * the texture buffer too (in order to insert the depth or stencil values. |
| * \param userFormat the user-provided image format |
| * \param texFormat the destination texture format |
| */ |
| static GLbitfield |
| get_read_write_mode(GLenum userFormat, gl_format texFormat) |
| { |
| if ((userFormat == GL_STENCIL_INDEX || userFormat == GL_DEPTH_COMPONENT) |
| && _mesa_get_format_base_format(texFormat) == GL_DEPTH_STENCIL) |
| return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; |
| else |
| return GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT; |
| } |
| |
| |
| /** |
| * Helper function for storing 1D, 2D, 3D whole and subimages into texture |
| * memory. |
| * The source of the image data may be user memory or a PBO. In the later |
| * case, we'll map the PBO, copy from it, then unmap it. |
| */ |
| static void |
| store_texsubimage(struct gl_context *ctx, |
| struct gl_texture_image *texImage, |
| GLint xoffset, GLint yoffset, GLint zoffset, |
| GLint width, GLint height, GLint depth, |
| GLenum format, GLenum type, const GLvoid *pixels, |
| const struct gl_pixelstore_attrib *packing, |
| const char *caller) |
| |
| { |
| const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat); |
| const GLenum target = texImage->TexObject->Target; |
| GLboolean success = GL_FALSE; |
| GLuint dims, slice, numSlices = 1, sliceOffset = 0; |
| GLint srcImageStride = 0; |
| const GLubyte *src; |
| |
| assert(xoffset + width <= texImage->Width); |
| assert(yoffset + height <= texImage->Height); |
| assert(zoffset + depth <= texImage->Depth); |
| |
| switch (target) { |
| case GL_TEXTURE_1D: |
| dims = 1; |
| break; |
| case GL_TEXTURE_2D_ARRAY: |
| case GL_TEXTURE_3D: |
| dims = 3; |
| break; |
| default: |
| dims = 2; |
| } |
| |
| /* get pointer to src pixels (may be in a pbo which we'll map here) */ |
| src = (const GLubyte *) |
| _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, |
| format, type, pixels, packing, caller); |
| if (!src) |
| return; |
| |
| /* compute slice info (and do some sanity checks) */ |
| switch (target) { |
| case GL_TEXTURE_2D: |
| case GL_TEXTURE_RECTANGLE: |
| case GL_TEXTURE_CUBE_MAP: |
| /* one image slice, nothing special needs to be done */ |
| break; |
| case GL_TEXTURE_1D: |
| assert(height == 1); |
| assert(depth == 1); |
| assert(yoffset == 0); |
| assert(zoffset == 0); |
| break; |
| case GL_TEXTURE_1D_ARRAY: |
| assert(depth == 1); |
| assert(zoffset == 0); |
| numSlices = height; |
| sliceOffset = yoffset; |
| height = 1; |
| yoffset = 0; |
| srcImageStride = _mesa_image_row_stride(packing, width, format, type); |
| break; |
| case GL_TEXTURE_2D_ARRAY: |
| numSlices = depth; |
| sliceOffset = zoffset; |
| depth = 1; |
| zoffset = 0; |
| srcImageStride = _mesa_image_image_stride(packing, width, height, |
| format, type); |
| break; |
| case GL_TEXTURE_3D: |
| /* we'll store 3D images as a series of slices */ |
| numSlices = depth; |
| sliceOffset = zoffset; |
| srcImageStride = _mesa_image_image_stride(packing, width, height, |
| format, type); |
| break; |
| default: |
| _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()", target); |
| return; |
| } |
| |
| assert(numSlices == 1 || srcImageStride != 0); |
| |
| for (slice = 0; slice < numSlices; slice++) { |
| GLubyte *dstMap; |
| GLint dstRowStride; |
| |
| ctx->Driver.MapTextureImage(ctx, texImage, |
| slice + sliceOffset, |
| xoffset, yoffset, width, height, |
| mapMode, &dstMap, &dstRowStride); |
| if (dstMap) { |
| /* Note: we're only storing a 2D (or 1D) slice at a time but we need |
| * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is |
| * used for 3D images. |
| */ |
| success = _mesa_texstore(ctx, dims, texImage->_BaseFormat, |
| texImage->TexFormat, |
| dstRowStride, |
| &dstMap, |
| width, height, 1, /* w, h, d */ |
| format, type, src, packing); |
| |
| ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset); |
| } |
| |
| src += srcImageStride; |
| |
| if (!success) |
| break; |
| } |
| |
| if (!success) |
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); |
| |
| _mesa_unmap_teximage_pbo(ctx, packing); |
| } |
| |
| |
| |
| /** |
| * Fallback code for ctx->Driver.TexImage(). |
| * Basically, allocate storage for the texture image, then copy the |
| * user's image into it. |
| */ |
| void |
| _mesa_store_teximage(struct gl_context *ctx, |
| GLuint dims, |
| struct gl_texture_image *texImage, |
| GLenum format, GLenum type, const GLvoid *pixels, |
| const struct gl_pixelstore_attrib *packing) |
| { |
| assert(dims == 1 || dims == 2 || dims == 3); |
| |
| if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0) |
| return; |
| |
| /* allocate storage for texture data */ |
| if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) { |
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); |
| return; |
| } |
| |
| store_texsubimage(ctx, texImage, |
| 0, 0, 0, texImage->Width, texImage->Height, texImage->Depth, |
| format, type, pixels, packing, "glTexImage"); |
| } |
| |
| |
| /* |
| * Fallback for Driver.TexSubImage(). |
| */ |
| void |
| _mesa_store_texsubimage(struct gl_context *ctx, GLuint dims, |
| struct gl_texture_image *texImage, |
| GLint xoffset, GLint yoffset, GLint zoffset, |
| GLint width, GLint height, GLint depth, |
| GLenum format, GLenum type, const void *pixels, |
| const struct gl_pixelstore_attrib *packing) |
| { |
| store_texsubimage(ctx, texImage, |
| xoffset, yoffset, zoffset, width, height, depth, |
| format, type, pixels, packing, "glTexSubImage"); |
| } |
| |
| |
| /** |
| * Fallback for Driver.CompressedTexImage() |
| */ |
| void |
| _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, |
| struct gl_texture_image *texImage, |
| GLsizei imageSize, const GLvoid *data) |
| { |
| /* only 2D compressed images are supported at this time */ |
| if (dims != 2) { |
| _mesa_problem(ctx, "Unexpected glCompressedTexImage1D/3D call"); |
| return; |
| } |
| |
| /* This is pretty simple, because unlike the general texstore path we don't |
| * have to worry about the usual image unpacking or image transfer |
| * operations. |
| */ |
| ASSERT(texImage); |
| ASSERT(texImage->Width > 0); |
| ASSERT(texImage->Height > 0); |
| ASSERT(texImage->Depth == 1); |
| |
| /* allocate storage for texture data */ |
| if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) { |
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); |
| return; |
| } |
| |
| _mesa_store_compressed_texsubimage(ctx, dims, texImage, |
| 0, 0, 0, |
| texImage->Width, texImage->Height, texImage->Depth, |
| texImage->TexFormat, |
| imageSize, data); |
| } |
| |
| |
| /** |
| * Fallback for Driver.CompressedTexSubImage() |
| */ |
| void |
| _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, |
| struct gl_texture_image *texImage, |
| GLint xoffset, GLint yoffset, GLint zoffset, |
| GLsizei width, GLsizei height, GLsizei depth, |
| GLenum format, |
| GLsizei imageSize, const GLvoid *data) |
| { |
| GLint bytesPerRow, dstRowStride, srcRowStride; |
| GLint i, rows; |
| GLubyte *dstMap; |
| const GLubyte *src; |
| const gl_format texFormat = texImage->TexFormat; |
| GLuint bw, bh; |
| |
| if (dims != 2) { |
| _mesa_problem(ctx, "Unexpected 1D/3D compressed texsubimage call"); |
| return; |
| } |
| |
| _mesa_get_format_block_size(texFormat, &bw, &bh); |
| |
| /* get pointer to src pixels (may be in a pbo which we'll map here) */ |
| data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, |
| &ctx->Unpack, |
| "glCompressedTexSubImage2D"); |
| if (!data) |
| return; |
| |
| srcRowStride = _mesa_format_row_stride(texFormat, width); |
| src = (const GLubyte *) data; |
| |
| /* Map dest texture buffer */ |
| ctx->Driver.MapTextureImage(ctx, texImage, 0, |
| xoffset, yoffset, width, height, |
| GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, |
| &dstMap, &dstRowStride); |
| |
| if (dstMap) { |
| bytesPerRow = srcRowStride; /* bytes per row of blocks */ |
| rows = (height + bh - 1) / bh; /* rows in blocks */ |
| |
| /* copy rows of blocks */ |
| for (i = 0; i < rows; i++) { |
| memcpy(dstMap, src, bytesPerRow); |
| dstMap += dstRowStride; |
| src += srcRowStride; |
| } |
| |
| ctx->Driver.UnmapTextureImage(ctx, texImage, 0); |
| } |
| else { |
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D"); |
| } |
| |
| _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); |
| } |