From 69d910d52fb2c6a98a6658faa2efa9b95982e68b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Wed, 26 Nov 2014 14:24:57 +0100
Subject: wined3d: add DXT1 to B4G4R4A4, DXT1 to B5G5R5A1 and DXT3 to B4G4R4A4
 conversion.

---
 dlls/wined3d/dxtn.c    | 108 +++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/surface.c |  42 +++++++++++++++++++
 2 files changed, 150 insertions(+)

diff --git a/dlls/wined3d/dxtn.c b/dlls/wined3d/dxtn.c
index 6623e64..57da0df 100644
--- a/dlls/wined3d/dxtn.c
+++ b/dlls/wined3d/dxtn.c
@@ -64,6 +64,70 @@ static inline BOOL dxt1_to_x8r8g8b8(const BYTE *src, BYTE *dst, DWORD pitch_in,
     return TRUE;
 }
 
+static inline BOOL dxt1_to_x4r4g4b4(const BYTE *src, BYTE *dst, DWORD pitch_in,
+        DWORD pitch_out, unsigned int w, unsigned int h, BOOL alpha)
+{
+    unsigned int x, y;
+    DWORD color;
+
+    TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
+
+    for (y = 0; y < h; ++y)
+    {
+        WORD *dst_line = (WORD *)(dst + y * pitch_out);
+        for (x = 0; x < w; ++x)
+        {
+            /* pfetch_2d_texel_rgba_dxt1 doesn't correctly handle pitch */
+            pfetch_2d_texel_rgba_dxt1(0, src + (y / 4) * pitch_in + (x / 4) * 16,
+                                      x & 3, y & 3, &color);
+            if (alpha)
+            {
+                dst_line[x] = ((color & 0xf0000000) >> 16) | ((color & 0xf00000) >> 20) |
+                              ((color & 0xf000) >> 8) | ((color & 0xf0) << 4);
+            }
+            else
+            {
+                dst_line[x] = 0xf000  | ((color & 0xf00000) >> 20) |
+                              ((color & 0xf000) >> 8) | ((color & 0xf0) << 4);
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+static inline BOOL dxt1_to_x1r5g5b5(const BYTE *src, BYTE *dst, DWORD pitch_in,
+        DWORD pitch_out, unsigned int w, unsigned int h, BOOL alpha)
+{
+    unsigned int x, y;
+    DWORD color;
+
+    TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
+
+    for (y = 0; y < h; ++y)
+    {
+        WORD *dst_line = (WORD *)(dst + y * pitch_out);
+        for (x = 0; x < w; ++x)
+        {
+            /* pfetch_2d_texel_rgba_dxt1 doesn't correctly handle pitch */
+            pfetch_2d_texel_rgba_dxt1(0, src + (y / 4) * pitch_in + (x / 4) * 16,
+                                      x & 3, y & 3, &color);
+            if (alpha)
+            {
+                dst_line[x] = ((color & 0x80000000) >> 16) | ((color & 0xf80000) >> 19) |
+                              ((color & 0xf800) >> 6) | ((color & 0xf8) << 7);
+            }
+            else
+            {
+                dst_line[x] = 0x8000 | ((color & 0xf80000) >> 19) |
+                              ((color & 0xf800) >> 6) | ((color & 0xf8) << 7);
+            }
+        }
+    }
+
+    return TRUE;
+}
+
 static inline BOOL dxt3_to_x8r8g8b8(const BYTE *src, BYTE *dst, DWORD pitch_in,
         DWORD pitch_out, unsigned int w, unsigned int h, BOOL alpha)
 {
@@ -96,6 +160,38 @@ static inline BOOL dxt3_to_x8r8g8b8(const BYTE *src, BYTE *dst, DWORD pitch_in,
     return TRUE;
 }
 
+static inline BOOL dxt3_to_x4r4g4b4(const BYTE *src, BYTE *dst, DWORD pitch_in,
+        DWORD pitch_out, unsigned int w, unsigned int h, BOOL alpha)
+{
+    unsigned int x, y;
+    DWORD color;
+
+    TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
+
+    for (y = 0; y < h; ++y)
+    {
+        WORD *dst_line = (WORD *)(dst + y * pitch_out);
+        for (x = 0; x < w; ++x)
+        {
+            /* pfetch_2d_texel_rgba_dxt3 doesn't correctly handle pitch */
+            pfetch_2d_texel_rgba_dxt3(0, src + (y / 4) * pitch_in + (x / 4) * 16,
+                                      x & 3, y & 3, &color);
+            if (alpha)
+            {
+                dst_line[x] = ((color & 0xf0000000) >> 16) | ((color & 0xf00000) >> 20) |
+                              ((color & 0xf000) >> 8) | ((color & 0xf0) << 4);
+            }
+            else
+            {
+                dst_line[x] = 0xf000  | ((color & 0xf00000) >> 20) |
+                              ((color & 0xf000) >> 8) | ((color & 0xf0) << 4);
+            }
+        }
+    }
+
+    return TRUE;
+}
+
 static inline BOOL dxt5_to_x8r8g8b8(const BYTE *src, BYTE *dst, DWORD pitch_in,
         DWORD pitch_out, unsigned int w, unsigned int h, BOOL alpha)
 {
@@ -232,6 +328,14 @@ BOOL wined3d_dxt1_decode(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch
             return dxt1_to_x8r8g8b8(src, dst, pitch_in, pitch_out, w, h, TRUE);
         case WINED3DFMT_B8G8R8X8_UNORM:
             return dxt1_to_x8r8g8b8(src, dst, pitch_in, pitch_out, w, h, FALSE);
+        case WINED3DFMT_B4G4R4A4_UNORM:
+            return dxt1_to_x4r4g4b4(src, dst, pitch_in, pitch_out, w, h, TRUE);
+        case WINED3DFMT_B4G4R4X4_UNORM:
+            return dxt1_to_x4r4g4b4(src, dst, pitch_in, pitch_out, w, h, FALSE);
+        case WINED3DFMT_B5G5R5A1_UNORM:
+            return dxt1_to_x1r5g5b5(src, dst, pitch_in, pitch_out, w, h, TRUE);
+        case WINED3DFMT_B5G5R5X1_UNORM:
+            return dxt1_to_x1r5g5b5(src, dst, pitch_in, pitch_out, w, h, FALSE);
         default:
             break;
     }
@@ -252,6 +356,10 @@ BOOL wined3d_dxt3_decode(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch
             return dxt3_to_x8r8g8b8(src, dst, pitch_in, pitch_out, w, h, TRUE);
         case WINED3DFMT_B8G8R8X8_UNORM:
             return dxt3_to_x8r8g8b8(src, dst, pitch_in, pitch_out, w, h, FALSE);
+        case WINED3DFMT_B4G4R4A4_UNORM:
+            return dxt3_to_x4r4g4b4(src, dst, pitch_in, pitch_out, w, h, TRUE);
+        case WINED3DFMT_B4G4R4X4_UNORM:
+            return dxt3_to_x4r4g4b4(src, dst, pitch_in, pitch_out, w, h, FALSE);
         default:
             break;
     }
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 4fc917d..689fc0e 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -2428,6 +2428,30 @@ static void convert_dxt1_x8r8g8b8(const BYTE *src, BYTE *dst,
     wined3d_dxt1_decode(src, dst, pitch_in, pitch_out, WINED3DFMT_B8G8R8X8_UNORM, w, h);
 }
 
+static void convert_dxt1_a4r4g4b4(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    wined3d_dxt1_decode(src, dst, pitch_in, pitch_out, WINED3DFMT_B4G4R4A4_UNORM, w, h);
+}
+
+static void convert_dxt1_x4r4g4b4(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    wined3d_dxt1_decode(src, dst, pitch_in, pitch_out, WINED3DFMT_B4G4R4X4_UNORM, w, h);
+}
+
+static void convert_dxt1_a1r5g5b5(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    wined3d_dxt1_decode(src, dst, pitch_in, pitch_out, WINED3DFMT_B5G5R5A1_UNORM, w, h);
+}
+
+static void convert_dxt1_x1r5g5b5(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    wined3d_dxt1_decode(src, dst, pitch_in, pitch_out, WINED3DFMT_B5G5R5X1_UNORM, w, h);
+}
+
 static void convert_dxt3_a8r8g8b8(const BYTE *src, BYTE *dst,
         DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
 {
@@ -2440,6 +2464,18 @@ static void convert_dxt3_x8r8g8b8(const BYTE *src, BYTE *dst,
     wined3d_dxt3_decode(src, dst, pitch_in, pitch_out, WINED3DFMT_B8G8R8X8_UNORM, w, h);
 }
 
+static void convert_dxt3_a4r4g4b4(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    wined3d_dxt3_decode(src, dst, pitch_in, pitch_out, WINED3DFMT_B4G4R4A4_UNORM, w, h);
+}
+
+static void convert_dxt3_x4r4g4b4(const BYTE *src, BYTE *dst,
+        DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
+{
+    wined3d_dxt3_decode(src, dst, pitch_in, pitch_out, WINED3DFMT_B4G4R4X4_UNORM, w, h);
+}
+
 static void convert_dxt5_a8r8g8b8(const BYTE *src, BYTE *dst,
         DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
 {
@@ -2521,8 +2557,14 @@ static const struct d3dfmt_converter_desc dxtn_converters[] =
     /* decode DXT */
     {WINED3DFMT_DXT1,           WINED3DFMT_B8G8R8A8_UNORM,  convert_dxt1_a8r8g8b8},
     {WINED3DFMT_DXT1,           WINED3DFMT_B8G8R8X8_UNORM,  convert_dxt1_x8r8g8b8},
+    {WINED3DFMT_DXT1,           WINED3DFMT_B4G4R4A4_UNORM,  convert_dxt1_a4r4g4b4},
+    {WINED3DFMT_DXT1,           WINED3DFMT_B4G4R4X4_UNORM,  convert_dxt1_x4r4g4b4},
+    {WINED3DFMT_DXT1,           WINED3DFMT_B5G5R5A1_UNORM,  convert_dxt1_a1r5g5b5},
+    {WINED3DFMT_DXT1,           WINED3DFMT_B5G5R5X1_UNORM,  convert_dxt1_x1r5g5b5},
     {WINED3DFMT_DXT3,           WINED3DFMT_B8G8R8A8_UNORM,  convert_dxt3_a8r8g8b8},
     {WINED3DFMT_DXT3,           WINED3DFMT_B8G8R8X8_UNORM,  convert_dxt3_x8r8g8b8},
+    {WINED3DFMT_DXT3,           WINED3DFMT_B4G4R4A4_UNORM,  convert_dxt3_a4r4g4b4},
+    {WINED3DFMT_DXT3,           WINED3DFMT_B4G4R4X4_UNORM,  convert_dxt3_x4r4g4b4},
     {WINED3DFMT_DXT5,           WINED3DFMT_B8G8R8A8_UNORM,  convert_dxt5_a8r8g8b8},
     {WINED3DFMT_DXT5,           WINED3DFMT_B8G8R8X8_UNORM,  convert_dxt5_x8r8g8b8},
 
-- 
2.2.1