diff options
author | Jean-Philippe Andre <jp.andre@samsung.com> | 2014-04-30 14:10:33 +0900 |
---|---|---|
committer | Jean-Philippe Andre <jp.andre@samsung.com> | 2014-05-27 12:21:30 +0900 |
commit | 5582ee016ef031006e4734e561e518041bb9c65e (patch) | |
tree | cfda2690d9a96c46d885572ecc061f7a024ad92d /src/static_libs | |
parent | 9550b653480f7a7a3af02c7e7712dc9e081605f4 (diff) | |
download | efl-5582ee016ef031006e4734e561e518041bb9c65e.tar.gz |
Evas rg_etc2: Add ETC2 decoding routines
Simple implementation of the OpenGL ES 3.0 specification, annex C.1.
Diffstat (limited to 'src/static_libs')
-rw-r--r-- | src/static_libs/rg_etc/rg_etc1.c | 2 | ||||
-rw-r--r-- | src/static_libs/rg_etc/rg_etc1.h | 6 | ||||
-rw-r--r-- | src/static_libs/rg_etc/rg_etc2.c | 247 |
3 files changed, 254 insertions, 1 deletions
diff --git a/src/static_libs/rg_etc/rg_etc1.c b/src/static_libs/rg_etc/rg_etc1.c index f768eaab83..bb825e685a 100644 --- a/src/static_libs/rg_etc/rg_etc1.c +++ b/src/static_libs/rg_etc/rg_etc1.c @@ -1164,7 +1164,7 @@ rg_etc1_block_subblock_color5_delta3_diff_get(unsigned int dst[4], if (!(table_idx < cETC1IntenModifierValues)) { fprintf(stderr, "table_idx %i < %i\n", table_idx, cETC1IntenModifierValues); - return 0; + return 0; } success = rg_etc1_block_color5_delta3_component_unpack(&r, &g, &b, packed_color5, packed_delta3, 1); diff --git a/src/static_libs/rg_etc/rg_etc1.h b/src/static_libs/rg_etc/rg_etc1.h index af887013a5..43a86aa3b0 100644 --- a/src/static_libs/rg_etc/rg_etc1.h +++ b/src/static_libs/rg_etc/rg_etc1.h @@ -36,6 +36,12 @@ void rg_etc1_pack_block_init(); // pack_etc1_block() does not currently support "perceptual" colorspace metrics - it primarily optimizes for RGB RMSE. unsigned int rg_etc1_pack_block(void* pETC1_block, const unsigned int* pSrc_pixels_rgba, rg_etc1_pack_params *pack_params); +// ETC2 support: RGB8_ETC2 +void rg_etc2_rgb8_decode_block(const uint8_t *etc_block, uint32_t *bgra); + +// ETC2 support: RGBA8_ETC2_EAC +//void rg_etc2_rgba8_decode_block(const uint8_t *etc_block, uint32_t *bgra); + //------------------------------------------------------------------------------ // // rg_etc1 uses the ZLIB license: diff --git a/src/static_libs/rg_etc/rg_etc2.c b/src/static_libs/rg_etc/rg_etc2.c new file mode 100644 index 0000000000..92044026e4 --- /dev/null +++ b/src/static_libs/rg_etc/rg_etc2.c @@ -0,0 +1,247 @@ +/* +Copyright (C) 2014 Jean-Philippe ANDRE + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * ETC2 decoding functions, reimplemented from scratch based on the + * OpenGL ES 3.0 spec (annex C.1). + * + * @author Jean-Philippe ANDRE + * @license BSD-2 with advertisement clause + */ + +#include <Eina.h> +#include "rg_etc1.h" + +void rg_etc2_rgb8_decode_block(const uint8_t *etc_block, uint32_t *bgra); +void rg_etc2_rgba8_decode_block(const uint8_t *etc_block, uint32_t *bgra); + +typedef const uint8_t etc_block; + +// For T and H modes +static const int kDistances[8] = { + 3, 6, 11, 16, 23, 32, 41, 64 +}; + +// For differential mode +static const int kSigned3bit[8] = { + 0, 1, 2, 3, -4, -3, -2, -1 +}; + +// Use with static constants so the compiler can optimize everything +#define BITS(byteval, lowbit, highbit) \ + (((byteval) >> (lowbit)) & ((1 << ((highbit) - (lowbit) + 1)) - 1)) + +#define BIT(byteval, bit) \ + (((byteval) >> (bit)) & 0x1) + +// Clamps only if value is > 255 +#define CLAMPDOWN(a) ({ int _z = (a); ((_z <= 255) ? _z : 255); }) + +// Clamps only if value is < 0 +#define CLAMPUP(a) ({ int _z = (a); ((_z >= 0) ? _z : 0); }) + +// Real clamp +#define CLAMP(a) ({ int _b = (a); (((_b) >= 0) ? (((_b) < 256) ? (_b) : 255) : 0); }) + +// Write a BGRA value for output to Evas +#define BGRA(r,g,b,a) ((a << 24) | (r << 16) | (g << 8) | b) + +#define _4to8(a) ({ int _a = (a) & ((1 << 4) - 1); ((_a << 4) | (_a & 0xf)); }) +#define _5to8(a) ({ int _a = (a) & ((1 << 5) - 1); ((_a << 3) | ((_a >> 2) & 0x7)); }) +#define _6to8(a) ({ int _a = (a) & ((1 << 6) - 1); ((_a << 2) | ((_a >> 4) & 0x3)); }) +#define _7to8(a) ({ int _a = (a) & ((1 << 7) - 1); ((_a << 1) | ((_a >> 6) & 0x1)); }) + + +static inline void +_T_mode_color_read(const uint8_t *etc, uint32_t *paint_colors, int alpha) +{ + // 4 bit colors + const int r1_4 = (BITS(etc[0], 3, 4) << 2) | BITS(etc[0], 0, 1); + const int g1_4 = BITS(etc[1], 4, 7); + const int b1_4 = BITS(etc[1], 0, 3); + const int r2_4 = BITS(etc[2], 4, 7); + const int g2_4 = BITS(etc[2], 0, 3); + const int b2_4 = BITS(etc[3], 4, 7); + + // Distance index + const int didx = (BITS(etc[3], 2, 3) << 1) | BIT(etc[3], 0); + const int d = kDistances[didx]; + + // Write out paint colors for T mode + paint_colors[0] = BGRA(_4to8(r1_4), _4to8(g1_4), _4to8(b1_4), alpha); + paint_colors[1] = BGRA(CLAMPDOWN(_4to8(r2_4) + d), + CLAMPDOWN(_4to8(g2_4) + d), + CLAMPDOWN(_4to8(b2_4) + d), + alpha); + paint_colors[2] = BGRA(_4to8(r2_4), _4to8(g2_4), _4to8(b2_4), alpha); + paint_colors[3] = BGRA(CLAMPUP(_4to8(r2_4) - d), + CLAMPUP(_4to8(g2_4) - d), + CLAMPUP(_4to8(b2_4) - d), + alpha); +} + +static inline void +_H_mode_color_read(const uint8_t *etc, uint32_t *paint_colors, int alpha) +{ + // 4 bit colors + const int r1_4 = BITS(etc[0], 3, 6); + const int g1_4 = (BITS(etc[0], 0, 2) << 1) | (BIT(etc[1], 4)); + const int b1_4 = (BIT(etc[1], 3) << 3) | (BITS(etc[1], 0, 1) << 1) | (BIT(etc[2], 7)); + const int r2_4 = BITS(etc[2], 3, 6); + const int g2_4 = (BITS(etc[2], 0, 2) << 1) | (BIT(etc[3], 7)); + const int b2_4 = BITS(etc[3], 3, 6); + + // Distance index + const int basecol1 = (_4to8(r1_4) << 16) | (_4to8(g1_4) << 8) | _4to8(b1_4); + const int basecol2 = (_4to8(r2_4) << 16) | (_4to8(g2_4) << 8) | _4to8(b2_4); + const int didx = + (BIT(etc[3], 2) << 2) | + (BIT(etc[3], 0) << 1) | + ((basecol1 >= basecol2) ? 1 : 0); + const int d = kDistances[didx]; + + // Write out paint colors for H mode + paint_colors[0] = BGRA(CLAMPDOWN(_4to8(r1_4) + d), + CLAMPDOWN(_4to8(g1_4) + d), + CLAMPDOWN(_4to8(b1_4) + d), + alpha); + paint_colors[1] = BGRA(CLAMPUP(_4to8(r1_4) - d), + CLAMPUP(_4to8(g1_4) - d), + CLAMPUP(_4to8(b1_4) - d), + alpha); + paint_colors[2] = BGRA(CLAMPDOWN(_4to8(r2_4) + d), + CLAMPDOWN(_4to8(g2_4) + d), + CLAMPDOWN(_4to8(b2_4) + d), + alpha); + paint_colors[3] = BGRA(CLAMPUP(_4to8(r2_4) - d), + CLAMPUP(_4to8(g2_4) - d), + CLAMPUP(_4to8(b2_4) - d), + alpha); +} + +static inline void +_planar_mode_color_read(const uint8_t *etc, uint32_t *bgra, int alpha) +{ + // RO: Bits 57-62 + const int RO = _6to8(BITS(etc[0], 1, 6)); + // GO: Bits 49-54,56 + const int GO = _7to8((BIT(etc[0], 0) << 6) | (BITS(etc[1], 1, 6))); + // BO: Bits 39,40-41,43-44,48 + const int BO = _6to8((BIT(etc[1], 0) << 5) | (BITS(etc[2], 3, 4) << 3) | (BITS(etc[2], 0, 1) << 1) | BIT(etc[3], 7)); + // RH: Bits 32,34-38 + const int RH = _6to8((BITS(etc[3], 2, 6) << 1) | BIT(etc[3], 0)); + // GH: Bits 25-31 + const int GH = _7to8(BITS(etc[4], 1, 7)); + // BH: Bits 19-23,24 + const int BH = _6to8((BIT(etc[4], 0) << 5) | (BITS(etc[5], 3, 7))); + // RV: Bits 13-15,16-18 + const int RV = _6to8((BITS(etc[5], 0, 2) << 3) | (BITS(etc[6], 5, 7))); + // GV: Bits 6-7,8-12 + const int GV = _7to8((BITS(etc[6], 0, 4) << 2) | (BITS(etc[7], 6, 7))); + // BV: Bits 0-5 + const int BV = _6to8(BITS(etc[7], 0, 5)); + + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + { + // Formulas straight from the spec + const int R = CLAMP(((x * (RH - RO)) + y * (RV - RO) + 4 * RO + 2) >> 2); + const int G = CLAMP(((x * (GH - GO)) + y * (GV - GO) + 4 * GO + 2) >> 2); + const int B = CLAMP(((x * (BH - BO)) + y * (BV - BO) + 4 * BO + 2) >> 2); + *bgra++ = BGRA(R, G, B, alpha); + } +} + +void +rg_etc2_rgb8_decode_block(const uint8_t *etc, uint32_t *bgra) +{ + // Check differential mode bit + if ((etc[3] & 0x2) == 0) + goto etc1; + + // Read R,G,B + const int R = BITS(etc[0], 3, 7); + const int dR = kSigned3bit[BITS(etc[0], 0, 2)]; + const int G = BITS(etc[1], 3, 7); + const int dG = kSigned3bit[BITS(etc[1], 0, 2)]; + const int B = BITS(etc[2], 3, 7); + const int dB = kSigned3bit[BITS(etc[2], 0, 2)]; + uint32_t paint_colors[4]; + + if ((R + dR) < 0 || (R + dR) >= 32) + { + // T mode + _T_mode_color_read(etc, paint_colors, 255); + goto th_mode; + } + if ((G + dG) < 0 || (G + dG) >= 32) + { + // H mode + _H_mode_color_read(etc, paint_colors, 255); + goto th_mode; + } + if ((B + dB) < 0 || (B + dB) >= 32) + { + // Planar mode + _planar_mode_color_read(etc, bgra, 255); + return; + } + +etc1: + // Valid differential mode or individual mode: ETC1 + if (!rg_etc1_unpack_block(etc, bgra, 0)) + fprintf(stderr, "ETC2: Something very strange is happening here!\n"); + return; + +th_mode: + // Common code for modes T and H. + + // a,b,c,d + bgra[ 0] = paint_colors[(BIT(etc[5], 0) << 1) | (BIT(etc[7], 0))]; + bgra[ 4] = paint_colors[(BIT(etc[5], 1) << 1) | (BIT(etc[7], 1))]; + bgra[ 8] = paint_colors[(BIT(etc[5], 2) << 1) | (BIT(etc[7], 2))]; + bgra[12] = paint_colors[(BIT(etc[5], 3) << 1) | (BIT(etc[7], 3))]; + + // e,f,g,h + bgra[ 1] = paint_colors[(BIT(etc[5], 4) << 1) | (BIT(etc[7], 4))]; + bgra[ 5] = paint_colors[(BIT(etc[5], 5) << 1) | (BIT(etc[7], 5))]; + bgra[ 9] = paint_colors[(BIT(etc[5], 6) << 1) | (BIT(etc[7], 6))]; + bgra[13] = paint_colors[(BIT(etc[5], 7) << 1) | (BIT(etc[7], 7))]; + + // i,j,k,l + bgra[ 2] = paint_colors[(BIT(etc[4], 0) << 1) | (BIT(etc[6], 0))]; + bgra[ 6] = paint_colors[(BIT(etc[4], 1) << 1) | (BIT(etc[6], 1))]; + bgra[10] = paint_colors[(BIT(etc[4], 2) << 1) | (BIT(etc[6], 2))]; + bgra[14] = paint_colors[(BIT(etc[4], 3) << 1) | (BIT(etc[6], 3))]; + + // m,n,o,p + bgra[ 3] = paint_colors[(BIT(etc[4], 4) << 1) | (BIT(etc[6], 4))]; + bgra[ 7] = paint_colors[(BIT(etc[4], 5) << 1) | (BIT(etc[6], 5))]; + bgra[11] = paint_colors[(BIT(etc[4], 6) << 1) | (BIT(etc[6], 6))]; + bgra[15] = paint_colors[(BIT(etc[4], 7) << 1) | (BIT(etc[6], 7))]; + return; +} |