From d9d0ff2088e4b554caef52e2a5b6d522a5b0f42d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 19 Jun 2014 17:52:25 +0900 Subject: [PATCH] Evas DDS: Implement decoding of DXT2 and DXT3 --- .../evas/loaders/dds/evas_image_load_dds.c | 18 ++++--- src/modules/evas/loaders/dds/s3tc.h | 2 + src/modules/evas/loaders/dds/s3tc_decoder.c | 54 +++++++++++++------ 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/modules/evas/loaders/dds/evas_image_load_dds.c b/src/modules/evas/loaders/dds/evas_image_load_dds.c index db2b9cc294..3311c2f3b2 100644 --- a/src/modules/evas/loaders/dds/evas_image_load_dds.c +++ b/src/modules/evas/loaders/dds/evas_image_load_dds.c @@ -34,8 +34,6 @@ struct _Evas_Loader_Internal unsigned int g_mask; unsigned int b_mask; unsigned int a_mask; - - Eina_Bool has_alpha : 1; // TODO: check mipmaps to load faster a small image :) } pf; // pixel format }; @@ -159,7 +157,7 @@ _dword_read(const char **m) return val; } -#define FAIL() do { fprintf(stderr, "DDS: ERROR at %s:%d", \ +#define FAIL() do { fprintf(stderr, "DDS: ERROR at %s:%d\n", \ __FUNCTION__, __LINE__); goto on_error; } while (0) static Eina_Bool @@ -228,7 +226,6 @@ evas_image_load_file_head_dds(void *loader_data, if (!(loader->pf.flags & DDPF_FOURCC)) FAIL(); // Unsupported (uncompressed formats may not have a FOURCC) loader->pf.fourcc = _dword_read(&m); - loader->pf.has_alpha = EINA_TRUE; loader->block_size = 16; switch (loader->pf.fourcc) { @@ -238,7 +235,6 @@ evas_image_load_file_head_dds(void *loader_data, { prop->alpha = EINA_FALSE; prop->cspaces = cspaces_s3tc_dxt1_rgb; - loader->pf.has_alpha = EINA_FALSE; loader->format = EVAS_COLORSPACE_RGB_S3TC_DXT1; } else @@ -248,7 +244,6 @@ evas_image_load_file_head_dds(void *loader_data, loader->format = EVAS_COLORSPACE_RGBA_S3TC_DXT1; } break; -#if 0 case FOURCC('D', 'X', 'T', '2'): loader->format = EVAS_COLORSPACE_RGBA_S3TC_DXT2; prop->alpha = EINA_TRUE; @@ -259,6 +254,7 @@ evas_image_load_file_head_dds(void *loader_data, prop->alpha = EINA_TRUE; prop->cspaces = cspaces_s3tc_dxt5; break; +#if 0 case FOURCC('D', 'X', 'T', '4'): loader->format = EVAS_COLORSPACE_RGBA_S3TC_DXT4; prop->alpha = EINA_TRUE; @@ -353,9 +349,19 @@ evas_image_load_file_data_dds(void *loader_data, { case EVAS_COLORSPACE_RGB_S3TC_DXT1: func = s3tc_decode_dxt1_rgb; + prop->premul = EINA_FALSE; break; case EVAS_COLORSPACE_RGBA_S3TC_DXT1: func = s3tc_decode_dxt1_rgba; + prop->premul = EINA_FALSE; + break; + case EVAS_COLORSPACE_RGBA_S3TC_DXT2: + func = s3tc_decode_dxt2_rgba; + prop->premul = EINA_FALSE; + break; + case EVAS_COLORSPACE_RGBA_S3TC_DXT3: + func = s3tc_decode_dxt3_rgba; + prop->premul = EINA_TRUE; break; default: FAIL(); diff --git a/src/modules/evas/loaders/dds/s3tc.h b/src/modules/evas/loaders/dds/s3tc.h index a2efdeb47b..6341b79d7d 100644 --- a/src/modules/evas/loaders/dds/s3tc.h +++ b/src/modules/evas/loaders/dds/s3tc.h @@ -3,5 +3,7 @@ void s3tc_decode_dxt1_rgb(unsigned int *bgra, const unsigned char *s3tc); void s3tc_decode_dxt1_rgba(unsigned int *bgra, const unsigned char *s3tc); +void s3tc_decode_dxt2_rgba(unsigned int *bgra, const unsigned char *s3tc); +void s3tc_decode_dxt3_rgba(unsigned int *bgra, const unsigned char *s3tc); #endif // EFL_S3TC_H diff --git a/src/modules/evas/loaders/dds/s3tc_decoder.c b/src/modules/evas/loaders/dds/s3tc_decoder.c index 30cd8ad795..f8ded4fea8 100644 --- a/src/modules/evas/loaders/dds/s3tc_decoder.c +++ b/src/modules/evas/loaders/dds/s3tc_decoder.c @@ -10,15 +10,11 @@ ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \ ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000))) -static inline unsigned int -_rgb565_to_rgba8888(unsigned short s) -{ - return 0xFF000000 | CONVERT_RGB_565_TO_RGB_888(s); -} +#define ALPHA4(a) (((a) << 4) | (a)) static void _decode_dxt1_rgb(unsigned int *bgra, const unsigned char *s3tc, - Eina_Bool alpha) + unsigned int amask, Eina_Bool dxt1, Eina_Bool alpha) { unsigned short color0, color1; unsigned int colors[4]; @@ -27,18 +23,18 @@ _decode_dxt1_rgb(unsigned int *bgra, const unsigned char *s3tc, color0 = s3tc[0] | (s3tc[1] << 8); color1 = s3tc[2] | (s3tc[3] << 8); - colors[0] = _rgb565_to_rgba8888(color0); - colors[1] = _rgb565_to_rgba8888(color1); - if (color0 > color1) + colors[0] = amask | CONVERT_RGB_565_TO_RGB_888(color0); + colors[1] = amask | CONVERT_RGB_565_TO_RGB_888(color1); + if (!dxt1 || (color0 > color1)) { // This is what's not supported by S2TC. - colors[2] = 0xFF000000 | INTERP_RGB_256((2*256)/3, colors[0], colors[1]); - colors[3] = 0xFF000000 | INTERP_RGB_256((1*256)/3, colors[0], colors[1]); + colors[2] = amask | INTERP_RGB_256((2*256)/3, colors[0], colors[1]); + colors[3] = amask | INTERP_RGB_256((1*256)/3, colors[0], colors[1]); } else { - colors[2] = 0xFF000000 | INTERP_RGB_256(128, colors[0], colors[1]); - colors[3] = (alpha ? 0x00000000 : 0xFF000000); + colors[2] = amask | INTERP_RGB_256(128, colors[0], colors[1]); + colors[3] = (alpha ? 0x00000000 : amask); } bits = s3tc[4] + ((s3tc[5] + ((s3tc[6] + (s3tc[7] << 8)) << 8)) << 8); @@ -46,18 +42,42 @@ _decode_dxt1_rgb(unsigned int *bgra, const unsigned char *s3tc, for (int i = 0; i < 4; i++) { int idx = bits & 0x3; - bits >>= 2; - bgra[(j * 4) + i] = colors[idx]; + bits >>= 2; } } +static void +_decode_alpha4(unsigned int *bgra, const unsigned char *s3tc) +{ + for (int k = 0; k < 16; k += 2) + { + unsigned int a0 = ALPHA4((*s3tc) & 0x0F); + unsigned int a1 = ALPHA4(((*s3tc) & 0xF0) >> 4); + *bgra++ |= (a0 << 24); + *bgra++ |= (a1 << 24); + s3tc++; + } +} + void s3tc_decode_dxt1_rgb(unsigned int *bgra, const unsigned char *s3tc) { - _decode_dxt1_rgb(bgra, s3tc, EINA_FALSE); + _decode_dxt1_rgb(bgra, s3tc, 0xFF000000, EINA_TRUE, EINA_FALSE); } void s3tc_decode_dxt1_rgba(unsigned int *bgra, const unsigned char *s3tc) { - _decode_dxt1_rgb(bgra, s3tc, EINA_TRUE); + _decode_dxt1_rgb(bgra, s3tc, 0xFF000000, EINA_TRUE, EINA_TRUE); +} + +void s3tc_decode_dxt2_rgba(unsigned int *bgra, const unsigned char *s3tc) +{ + _decode_dxt1_rgb(bgra, s3tc + 8, 0x0, EINA_FALSE, EINA_FALSE); + _decode_alpha4(bgra, s3tc); +} + +void s3tc_decode_dxt3_rgba(unsigned int *bgra, const unsigned char *s3tc) +{ + _decode_dxt1_rgb(bgra, s3tc + 8, 0x0, EINA_FALSE, EINA_FALSE); + _decode_alpha4(bgra, s3tc); }