X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Ftexcompress_etc.c;h=d4650109857171d6c114ca05fd3370d513b27227;hb=edd50828618ed2efe799013c2723d67c407d86b4;hp=d5a623a464a415a062187977b0fab0b6b3d0f516;hpb=75211f4367cab6477890111211d3437bf469670b;p=mesa.git diff --git a/src/mesa/main/texcompress_etc.c b/src/mesa/main/texcompress_etc.c index d5a623a464a..d4650109857 100644 --- a/src/mesa/main/texcompress_etc.c +++ b/src/mesa/main/texcompress_etc.c @@ -33,22 +33,25 @@ * GL_COMPRESSED_RG11_EAC * GL_COMPRESSED_SIGNED_R11_EAC * GL_COMPRESSED_SIGNED_RG11_EAC + * MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1 + * MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1 */ #include -#include "mfeatures.h" #include "texcompress.h" #include "texcompress_etc.h" #include "texstore.h" #include "macros.h" -#include "swrast/s_context.h" #include "format_unpack.h" +#include "util/format_srgb.h" + struct etc2_block { int distance; uint64_t pixel_indices[2]; const int *modifier_tables[2]; bool flipped; + bool opaque; bool is_ind_mode; bool is_diff_mode; bool is_t_mode; @@ -83,6 +86,17 @@ static const int etc2_modifier_tables[16][8] = { { -3, -5, -7, -9, 2, 4, 6, 8}, }; +static const int etc2_modifier_tables_non_opaque[8][4] = { + { 0, 8, 0, -8}, + { 0, 17, 0, -17}, + { 0, 29, 0, -29}, + { 0, 42, 0, -42}, + { 0, 60, 0, -60}, + { 0, 80, 0, -80}, + { 0, 106, 0, -106}, + { 0, 183, 0, -183} +}; + /* define etc1_parse_block and etc. */ #define UINT8_TYPE GLubyte #define TAG(x) x @@ -94,30 +108,11 @@ GLboolean _mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS) { /* GL_ETC1_RGB8_OES is only valid in glCompressedTexImage2D */ - ASSERT(0); + assert(0); return GL_FALSE; } -void -_mesa_fetch_texel_2d_f_etc1_rgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - struct etc1_block block; - GLubyte dst[3]; - const GLubyte *src; - - src = (const GLubyte *) texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; - - etc1_parse_block(&block, src); - etc1_fetch_texel(&block, i % 4, j % 4, dst); - - texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); - texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); - texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); - texel[ACOMP] = 1.0f; -} /** * Decode texture data in format `MESA_FORMAT_ETC1_RGB8` to @@ -217,7 +212,7 @@ etc2_base_color1_h_mode(const uint8_t *in, GLuint index) break; } return ((x << 4) | (x & 0xf)); - } +} static uint8_t etc2_base_color2_h_mode(const uint8_t *in, GLuint index) @@ -239,7 +234,7 @@ etc2_base_color2_h_mode(const uint8_t *in, GLuint index) break; } return ((x << 4) | (x & 0xf)); - } +} static uint8_t etc2_base_color_o_planar(const uint8_t *in, GLuint index) @@ -338,10 +333,12 @@ etc2_clamp3(int color) } static void -etc2_rgb8_parse_block(struct etc2_block *block, const uint8_t *src) +etc2_rgb8_parse_block(struct etc2_block *block, + const uint8_t *src, + GLboolean punchthrough_alpha) { unsigned i; - GLboolean diffbit = src[3] & 0x2; + GLboolean diffbit = false; static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 }; const int R_plus_dR = (src[0] >> 3) + lookup[src[0] & 0x7]; @@ -355,7 +352,12 @@ etc2_rgb8_parse_block(struct etc2_block *block, const uint8_t *src) block->is_h_mode = false; block->is_planar_mode = false; - if (!diffbit) { + if (punchthrough_alpha) + block->opaque = src[3] & 0x2; + else + diffbit = src[3] & 0x2; + + if (!diffbit && !punchthrough_alpha) { /* individual mode */ block->is_ind_mode = true; @@ -390,9 +392,10 @@ etc2_rgb8_parse_block(struct etc2_block *block, const uint8_t *src) } } else if (G_plus_dG < 0 || G_plus_dG > 31){ + int base_color_1_value, base_color_2_value; + /* H mode */ block->is_h_mode = true; - int base_color_1_value, base_color_2_value; for(i = 0; i < 3; i++) { block->base_colors[0][i] = etc2_base_color1_h_mode(src, i); @@ -422,17 +425,20 @@ etc2_rgb8_parse_block(struct etc2_block *block, const uint8_t *src) block->distance); } } - else if (B_plus_dB < 0 || B_plus_dB > 31){ + else if (B_plus_dB < 0 || B_plus_dB > 31) { /* Planar mode */ block->is_planar_mode = true; + /* opaque bit must be set in planar mode */ + block->opaque = true; + for (i = 0; i < 3; i++) { block->base_colors[0][i] = etc2_base_color_o_planar(src, i); block->base_colors[1][i] = etc2_base_color_h_planar(src, i); block->base_colors[2][i] = etc2_base_color_v_planar(src, i); } } - else if (diffbit) { + else if (diffbit || punchthrough_alpha) { /* differential mode */ block->is_diff_mode = true; @@ -442,13 +448,23 @@ etc2_rgb8_parse_block(struct etc2_block *block, const uint8_t *src) */ block->base_colors[0][i] = etc1_base_color_diff_hi(src[i]); block->base_colors[1][i] = etc1_base_color_diff_lo(src[i]); - } + } } if (block->is_ind_mode || block->is_diff_mode) { - /* pick modifier tables. same for etc1 & etc2 textures */ - block->modifier_tables[0] = etc1_modifier_tables[(src[3] >> 5) & 0x7]; - block->modifier_tables[1] = etc1_modifier_tables[(src[3] >> 2) & 0x7]; + int table1_idx = (src[3] >> 5) & 0x7; + int table2_idx = (src[3] >> 2) & 0x7; + + /* Use same modifier tables as for etc1 textures if opaque bit is set + * or if non punchthrough texture format + */ + block->modifier_tables[0] = (!punchthrough_alpha || block->opaque) ? + etc1_modifier_tables[table1_idx] : + etc2_modifier_tables_non_opaque[table1_idx]; + block->modifier_tables[1] = (!punchthrough_alpha || block->opaque) ? + etc1_modifier_tables[table2_idx] : + etc2_modifier_tables_non_opaque[table2_idx]; + block->flipped = (src[3] & 0x1); } @@ -458,7 +474,8 @@ etc2_rgb8_parse_block(struct etc2_block *block, const uint8_t *src) static void etc2_rgb8_fetch_texel(const struct etc2_block *block, - int x, int y, uint8_t *dst) + int x, int y, uint8_t *dst, + GLboolean punchthrough_alpha) { const uint8_t *base_color; int modifier, bit, idx, blk; @@ -469,6 +486,16 @@ etc2_rgb8_fetch_texel(const struct etc2_block *block, ((block->pixel_indices[0] >> (bit)) & 0x1); if (block->is_ind_mode || block->is_diff_mode) { + /* check for punchthrough_alpha format */ + if (punchthrough_alpha) { + if (!block->opaque && idx == 2) { + dst[0] = dst[1] = dst[2] = dst[3] = 0; + return; + } + else + dst[3] = 255; + } + /* Use pixel index and subblock to get the modifier */ blk = (block->flipped) ? (y >= 2) : (x >= 2); base_color = block->base_colors[blk]; @@ -479,6 +506,16 @@ etc2_rgb8_fetch_texel(const struct etc2_block *block, dst[2] = etc2_clamp(base_color[2] + modifier); } else if (block->is_t_mode || block->is_h_mode) { + /* check for punchthrough_alpha format */ + if (punchthrough_alpha) { + if (!block->opaque && idx == 2) { + dst[0] = dst[1] = dst[2] = dst[3] = 0; + return; + } + else + dst[3] = 255; + } + /* Use pixel index to pick one of the paint colors */ dst[0] = block->paint_colors[idx][0]; dst[1] = block->paint_colors[idx][1]; @@ -505,7 +542,11 @@ etc2_rgb8_fetch_texel(const struct etc2_block *block, dst[0] = etc2_clamp(red); dst[1] = etc2_clamp(green); dst[2] = etc2_clamp(blue); - } + + /* check for punchthrough_alpha format */ + if (punchthrough_alpha) + dst[3] = 255; + } } static void @@ -609,8 +650,8 @@ static void etc2_rgba8_parse_block(struct etc2_block *block, const uint8_t *src) { /* RGB component is parsed the same way as for MESA_FORMAT_ETC2_RGB8 */ - etc2_rgb8_parse_block(block, src + 8); - + etc2_rgb8_parse_block(block, src + 8, + false /* punchthrough_alpha */); /* Parse Alpha component */ etc2_alpha8_parse_block(block, src); } @@ -619,7 +660,8 @@ static void etc2_rgba8_fetch_texel(const struct etc2_block *block, int x, int y, uint8_t *dst) { - etc2_rgb8_fetch_texel(block, x, y, dst); + etc2_rgb8_fetch_texel(block, x, y, dst, + false /* punchthrough_alpha */); etc2_alpha8_fetch_texel(block, x, y, dst); } @@ -637,14 +679,27 @@ etc2_unpack_rgb8(uint8_t *dst_row, for (y = 0; y < height; y += bh) { const uint8_t *src = src_row; + /* + * Destination texture may not be a multiple of four texels in + * height. Compute a safe height to avoid writing outside the texture. + */ + const unsigned h = MIN2(bh, height - y); for (x = 0; x < width; x+= bw) { - etc2_rgb8_parse_block(&block, src); + /* + * Destination texture may not be a multiple of four texels in + * width. Compute a safe width to avoid writing outside the texture. + */ + const unsigned w = MIN2(bw, width - x); + + etc2_rgb8_parse_block(&block, src, + false /* punchthrough_alpha */); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; - for (i = 0; i < bw; i++) { - etc2_rgb8_fetch_texel(&block, i, j, dst); + for (i = 0; i < w; i++) { + etc2_rgb8_fetch_texel(&block, i, j, dst, + false /* punchthrough_alpha */); dst[3] = 255; dst += comps; } @@ -672,15 +727,20 @@ etc2_unpack_srgb8(uint8_t *dst_row, for (y = 0; y < height; y += bh) { const uint8_t *src = src_row; + const unsigned h = MIN2(bh, height - y); for (x = 0; x < width; x+= bw) { - etc2_rgb8_parse_block(&block, src); + const unsigned w = MIN2(bw, width - x); + etc2_rgb8_parse_block(&block, src, + false /* punchthrough_alpha */); - for (j = 0; j < bh; j++) { + + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; - for (i = 0; i < bw; i++) { - etc2_rgb8_fetch_texel(&block, i, j, dst); - /* Convert to MESA_FORMAT_SARGB8 */ + for (i = 0; i < w; i++) { + etc2_rgb8_fetch_texel(&block, i, j, dst, + false /* punchthrough_alpha */); + /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */ tmp = dst[0]; dst[0] = dst[2]; dst[2] = tmp; @@ -690,10 +750,10 @@ etc2_unpack_srgb8(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -714,22 +774,24 @@ etc2_unpack_rgba8(uint8_t *dst_row, for (y = 0; y < height; y += bh) { const uint8_t *src = src_row; + const unsigned h = MIN2(bh, height - y); for (x = 0; x < width; x+= bw) { + const unsigned w = MIN2(bw, width - x); etc2_rgba8_parse_block(&block, src); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; - for (i = 0; i < bw; i++) { + for (i = 0; i < w; i++) { etc2_rgba8_fetch_texel(&block, i, j, dst); dst += comps; } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -750,17 +812,19 @@ etc2_unpack_srgb8_alpha8(uint8_t *dst_row, uint8_t tmp; for (y = 0; y < height; y += bh) { + const unsigned h = MIN2(bh, height - y); const uint8_t *src = src_row; for (x = 0; x < width; x+= bw) { + const unsigned w = MIN2(bw, width - x); etc2_rgba8_parse_block(&block, src); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; - for (i = 0; i < bw; i++) { + for (i = 0; i < w; i++) { etc2_rgba8_fetch_texel(&block, i, j, dst); - /* Convert to MESA_FORMAT_SARGB8 */ + /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */ tmp = dst[0]; dst[0] = dst[2]; dst[2] = tmp; @@ -770,10 +834,10 @@ etc2_unpack_srgb8_alpha8(uint8_t *dst_row, } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -792,23 +856,25 @@ etc2_unpack_r11(uint8_t *dst_row, unsigned x, y, i, j; for (y = 0; y < height; y += bh) { + const unsigned h = MIN2(bh, height - y); const uint8_t *src = src_row; for (x = 0; x < width; x+= bw) { + const unsigned w = MIN2(bw, width - x); etc2_r11_parse_block(&block, src); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size; - for (i = 0; i < bw; i++) { + for (i = 0; i < w; i++) { etc2_r11_fetch_texel(&block, i, j, dst); dst += comps * comp_size; } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -827,16 +893,18 @@ etc2_unpack_rg11(uint8_t *dst_row, unsigned x, y, i, j; for (y = 0; y < height; y += bh) { + const unsigned h = MIN2(bh, height - y); const uint8_t *src = src_row; for (x = 0; x < width; x+= bw) { + const unsigned w = MIN2(bw, width - x); /* red component */ etc2_r11_parse_block(&block, src); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size; - for (i = 0; i < bw; i++) { + for (i = 0; i < w; i++) { etc2_r11_fetch_texel(&block, i, j, dst); dst += comps * comp_size; } @@ -844,19 +912,19 @@ etc2_unpack_rg11(uint8_t *dst_row, /* green component */ etc2_r11_parse_block(&block, src + 8); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size; - for (i = 0; i < bw; i++) { + for (i = 0; i < w; i++) { etc2_r11_fetch_texel(&block, i, j, dst + comp_size); dst += comps * comp_size; } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -875,24 +943,26 @@ etc2_unpack_signed_r11(uint8_t *dst_row, unsigned x, y, i, j; for (y = 0; y < height; y += bh) { + const unsigned h = MIN2(bh, height - y); const uint8_t *src = src_row; for (x = 0; x < width; x+= bw) { + const unsigned w = MIN2(bw, width - x); etc2_r11_parse_block(&block, src); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size; - for (i = 0; i < bw; i++) { + for (i = 0; i < w; i++) { etc2_signed_r11_fetch_texel(&block, i, j, dst); dst += comps * comp_size; } } src += bs; - } + } src_row += src_stride; - } + } } static void @@ -911,16 +981,18 @@ etc2_unpack_signed_rg11(uint8_t *dst_row, unsigned x, y, i, j; for (y = 0; y < height; y += bh) { + const unsigned h = MIN2(bh, height - y); const uint8_t *src = src_row; for (x = 0; x < width; x+= bw) { + const unsigned w = MIN2(bw, width - x); /* red component */ etc2_r11_parse_block(&block, src); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size; - for (i = 0; i < bw; i++) { + for (i = 0; i < w; i++) { etc2_signed_r11_fetch_texel(&block, i, j, dst); dst += comps * comp_size; } @@ -928,19 +1000,98 @@ etc2_unpack_signed_rg11(uint8_t *dst_row, /* green component */ etc2_r11_parse_block(&block, src + 8); - for (j = 0; j < bh; j++) { + for (j = 0; j < h; j++) { uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size; - for (i = 0; i < bw; i++) { + for (i = 0; i < w; i++) { etc2_signed_r11_fetch_texel(&block, i, j, dst + comp_size); dst += comps * comp_size; } } src += bs; - } + } src_row += src_stride; - } + } +} + +static void +etc2_unpack_rgb8_punchthrough_alpha1(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + const unsigned bw = 4, bh = 4, bs = 8, comps = 4; + struct etc2_block block; + unsigned x, y, i, j; + + for (y = 0; y < height; y += bh) { + const unsigned h = MIN2(bh, height - y); + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + const unsigned w = MIN2(bw, width - x); + etc2_rgb8_parse_block(&block, src, + true /* punchthrough_alpha */); + for (j = 0; j < h; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; + for (i = 0; i < w; i++) { + etc2_rgb8_fetch_texel(&block, i, j, dst, + true /* punchthrough_alpha */); + dst += comps; + } + } + + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_srgb8_punchthrough_alpha1(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + const unsigned bw = 4, bh = 4, bs = 8, comps = 4; + struct etc2_block block; + unsigned x, y, i, j; + uint8_t tmp; + + for (y = 0; y < height; y += bh) { + const unsigned h = MIN2(bh, height - y); + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + const unsigned w = MIN2(bw, width - x); + etc2_rgb8_parse_block(&block, src, + true /* punchthrough_alpha */); + for (j = 0; j < h; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; + for (i = 0; i < w; i++) { + etc2_rgb8_fetch_texel(&block, i, j, dst, + true /* punchthrough_alpha */); + /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */ + tmp = dst[0]; + dst[0] = dst[2]; + dst[2] = tmp; + dst[3] = dst[3]; + + dst += comps; + } + } + + src += bs; + } + + src_row += src_stride; + } } /* ETC2 texture formats are valid in glCompressedTexImage2D and @@ -948,7 +1099,7 @@ etc2_unpack_signed_rg11(uint8_t *dst_row, GLboolean _mesa_texstore_etc2_rgb8(TEXSTORE_PARAMS) { - ASSERT(0); + assert(0); return GL_FALSE; } @@ -956,7 +1107,7 @@ _mesa_texstore_etc2_rgb8(TEXSTORE_PARAMS) GLboolean _mesa_texstore_etc2_srgb8(TEXSTORE_PARAMS) { - ASSERT(0); + assert(0); return GL_FALSE; } @@ -964,7 +1115,7 @@ _mesa_texstore_etc2_srgb8(TEXSTORE_PARAMS) GLboolean _mesa_texstore_etc2_rgba8_eac(TEXSTORE_PARAMS) { - ASSERT(0); + assert(0); return GL_FALSE; } @@ -972,7 +1123,7 @@ _mesa_texstore_etc2_rgba8_eac(TEXSTORE_PARAMS) GLboolean _mesa_texstore_etc2_srgb8_alpha8_eac(TEXSTORE_PARAMS) { - ASSERT(0); + assert(0); return GL_FALSE; } @@ -980,7 +1131,7 @@ _mesa_texstore_etc2_srgb8_alpha8_eac(TEXSTORE_PARAMS) GLboolean _mesa_texstore_etc2_r11_eac(TEXSTORE_PARAMS) { - ASSERT(0); + assert(0); return GL_FALSE; } @@ -988,7 +1139,7 @@ _mesa_texstore_etc2_r11_eac(TEXSTORE_PARAMS) GLboolean _mesa_texstore_etc2_signed_r11_eac(TEXSTORE_PARAMS) { - ASSERT(0); + assert(0); return GL_FALSE; } @@ -996,7 +1147,7 @@ _mesa_texstore_etc2_signed_r11_eac(TEXSTORE_PARAMS) GLboolean _mesa_texstore_etc2_rg11_eac(TEXSTORE_PARAMS) { - ASSERT(0); + assert(0); return GL_FALSE; } @@ -1004,24 +1155,137 @@ _mesa_texstore_etc2_rg11_eac(TEXSTORE_PARAMS) GLboolean _mesa_texstore_etc2_signed_rg11_eac(TEXSTORE_PARAMS) { - ASSERT(0); + assert(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_rgb8_punchthrough_alpha1(TEXSTORE_PARAMS) +{ + assert(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_srgb8_punchthrough_alpha1(TEXSTORE_PARAMS) +{ + assert(0); return GL_FALSE; } + +/** + * Decode texture data in any one of following formats: + * `MESA_FORMAT_ETC2_RGB8` + * `MESA_FORMAT_ETC2_SRGB8` + * `MESA_FORMAT_ETC2_RGBA8_EAC` + * `MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC` + * `MESA_FORMAT_ETC2_R11_EAC` + * `MESA_FORMAT_ETC2_RG11_EAC` + * `MESA_FORMAT_ETC2_SIGNED_R11_EAC` + * `MESA_FORMAT_ETC2_SIGNED_RG11_EAC` + * `MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1` + * `MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1` + * + * The size of the source data must be a multiple of the ETC2 block size + * even if the texture image's dimensions are not aligned to 4. + * + * \param src_width in pixels + * \param src_height in pixels + * \param dst_stride in bytes + */ + void -_mesa_fetch_texel_2d_f_etc2_rgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +_mesa_unpack_etc2_format(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned src_width, + unsigned src_height, + mesa_format format) +{ + if (format == MESA_FORMAT_ETC2_RGB8) + etc2_unpack_rgb8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8) + etc2_unpack_srgb8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RGBA8_EAC) + etc2_unpack_rgba8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC) + etc2_unpack_srgb8_alpha8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_R11_EAC) + etc2_unpack_r11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RG11_EAC) + etc2_unpack_rg11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SIGNED_R11_EAC) + etc2_unpack_signed_r11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SIGNED_RG11_EAC) + etc2_unpack_signed_rg11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1) + etc2_unpack_rgb8_punchthrough_alpha1(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1) + etc2_unpack_srgb8_punchthrough_alpha1(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); +} + + + +static void +fetch_etc1_rgb8(const GLubyte *map, + GLint rowStride, GLint i, GLint j, + GLfloat *texel) +{ + struct etc1_block block; + GLubyte dst[3]; + const GLubyte *src; + + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc1_parse_block(&block, src); + etc1_fetch_texel(&block, i % 4, j % 4, dst); + + texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); + texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); + texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); + texel[ACOMP] = 1.0f; +} + + +static void +fetch_etc2_rgb8(const GLubyte *map, + GLint rowStride, GLint i, GLint j, GLfloat *texel) { struct etc2_block block; uint8_t dst[3]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; - etc2_rgb8_parse_block(&block, src); - etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst); + etc2_rgb8_parse_block(&block, src, + false /* punchthrough_alpha */); + etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, + false /* punchthrough_alpha */); texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); @@ -1029,36 +1293,36 @@ _mesa_fetch_texel_2d_f_etc2_rgb8(const struct swrast_texture_image *texImage, texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_srgb8(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_srgb8(const GLubyte *map, + GLint rowStride, GLint i, GLint j, GLfloat *texel) { struct etc2_block block; uint8_t dst[3]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; - etc2_rgb8_parse_block(&block, src); - etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst); + etc2_rgb8_parse_block(&block, src, + false /* punchthrough_alpha */); + etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, + false /* punchthrough_alpha */); - texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]); - texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]); - texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_rgba8_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_rgba8_eac(const GLubyte *map, + GLint rowStride, GLint i, GLint j, GLfloat *texel) { struct etc2_block block; uint8_t dst[4]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; etc2_rgba8_parse_block(&block, src); etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); @@ -1069,38 +1333,34 @@ _mesa_fetch_texel_2d_f_etc2_rgba8_eac(const struct swrast_texture_image *texImag texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); } -void -_mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac(const struct - swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel) +static void +fetch_etc2_srgb8_alpha8_eac(const GLubyte *map, + GLint rowStride, GLint i, GLint j, GLfloat *texel) { struct etc2_block block; uint8_t dst[4]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; etc2_rgba8_parse_block(&block, src); etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); - texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]); - texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]); - texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); } -void -_mesa_fetch_texel_2d_f_etc2_r11_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_r11_eac(const GLubyte *map, + GLint rowStride, GLint i, GLint j, GLfloat *texel) { struct etc2_block block; GLushort dst; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; etc2_r11_parse_block(&block, src); etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst); @@ -1111,18 +1371,15 @@ _mesa_fetch_texel_2d_f_etc2_r11_eac(const struct swrast_texture_image *texImage, texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_rg11_eac(const struct - swrast_texture_image *texImage, - GLint i, GLint j, - GLint k, GLfloat *texel) +static void +fetch_etc2_rg11_eac(const GLubyte *map, + GLint rowStride, GLint i, GLint j, GLfloat *texel) { struct etc2_block block; GLushort dst[2]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; /* red component */ etc2_r11_parse_block(&block, src); @@ -1138,16 +1395,15 @@ _mesa_fetch_texel_2d_f_etc2_rg11_eac(const struct texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_signed_r11_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_signed_r11_eac(const GLubyte *map, + GLint rowStride, GLint i, GLint j, GLfloat *texel) { struct etc2_block block; GLushort dst; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; etc2_r11_parse_block(&block, src); etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst); @@ -1158,16 +1414,15 @@ _mesa_fetch_texel_2d_f_etc2_signed_r11_eac(const struct swrast_texture_image *te texel[ACOMP] = 1.0f; } -void -_mesa_fetch_texel_2d_f_etc2_signed_rg11_eac(const struct swrast_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) +static void +fetch_etc2_signed_rg11_eac(const GLubyte *map, + GLint rowStride, GLint i, GLint j, GLfloat *texel) { struct etc2_block block; GLushort dst[2]; const uint8_t *src; - src = texImage->Map + - (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; /* red component */ etc2_r11_parse_block(&block, src); @@ -1183,64 +1438,76 @@ _mesa_fetch_texel_2d_f_etc2_signed_rg11_eac(const struct swrast_texture_image *t texel[ACOMP] = 1.0f; } -/** - * Decode texture data in any one of following formats: - * `MESA_FORMAT_ETC2_RGB8` - * `MESA_FORMAT_ETC2_SRGB8` - * `MESA_FORMAT_ETC2_RGBA8_EAC` - * `MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC` - * `MESA_FORMAT_ETC2_R11_EAC` - * `MESA_FORMAT_ETC2_RG11_EAC` - * `MESA_FORMAT_ETC2_SIGNED_R11_EAC` - * `MESA_FORMAT_ETC2_SIGNED_RG11_EAC` - * - * The size of the source data must be a multiple of the ETC2 block size - * even if the texture image's dimensions are not aligned to 4. - * - * \param src_width in pixels - * \param src_height in pixels - * \param dst_stride in bytes - */ +static void +fetch_etc2_rgb8_punchthrough_alpha1(const GLubyte *map, + GLint rowStride, GLint i, GLint j, + GLfloat *texel) +{ + struct etc2_block block; + uint8_t dst[4]; + const uint8_t *src; -void -_mesa_unpack_etc2_format(uint8_t *dst_row, - unsigned dst_stride, - const uint8_t *src_row, - unsigned src_stride, - unsigned src_width, - unsigned src_height, - gl_format format) + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc2_rgb8_parse_block(&block, src, + true /* punchthrough alpha */); + etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, + true /* punchthrough alpha */); + texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); + texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); + texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); + texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); +} + +static void +fetch_etc2_srgb8_punchthrough_alpha1(const GLubyte *map, + GLint rowStride, + GLint i, GLint j, GLfloat *texel) { - if (format == MESA_FORMAT_ETC2_RGB8) - etc2_unpack_rgb8(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SRGB8) - etc2_unpack_srgb8(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_RGBA8_EAC) - etc2_unpack_rgba8(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC) - etc2_unpack_srgb8_alpha8(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_R11_EAC) - etc2_unpack_r11(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_RG11_EAC) - etc2_unpack_rg11(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SIGNED_R11_EAC) - etc2_unpack_signed_r11(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); - else if (format == MESA_FORMAT_ETC2_SIGNED_RG11_EAC) - etc2_unpack_signed_rg11(dst_row, dst_stride, - src_row, src_stride, - src_width, src_height); + struct etc2_block block; + uint8_t dst[4]; + const uint8_t *src; + + src = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc2_rgb8_parse_block(&block, src, + true /* punchthrough alpha */); + etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, + true /* punchthrough alpha */); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); + texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); +} + + +compressed_fetch_func +_mesa_get_etc_fetch_func(mesa_format format) +{ + switch (format) { + case MESA_FORMAT_ETC1_RGB8: + return fetch_etc1_rgb8; + case MESA_FORMAT_ETC2_RGB8: + return fetch_etc2_rgb8; + case MESA_FORMAT_ETC2_SRGB8: + return fetch_etc2_srgb8; + case MESA_FORMAT_ETC2_RGBA8_EAC: + return fetch_etc2_rgba8_eac; + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + return fetch_etc2_srgb8_alpha8_eac; + case MESA_FORMAT_ETC2_R11_EAC: + return fetch_etc2_r11_eac; + case MESA_FORMAT_ETC2_RG11_EAC: + return fetch_etc2_rg11_eac; + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + return fetch_etc2_signed_r11_eac; + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + return fetch_etc2_signed_rg11_eac; + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + return fetch_etc2_rgb8_punchthrough_alpha1; + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: + return fetch_etc2_srgb8_punchthrough_alpha1; + default: + return NULL; + } }