Evas DDS: Implement support for DXT4 and DXT5
authorJean-Philippe Andre <jp.andre@samsung.com>
Thu, 19 Jun 2014 09:01:46 +0000 (18:01 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Thu, 3 Jul 2014 02:37:48 +0000 (11:37 +0900)
src/modules/evas/loaders/dds/evas_image_load_dds.c
src/modules/evas/loaders/dds/s3tc.h
src/modules/evas/loaders/dds/s3tc_decoder.c

index 3311c2f..dc4fd62 100644 (file)
@@ -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();
      }
index 6341b79..91f05f0 100644 (file)
@@ -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
index f8ded4f..a3e09dc 100644 (file)
@@ -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);
+}