aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main/texstore.c
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main/texstore.c')
-rw-r--r--mesalib/src/mesa/main/texstore.c1179
1 files changed, 113 insertions, 1066 deletions
diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c
index 50aa1fd5e..7039cdf81 100644
--- a/mesalib/src/mesa/main/texstore.c
+++ b/mesalib/src/mesa/main/texstore.c
@@ -73,6 +73,7 @@
#include "texstore.h"
#include "enums.h"
#include "glformats.h"
+#include "pixeltransfer.h"
#include "../../gallium/auxiliary/util/u_format_rgb9e5.h"
#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h"
@@ -87,577 +88,6 @@ enum {
* Texture image storage function.
*/
typedef GLboolean (*StoreTexImageFunc)(TEXSTORE_PARAMS);
-
-
-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:
- case GL_LUMINANCE_INTEGER_EXT:
- return IDX_LUMINANCE;
- case GL_ALPHA:
- case GL_ALPHA_INTEGER:
- return IDX_ALPHA;
- case GL_INTENSITY:
- return IDX_INTENSITY;
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE_ALPHA_INTEGER_EXT:
- return IDX_LUMINANCE_ALPHA;
- case GL_RGB:
- case GL_RGB_INTEGER:
- return IDX_RGB;
- case GL_RGBA:
- case GL_RGBA_INTEGER:
- return IDX_RGBA;
- case GL_RED:
- case GL_RED_INTEGER:
- return IDX_RED;
- case GL_GREEN:
- return IDX_GREEN;
- case GL_BLUE:
- return IDX_BLUE;
- case GL_BGR:
- case GL_BGR_INTEGER:
- return IDX_BGR;
- case GL_BGRA:
- case GL_BGRA_INTEGER:
- return IDX_BGRA;
- case GL_ABGR_EXT:
- return IDX_ABGR;
- case GL_RG:
- case GL_RG_INTEGER:
- return IDX_RG;
- default:
- _mesa_problem(NULL, "Unexpected inFormat %s",
- _mesa_lookup_enum_by_nr(value));
- 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 = 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 = 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 = 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 = 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 = 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 = 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;
-}
-
-
static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE };
static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE };
static const GLubyte map_1032[6] = { 1, 0, 3, 2, ZERO, ONE };
@@ -716,46 +146,6 @@ memcpy_texture(struct gl_context *ctx,
/**
- * 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;
-
- /* This way we will use the RGB versions of the packing functions and it
- * will work for both RGB and sRGB textures*/
- dstFormat = _mesa_get_srgb_format_linear(dstFormat);
-
- 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
@@ -888,56 +278,6 @@ _mesa_texstore_z16(TEXSTORE_PARAMS)
/**
- * Store an rgb565 or rgb565_rev texture image.
- */
-static GLboolean
-_mesa_texstore_rgb565(TEXSTORE_PARAMS)
-{
- ASSERT(dstFormat == MESA_FORMAT_B5G6R5_UNORM ||
- dstFormat == MESA_FORMAT_R5G6B5_UNORM);
- ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
-
- 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_B5G6R5_UNORM) {
- 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;
- }
- return GL_TRUE;
- } else {
- return GL_FALSE;
- }
-}
-
-
-/**
* Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
*/
static GLboolean
@@ -1245,119 +585,6 @@ _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
}
static GLboolean
-_mesa_texstore_argb2101010_uint(TEXSTORE_PARAMS)
-{
- const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
- ASSERT(dstFormat == MESA_FORMAT_B10G10R10A2_UINT);
- ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
-
- {
- /* 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_R10G10B10A2_UINT);
- ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
-
- {
- /* 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
texstore_depth_stencil(TEXSTORE_PARAMS)
{
static StoreTexImageFunc table[MESA_FORMAT_COUNT];
@@ -1446,329 +673,149 @@ texstore_compressed(TEXSTORE_PARAMS)
srcFormat, srcType, srcAddr, srcPacking);
}
-static void
-invert_swizzle(uint8_t dst[4], const uint8_t src[4])
-{
- int i, j;
-
- dst[0] = MESA_FORMAT_SWIZZLE_NONE;
- dst[1] = MESA_FORMAT_SWIZZLE_NONE;
- dst[2] = MESA_FORMAT_SWIZZLE_NONE;
- dst[3] = MESA_FORMAT_SWIZZLE_NONE;
-
- for (i = 0; i < 4; ++i)
- for (j = 0; j < 4; ++j)
- if (src[j] == i && dst[i] == MESA_FORMAT_SWIZZLE_NONE)
- dst[i] = j;
-}
-
-/** Store a texture by per-channel conversions and swizzling.
- *
- * This function attempts to perform a texstore operation by doing simple
- * per-channel conversions and swizzling. This covers a huge chunk of the
- * texture storage operations that anyone cares about. If this function is
- * incapable of performing the operation, it bails and returns GL_FALSE.
- */
static GLboolean
-texstore_swizzle(TEXSTORE_PARAMS)
+texstore_rgba(TEXSTORE_PARAMS)
{
- 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(dims,
- srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
- const int src_components = _mesa_components_in_format(srcFormat);
-
- GLubyte swizzle[4], rgba2base[6], base2src[6], rgba2dst[4], dst2rgba[4];
- const GLubyte *swap;
- GLenum dst_type;
- int dst_components;
- bool is_array, normalized, need_swap;
- GLint i, img, row;
- const GLubyte *src_row;
- GLubyte *dst_row;
-
- is_array = _mesa_format_to_array(dstFormat, &dst_type, &dst_components,
- rgba2dst, &normalized);
-
- if (!is_array)
- return GL_FALSE;
-
- if (srcFormat == GL_COLOR_INDEX)
- return GL_FALSE;
-
- if (_mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat))
- return GL_FALSE;
-
- switch (srcType) {
- case GL_FLOAT:
- case GL_UNSIGNED_BYTE:
- case GL_BYTE:
- case GL_UNSIGNED_SHORT:
- case GL_SHORT:
- case GL_UNSIGNED_INT:
- case GL_INT:
- /* If wa have to swap bytes in a multi-byte datatype, that means
- * we're not doing an array conversion anymore */
- if (srcPacking->SwapBytes)
- return GL_FALSE;
- need_swap = false;
- break;
- case GL_UNSIGNED_INT_8_8_8_8:
- need_swap = srcPacking->SwapBytes;
- if (_mesa_little_endian())
- need_swap = !need_swap;
- srcType = GL_UNSIGNED_BYTE;
- break;
- case GL_UNSIGNED_INT_8_8_8_8_REV:
- need_swap = srcPacking->SwapBytes;
- if (!_mesa_little_endian())
- need_swap = !need_swap;
- srcType = GL_UNSIGNED_BYTE;
- break;
- default:
- return GL_FALSE;
+ void *tempImage = NULL, *tempRGBA = NULL;
+ int srcRowStride, img;
+ GLubyte *src, *dst;
+ uint32_t srcMesaFormat;
+ uint8_t rebaseSwizzle[4];
+ bool needRebase;
+ bool transferOpsDone = false;
+
+ /* We have to handle MESA_FORMAT_YCBCR manually because it is a special case
+ * and _mesa_format_convert does not support it. In this case the we only
+ * allow conversions between YCBCR formats and it is mostly a memcpy.
+ */
+ if (dstFormat == MESA_FORMAT_YCBCR || dstFormat == MESA_FORMAT_YCBCR_REV) {
+ return _mesa_texstore_ycbcr(ctx, dims, baseInternalFormat,
+ dstFormat, dstRowStride, dstSlices,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
}
- swap = need_swap ? map_3210 : map_identity;
-
- compute_component_mapping(srcFormat, baseInternalFormat, base2src);
- compute_component_mapping(baseInternalFormat, GL_RGBA, rgba2base);
- invert_swizzle(dst2rgba, rgba2dst);
- for (i = 0; i < 4; i++) {
- if (dst2rgba[i] == MESA_FORMAT_SWIZZLE_NONE)
- swizzle[i] = MESA_FORMAT_SWIZZLE_NONE;
- else
- swizzle[i] = swap[base2src[rgba2base[dst2rgba[i]]]];
- }
+ /* We have to deal with GL_COLOR_INDEX manually because
+ * _mesa_format_convert does not handle this format. So what we do here is
+ * convert it to RGBA ubyte first and then convert from that to dst as usual.
+ */
+ if (srcFormat == GL_COLOR_INDEX) {
+ /* Notice that this will already handle byte swapping if necessary */
+ tempImage =
+ _mesa_unpack_color_index_to_rgba_ubyte(ctx, dims,
+ srcAddr, srcFormat, srcType,
+ srcWidth, srcHeight, srcDepth,
+ srcPacking,
+ ctx->_ImageTransferState);
+ if (!tempImage)
+ return GL_FALSE;
- /* Is it normalized? */
- normalized |= !_mesa_is_enum_format_integer(srcFormat);
+ /* _mesa_unpack_color_index_to_rgba_ubyte has handled transferops
+ * if needed.
+ */
+ transferOpsDone = true;
- for (img = 0; img < srcDepth; img++) {
- if (dstRowStride == srcWidth * dst_components &&
- srcRowStride == srcWidth * src_components) {
- _mesa_swizzle_and_convert(dstSlices[img], dst_type, dst_components,
- srcImage, srcType, src_components,
- swizzle, normalized, srcWidth * srcHeight);
- } else {
- src_row = srcImage;
- dst_row = dstSlices[img];
- for (row = 0; row < srcHeight; row++) {
- _mesa_swizzle_and_convert(dst_row, dst_type, dst_components,
- src_row, srcType, src_components,
- swizzle, normalized, srcWidth);
- dst_row += dstRowStride;
- src_row += srcRowStride;
- }
+ /* Now we only have to adjust our src info for a conversion from
+ * the RGBA ubyte and then we continue as usual.
+ */
+ srcAddr = tempImage;
+ srcFormat = GL_RGBA;
+ srcType = GL_UNSIGNED_BYTE;
+ } else if (srcPacking->SwapBytes) {
+ /* We have to handle byte-swapping scenarios before calling
+ * _mesa_format_convert
+ */
+ GLint swapSize = _mesa_sizeof_packed_type(srcType);
+ if (swapSize == 2 || swapSize == 4) {
+ int bytesPerPixel = _mesa_bytes_per_pixel(srcFormat, srcType);
+ int swapsPerPixel = bytesPerPixel / swapSize;
+ int elementCount = srcWidth * srcHeight * srcDepth;
+ assert(bytesPerPixel % swapSize == 0);
+ tempImage = malloc(elementCount * bytesPerPixel);
+ if (!tempImage)
+ return GL_FALSE;
+ if (swapSize == 2)
+ _mesa_swap2_copy(tempImage, (GLushort *) srcAddr,
+ elementCount * swapsPerPixel);
+ else
+ _mesa_swap4_copy(tempImage, (GLuint *) srcAddr,
+ elementCount * swapsPerPixel);
+ srcAddr = tempImage;
}
- srcImage += srcImageStride;
}
- return GL_TRUE;
-}
-
-
-/** Stores a texture by converting float and then to the texture format
- *
- * This function performs a texstore operation by converting to float,
- * applying pixel transfer ops, and then converting to the texture's
- * internal format using pixel store functions. This function will work
- * for any rgb or srgb textore format.
- */
-static GLboolean
-texstore_via_float(TEXSTORE_PARAMS)
-{
- GLuint i, img, row;
- const GLint src_stride =
+ srcRowStride =
_mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
- float *tmp_row;
- bool need_convert;
- uint8_t *src_row, *dst_row, map[4], rgba2base[6], base2rgba[6];
-
- tmp_row = malloc(srcWidth * 4 * sizeof(*tmp_row));
- if (!tmp_row)
- return GL_FALSE;
- /* The GL spec (4.0, compatibility profile) only specifies srgb
- * conversion as something that is done in the sampler during the
- * filtering process before the colors are handed to the shader.
- * Furthermore, the flowchart (Figure 3.7 in the 4.0 compatibility spec)
- * does not list RGB <-> sRGB conversions anywhere. Therefore, we just
- * treat sRGB formats the same as RGB formats for the purposes of
- * texture upload and transfer ops.
- */
+ srcMesaFormat = _mesa_format_from_format_and_type(srcFormat, srcType);
dstFormat = _mesa_get_srgb_format_linear(dstFormat);
- need_convert = false;
- if (baseInternalFormat != _mesa_get_format_base_format(dstFormat)) {
- compute_component_mapping(GL_RGBA, baseInternalFormat, base2rgba);
- compute_component_mapping(baseInternalFormat, GL_RGBA, rgba2base);
- for (i = 0; i < 4; ++i) {
- map[i] = base2rgba[rgba2base[i]];
- if (map[i] != i)
- need_convert = true;
+ /* If we have transferOps then we need to convert to RGBA float first,
+ then apply transferOps, then do the conversion to dst
+ */
+ if (!transferOpsDone &&
+ _mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) {
+ /* Allocate RGBA float image */
+ int elementCount = srcWidth * srcHeight * srcDepth;
+ tempRGBA = malloc(4 * elementCount * sizeof(float));
+ if (!tempRGBA) {
+ free(tempImage);
+ free(tempRGBA);
+ return GL_FALSE;
}
- }
- for (img = 0; img < srcDepth; img++) {
- dst_row = dstSlices[img];
- src_row = _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, GL_RGBA, tmp_row,
- srcFormat, srcType, src_row,
- srcPacking, ctx->_ImageTransferState);
- if (need_convert)
- _mesa_swizzle_and_convert(tmp_row, GL_FLOAT, 4,
- tmp_row, GL_FLOAT, 4,
- map, false, srcWidth);
- _mesa_pack_float_rgba_row(dstFormat, srcWidth,
- (const GLfloat (*)[4])tmp_row,
- dst_row);
- dst_row += dstRowStride;
- src_row += src_stride;
+ /* Convert from src to RGBA float */
+ src = (GLubyte *) srcAddr;
+ dst = (GLubyte *) tempRGBA;
+ for (img = 0; img < srcDepth; img++) {
+ _mesa_format_convert(dst, RGBA32_FLOAT, 4 * srcWidth * sizeof(float),
+ src, srcMesaFormat, srcRowStride,
+ srcWidth, srcHeight, NULL);
+ src += srcHeight * srcRowStride;
+ dst += srcHeight * 4 * srcWidth * sizeof(float);
}
- }
- free(tmp_row);
-
- return GL_TRUE;
-}
+ /* Apply transferOps */
+ _mesa_apply_rgba_transfer_ops(ctx, ctx->_ImageTransferState, elementCount,
+ (float(*)[4]) tempRGBA);
-/** Stores an integer rgba texture
- *
- * This function performs an integer texture storage operation by unpacking
- * the texture to 32-bit integers, and repacking it into the internal
- * format of the texture. This will work for any integer rgb texture
- * storage operation.
- */
-static GLboolean
-texstore_rgba_integer(TEXSTORE_PARAMS)
-{
- GLuint i, img, row, *tmp_row;
- GLenum dst_type, tmp_type;
- const GLint src_stride =
- _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
- int num_dst_components;
- bool is_array, normalized;
- uint8_t *src_row, *dst_row;
- uint8_t swizzle[4], rgba2base[6], base2rgba[6], rgba2dst[4], dst2rgba[4];
-
- tmp_row = malloc(srcWidth * 4 * sizeof(*tmp_row));
- if (!tmp_row)
- return GL_FALSE;
-
- is_array = _mesa_format_to_array(dstFormat, &dst_type, &num_dst_components,
- rgba2dst, &normalized);
-
- assert(is_array && !normalized);
-
- if (!is_array) {
- free(tmp_row);
- return GL_FALSE;
+ /* Now we have to adjust our src info for a conversion from
+ * the RGBA float image and then we continue as usual.
+ */
+ srcAddr = tempRGBA;
+ srcFormat = GL_RGBA;
+ srcType = GL_FLOAT;
+ srcRowStride = srcWidth * 4 * sizeof(float);
+ srcMesaFormat = RGBA32_FLOAT;
}
- invert_swizzle(dst2rgba, rgba2dst);
- compute_component_mapping(GL_RGBA, baseInternalFormat, base2rgba);
- compute_component_mapping(baseInternalFormat, GL_RGBA, rgba2base);
-
- for (i = 0; i < 4; ++i) {
- if (dst2rgba[i] == MESA_FORMAT_SWIZZLE_NONE)
- swizzle[i] = MESA_FORMAT_SWIZZLE_NONE;
- else
- swizzle[i] = base2rgba[rgba2base[dst2rgba[i]]];
- }
+ src = (GLubyte *)
+ _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
+ srcFormat, srcType, 0, 0, 0);
- if (_mesa_is_type_unsigned(srcType)) {
- tmp_type = GL_UNSIGNED_INT;
+ if (_mesa_get_format_base_format(dstFormat) != baseInternalFormat) {
+ needRebase =
+ _mesa_compute_rgba2base2rgba_component_mapping(baseInternalFormat,
+ rebaseSwizzle);
} else {
- tmp_type = GL_INT;
+ needRebase = false;
}
for (img = 0; img < srcDepth; img++) {
- dst_row = dstSlices[img];
- src_row = _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, GL_RGBA, tmp_row,
- srcFormat, srcType, src_row, srcPacking);
- _mesa_swizzle_and_convert(dst_row, dst_type, num_dst_components,
- tmp_row, tmp_type, 4,
- swizzle, false, srcWidth);
- dst_row += dstRowStride;
- src_row += src_stride;
- }
+ _mesa_format_convert(dstSlices[img], dstFormat, dstRowStride,
+ src, srcMesaFormat, srcRowStride,
+ srcWidth, srcHeight,
+ needRebase ? rebaseSwizzle : NULL);
+ src += srcHeight * srcRowStride;
}
- free(tmp_row);
+ free(tempImage);
+ free(tempRGBA);
return GL_TRUE;
}
-static GLboolean
-texstore_rgba(TEXSTORE_PARAMS)
-{
- static StoreTexImageFunc table[MESA_FORMAT_COUNT];
- static GLboolean initialized = GL_FALSE;
-
- if (!initialized) {
- memset(table, 0, sizeof table);
-
- table[MESA_FORMAT_B5G6R5_UNORM] = _mesa_texstore_rgb565;
- table[MESA_FORMAT_R5G6B5_UNORM] = _mesa_texstore_rgb565;
- table[MESA_FORMAT_YCBCR] = _mesa_texstore_ycbcr;
- table[MESA_FORMAT_YCBCR_REV] = _mesa_texstore_ycbcr;
-
- table[MESA_FORMAT_B10G10R10A2_UINT] = _mesa_texstore_argb2101010_uint;
- table[MESA_FORMAT_R10G10B10A2_UINT] = _mesa_texstore_abgr2101010_uint;
-
- initialized = GL_TRUE;
- }
-
- if (table[dstFormat] && table[dstFormat](ctx, dims, baseInternalFormat,
- dstFormat, dstRowStride, dstSlices,
- srcWidth, srcHeight, srcDepth,
- srcFormat, srcType, srcAddr,
- srcPacking)) {
- return GL_TRUE;
- }
-
- if (texstore_swizzle(ctx, dims, baseInternalFormat,
- dstFormat,
- dstRowStride, dstSlices,
- srcWidth, srcHeight, srcDepth,
- srcFormat, srcType, srcAddr, srcPacking)) {
- return GL_TRUE;
- }
-
- if (_mesa_is_format_integer(dstFormat)) {
- return texstore_rgba_integer(ctx, dims, baseInternalFormat,
- dstFormat, dstRowStride, dstSlices,
- srcWidth, srcHeight, srcDepth,
- srcFormat, srcType, srcAddr,
- srcPacking);
- } else if (_mesa_get_format_max_bits(dstFormat) <= 8 &&
- !_mesa_is_format_signed(dstFormat)) {
- return store_ubyte_texture(ctx, dims, baseInternalFormat,
- dstFormat,
- dstRowStride, dstSlices,
- srcWidth, srcHeight, srcDepth,
- srcFormat, srcType, srcAddr, srcPacking);
- } else {
- return texstore_via_float(ctx, dims, baseInternalFormat,
- dstFormat, dstRowStride, dstSlices,
- srcWidth, srcHeight, srcDepth,
- srcFormat, srcType, srcAddr,
- srcPacking);
- }
-}
-
GLboolean
_mesa_texstore_needs_transfer_ops(struct gl_context *ctx,
GLenum baseInternalFormat,