From 79ed3c45168d66245654acabd5ef9f3e714b15a7 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 19 Jun 2014 18:01:46 +0900 Subject: [PATCH] Evas DDS: Implement support for DXT4 and DXT5 --- .../evas/loaders/dds/evas_image_load_dds.c | 11 +++-- src/modules/evas/loaders/dds/s3tc.h | 2 + src/modules/evas/loaders/dds/s3tc_decoder.c | 47 +++++++++++++++++++ 3 files changed, 57 insertions(+), 3 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 3311c2f3b2..dc4fd629ba 100644 --- a/src/modules/evas/loaders/dds/evas_image_load_dds.c +++ b/src/modules/evas/loaders/dds/evas_image_load_dds.c @@ -254,7 +254,6 @@ 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; @@ -266,10 +265,8 @@ evas_image_load_file_head_dds(void *loader_data, prop->cspaces = cspaces_s3tc_dxt5; break; case FOURCC('D', 'X', '1', '0'): - loader->format = DX10; *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; FAIL(); -#endif default: // TODO: Implement decoding support for uncompressed formats FAIL(); @@ -363,6 +360,14 @@ evas_image_load_file_data_dds(void *loader_data, func = s3tc_decode_dxt3_rgba; prop->premul = EINA_TRUE; break; + case EVAS_COLORSPACE_RGBA_S3TC_DXT4: + func = s3tc_decode_dxt4_rgba; + prop->premul = EINA_FALSE; + break; + case EVAS_COLORSPACE_RGBA_S3TC_DXT5: + func = s3tc_decode_dxt5_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 6341b79d7d..91f05f0b5a 100644 --- a/src/modules/evas/loaders/dds/s3tc.h +++ b/src/modules/evas/loaders/dds/s3tc.h @@ -5,5 +5,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); +void s3tc_decode_dxt4_rgba(unsigned int *bgra, const unsigned char *s3tc); +void s3tc_decode_dxt5_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 f8ded4fea8..a3e09dc98e 100644 --- a/src/modules/evas/loaders/dds/s3tc_decoder.c +++ b/src/modules/evas/loaders/dds/s3tc_decoder.c @@ -60,6 +60,41 @@ _decode_alpha4(unsigned int *bgra, const unsigned char *s3tc) } } +static void +_decode_dxt_alpha(unsigned int *bgra, const unsigned char *s3tc) +{ + unsigned char a0 = s3tc[0]; + unsigned char a1 = s3tc[1]; + unsigned long long bits = 0ull; + unsigned char alpha[8]; + + for (int k = 5; k >= 0; k--) + bits = (bits << 8) | s3tc[k + 2]; + + alpha[0] = a0; + alpha[1] = a1; + + if (a0 > a1) + { + for (int k = 0; k < 6; k++) + alpha[2 + k] = ((6 - k) * a0 + (k + 1) * a1) / 7; + } + else + { + for (int k = 0; k < 4; k++) + alpha[2 + k] = ((4 - k) * a0 + (k + 1) * a1) / 5; + alpha[6] = 0; + alpha[7] = 255; + } + + for (int k = 0; k < 16; k++) + { + int index = (int) (bits & 0x7ull); + *bgra++ |= (alpha[index] << 24); + bits >>= 3; + } +} + void s3tc_decode_dxt1_rgb(unsigned int *bgra, const unsigned char *s3tc) { _decode_dxt1_rgb(bgra, s3tc, 0xFF000000, EINA_TRUE, EINA_FALSE); @@ -81,3 +116,15 @@ 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); } + +void s3tc_decode_dxt4_rgba(unsigned int *bgra, const unsigned char *s3tc) +{ + _decode_dxt1_rgb(bgra, s3tc + 8, 0x0, EINA_FALSE, EINA_FALSE); + _decode_dxt_alpha(bgra, s3tc); +} + +void s3tc_decode_dxt5_rgba(unsigned int *bgra, const unsigned char *s3tc) +{ + _decode_dxt1_rgb(bgra, s3tc + 8, 0x0, EINA_FALSE, EINA_FALSE); + _decode_dxt_alpha(bgra, s3tc); +}