mesa: Use _mesa_format_convert to implement texstore_rgba.
Notice that _mesa_format_convert does not handle byte-swapping scenarios, GL_COLOR_INDEX or MESA_FORMAT_YCBCR(_REV), so these must be handled separately. Also, remove all the code that goes unused after using _mesa_format_convert. Reviewed-by: Jason Ekstrand <jason.ekstrand@intel.com>
This commit is contained in:
@@ -220,116 +220,6 @@ _mesa_make_temp_float_image(struct gl_context *ctx, GLuint dims,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mesa_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.
|
* Make a temporary (color) texture image with GLubyte components.
|
||||||
* Apply all needed pixel unpacking and pixel transfer operations.
|
* Apply all needed pixel unpacking and pixel transfer operations.
|
||||||
@@ -517,46 +407,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.
|
* Store a 32-bit integer or float depth component texture image.
|
||||||
*/
|
*/
|
||||||
@@ -689,56 +539,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( srcUB[2], srcUB[1], srcUB[0] );
|
|
||||||
srcUB += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dst += dstRowStride;
|
|
||||||
src += srcRowStride;
|
|
||||||
}
|
|
||||||
return GL_TRUE;
|
|
||||||
} else {
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
|
* Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
|
||||||
*/
|
*/
|
||||||
@@ -1046,119 +846,6 @@ _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
|
|||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
static GLboolean
|
||||||
texstore_depth_stencil(TEXSTORE_PARAMS)
|
texstore_depth_stencil(TEXSTORE_PARAMS)
|
||||||
{
|
{
|
||||||
@@ -1248,327 +935,97 @@ texstore_compressed(TEXSTORE_PARAMS)
|
|||||||
srcFormat, srcType, srcAddr, srcPacking);
|
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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
swap = need_swap ? map_3210 : map_identity;
|
|
||||||
|
|
||||||
_mesa_compute_component_mapping(srcFormat, baseInternalFormat, base2src);
|
|
||||||
_mesa_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]]]];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is it normalized? */
|
|
||||||
normalized |= !_mesa_is_enum_format_integer(srcFormat);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 =
|
|
||||||
_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.
|
|
||||||
*/
|
|
||||||
dstFormat = _mesa_get_srgb_format_linear(dstFormat);
|
|
||||||
|
|
||||||
need_convert = false;
|
|
||||||
if (baseInternalFormat != _mesa_get_format_base_format(dstFormat)) {
|
|
||||||
_mesa_compute_component_mapping(GL_RGBA, baseInternalFormat, base2rgba);
|
|
||||||
_mesa_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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(tmp_row);
|
|
||||||
|
|
||||||
return GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
invert_swizzle(dst2rgba, rgba2dst);
|
|
||||||
_mesa_compute_component_mapping(GL_RGBA, baseInternalFormat, base2rgba);
|
|
||||||
_mesa_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]]];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_mesa_is_type_unsigned(srcType)) {
|
|
||||||
tmp_type = GL_UNSIGNED_INT;
|
|
||||||
} else {
|
|
||||||
tmp_type = GL_INT;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(tmp_row);
|
|
||||||
|
|
||||||
return GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLboolean
|
static GLboolean
|
||||||
texstore_rgba(TEXSTORE_PARAMS)
|
texstore_rgba(TEXSTORE_PARAMS)
|
||||||
{
|
{
|
||||||
static StoreTexImageFunc table[MESA_FORMAT_COUNT];
|
void *tempImage = NULL;
|
||||||
static GLboolean initialized = GL_FALSE;
|
int srcRowStride, img;
|
||||||
|
GLubyte *src;
|
||||||
|
uint32_t srcMesaFormat;
|
||||||
|
uint8_t rebaseSwizzle[4];
|
||||||
|
bool needRebase;
|
||||||
|
|
||||||
if (!initialized) {
|
/* We have to handle MESA_FORMAT_YCBCR manually because it is a special case
|
||||||
memset(table, 0, sizeof table);
|
* 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.
|
||||||
table[MESA_FORMAT_B5G6R5_UNORM] = _mesa_texstore_rgb565;
|
*/
|
||||||
table[MESA_FORMAT_R5G6B5_UNORM] = _mesa_texstore_rgb565;
|
if (dstFormat == MESA_FORMAT_YCBCR || dstFormat == MESA_FORMAT_YCBCR_REV) {
|
||||||
table[MESA_FORMAT_YCBCR] = _mesa_texstore_ycbcr;
|
return _mesa_texstore_ycbcr(ctx, dims, baseInternalFormat,
|
||||||
table[MESA_FORMAT_YCBCR_REV] = _mesa_texstore_ycbcr;
|
dstFormat, dstRowStride, dstSlices,
|
||||||
|
srcWidth, srcHeight, srcDepth,
|
||||||
table[MESA_FORMAT_B10G10R10A2_UINT] = _mesa_texstore_argb2101010_uint;
|
srcFormat, srcType, srcAddr,
|
||||||
table[MESA_FORMAT_R10G10B10A2_UINT] = _mesa_texstore_abgr2101010_uint;
|
srcPacking);
|
||||||
|
|
||||||
initialized = GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table[dstFormat] && table[dstFormat](ctx, dims, baseInternalFormat,
|
/* We have to deal with GL_COLOR_INDEX manually because
|
||||||
dstFormat, dstRowStride, dstSlices,
|
* _mesa_format_convert does not handle this format. So what we do here is
|
||||||
srcWidth, srcHeight, srcDepth,
|
* convert it to RGBA ubyte first and then convert from that to dst as usual.
|
||||||
srcFormat, srcType, srcAddr,
|
*/
|
||||||
srcPacking)) {
|
if (srcFormat == GL_COLOR_INDEX) {
|
||||||
return GL_TRUE;
|
/* Notice that this will already handle byte swapping if necessary */
|
||||||
|
tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
|
||||||
|
baseInternalFormat,
|
||||||
|
GL_RGBA,
|
||||||
|
srcWidth, srcHeight, srcDepth,
|
||||||
|
srcFormat, srcType, srcAddr,
|
||||||
|
srcPacking);
|
||||||
|
if (!tempImage)
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
|
/* 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 components = _mesa_components_in_format(srcFormat);
|
||||||
|
int elementCount = srcWidth * srcHeight * components;
|
||||||
|
tempImage = malloc(elementCount * swapSize);
|
||||||
|
if (!tempImage)
|
||||||
|
return GL_FALSE;
|
||||||
|
if (swapSize == 2)
|
||||||
|
_mesa_swap2_copy(tempImage, (GLushort *) srcAddr, elementCount);
|
||||||
|
else
|
||||||
|
_mesa_swap4_copy(tempImage, (GLuint *) srcAddr, elementCount);
|
||||||
|
srcAddr = tempImage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texstore_swizzle(ctx, dims, baseInternalFormat,
|
srcRowStride =
|
||||||
dstFormat,
|
_mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
|
||||||
dstRowStride, dstSlices,
|
|
||||||
srcWidth, srcHeight, srcDepth,
|
|
||||||
srcFormat, srcType, srcAddr, srcPacking)) {
|
|
||||||
return GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_mesa_is_format_integer(dstFormat)) {
|
src = (GLubyte *)
|
||||||
return texstore_rgba_integer(ctx, dims, baseInternalFormat,
|
_mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
|
||||||
dstFormat, dstRowStride, dstSlices,
|
srcFormat, srcType, 0, 0, 0);
|
||||||
srcWidth, srcHeight, srcDepth,
|
|
||||||
srcFormat, srcType, srcAddr,
|
srcMesaFormat = _mesa_format_from_format_and_type(srcFormat, srcType);
|
||||||
srcPacking);
|
dstFormat = _mesa_get_srgb_format_linear(dstFormat);
|
||||||
} else if (_mesa_get_format_max_bits(dstFormat) <= 8 &&
|
|
||||||
!_mesa_is_format_signed(dstFormat)) {
|
if (_mesa_get_format_base_format(dstFormat) != baseInternalFormat) {
|
||||||
return store_ubyte_texture(ctx, dims, baseInternalFormat,
|
needRebase =
|
||||||
dstFormat,
|
_mesa_compute_rgba2base2rgba_component_mapping(baseInternalFormat,
|
||||||
dstRowStride, dstSlices,
|
rebaseSwizzle);
|
||||||
srcWidth, srcHeight, srcDepth,
|
|
||||||
srcFormat, srcType, srcAddr, srcPacking);
|
|
||||||
} else {
|
} else {
|
||||||
return texstore_via_float(ctx, dims, baseInternalFormat,
|
needRebase = false;
|
||||||
dstFormat, dstRowStride, dstSlices,
|
|
||||||
srcWidth, srcHeight, srcDepth,
|
|
||||||
srcFormat, srcType, srcAddr,
|
|
||||||
srcPacking);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (img = 0; img < srcDepth; img++) {
|
||||||
|
_mesa_format_convert(dstSlices[img], dstFormat, dstRowStride,
|
||||||
|
src, srcMesaFormat, srcRowStride,
|
||||||
|
srcWidth, srcHeight,
|
||||||
|
needRebase ? rebaseSwizzle : NULL);
|
||||||
|
src += srcHeight * srcRowStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tempImage);
|
||||||
|
|
||||||
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLboolean
|
GLboolean
|
||||||
|
Reference in New Issue
Block a user