[WINESYNC]d3dx9_36: add DXTn support
authorwinesync <ros-dev@reactos.org>
Sat, 4 Jan 2020 01:09:33 +0000 (02:09 +0100)
committerJérôme Gardou <zefklop@users.noreply.github.com>
Wed, 26 Feb 2020 17:19:18 +0000 (18:19 +0100)
wine-staging patch by Christian Costa <titan.costa@gmail.com>

dll/directx/wine/d3dx9_36/d3dx9.cmake
dll/directx/wine/d3dx9_36/surface.c
modules/rostests/winetests/d3dx9_36/surface.c
sdk/tools/winesync/d3dx9_staging/0014-d3dx9_36__add_DXTn_support.diff [new file with mode: 0644]

index 77dd1cd..900a8bf 100644 (file)
@@ -35,7 +35,7 @@ function(add_d3dx9_target __version)
     set_module_type(${module} win32dll)
     add_dependencies(${module} d3d_idl_headers)
     target_link_libraries(${module} dxguid wine)
-    add_importlibs(${module} d3dcompiler_43 d3dxof user32 ole32 gdi32 msvcrt kernel32 ntdll)
+    add_importlibs(${module} d3dcompiler_43 d3dxof d3dwine user32 ole32 gdi32 msvcrt kernel32 ntdll)
     add_delay_importlibs(${module} windowscodecs)
     add_pch(${module} ../d3dx9_36/precomp.h SOURCE)
     add_cd_file(TARGET ${module} DESTINATION reactos/system32 FOR all)
index d236feb..3c308d3 100644 (file)
@@ -27,6 +27,8 @@
 #include "ole2.h"
 #include "wincodec.h"
 
+#include "wine/wined3d.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
@@ -1876,6 +1878,24 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic
     }
 }
 
+typedef BOOL (*dxtn_conversion_func)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out,
+                                     enum wined3d_format_id format, unsigned int w, unsigned int h);
+
+static dxtn_conversion_func get_dxtn_conversion_func(D3DFORMAT format, BOOL encode)
+{
+    switch (format)
+    {
+        case D3DFMT_DXT1:
+            return encode ? wined3d_dxt1_encode : wined3d_dxt1_decode;
+        case D3DFMT_DXT3:
+            return encode ? wined3d_dxt3_encode : wined3d_dxt3_decode;
+        case D3DFMT_DXT5:
+            return encode ? wined3d_dxt5_encode : wined3d_dxt5_decode;
+        default:
+            return NULL;
+    }
+}
+
 /************************************************************
  * D3DXLoadSurfaceFromMemory
  *
@@ -1915,10 +1935,12 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
 {
     const struct pixel_format_desc *srcformatdesc, *destformatdesc;
     IDirect3DSurface9 *surface;
+    void *tmp_src_memory = NULL, *tmp_dst_memory = NULL;
+    dxtn_conversion_func pre_convert = NULL, post_convert = NULL;
     D3DSURFACE_DESC surfdesc;
     D3DLOCKED_RECT lockrect;
     struct volume src_size, dst_size;
-    HRESULT hr;
+    HRESULT hr = D3D_OK;
 
     TRACE("(%p, %p, %s, %p, %#x, %u, %p, %s, %#x, 0x%08x)\n",
             dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_memory, src_format,
@@ -1999,18 +2021,65 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
     }
     else /* Stretching or format conversion. */
     {
-        if (!is_conversion_from_supported(srcformatdesc)
-                || !is_conversion_to_supported(destformatdesc))
+        UINT tmp_src_pitch, tmp_dst_pitch;
+
+        pre_convert  = get_dxtn_conversion_func(srcformatdesc->format, FALSE);
+        post_convert = get_dxtn_conversion_func(destformatdesc->format, TRUE);
+
+        if ((!pre_convert && !is_conversion_from_supported(srcformatdesc)) ||
+                (!post_convert && !is_conversion_to_supported(destformatdesc)))
         {
             FIXME("Unsupported format conversion %#x -> %#x.\n", src_format, surfdesc.Format);
             unlock_surface(dst_surface, &lockrect, surface, FALSE);
             return E_NOTIMPL;
         }
 
+        /* handle pre-conversion */
+        if (pre_convert)
+        {
+            tmp_src_memory = HeapAlloc(GetProcessHeap(), 0, src_size.width * src_size.height * sizeof(DWORD));
+            if (!tmp_src_memory)
+            {
+                hr = E_OUTOFMEMORY;
+                goto done;
+            }
+            tmp_src_pitch = src_size.width * sizeof(DWORD);
+            if (!pre_convert(src_memory, tmp_src_memory, src_pitch, tmp_src_pitch,
+                    WINED3DFMT_B8G8R8A8_UNORM, src_size.width, src_size.height))
+            {
+                hr = E_FAIL;
+                goto done;
+            }
+            srcformatdesc = get_format_info(D3DFMT_A8R8G8B8);
+        }
+        else
+        {
+            tmp_src_memory = (void *)src_memory;
+            tmp_src_pitch  = src_pitch;
+        }
+
+        /* handle post-conversion */
+        if (post_convert)
+        {
+            tmp_dst_memory = HeapAlloc(GetProcessHeap(), 0, dst_size.width * dst_size.height * sizeof(DWORD));
+            if (!tmp_dst_memory)
+            {
+                hr = E_OUTOFMEMORY;
+                goto done;
+            }
+            tmp_dst_pitch = dst_size.width * sizeof(DWORD);
+            destformatdesc = get_format_info(D3DFMT_A8R8G8B8);
+        }
+        else
+        {
+            tmp_dst_memory = lockrect.pBits;
+            tmp_dst_pitch  = lockrect.Pitch;
+        }
+
         if ((filter & 0xf) == D3DX_FILTER_NONE)
         {
-            convert_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
-                    lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
+            convert_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, &src_size, srcformatdesc,
+                    tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
         }
         else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */
         {
@@ -2019,12 +2088,29 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
 
             /* Always apply a point filter until D3DX_FILTER_LINEAR,
              * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */
-            point_filter_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
-                    lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
+            point_filter_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, &src_size, srcformatdesc,
+                    tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
+        }
+
+        /* handle post-conversion */
+        if (post_convert)
+        {
+            if (!post_convert(tmp_dst_memory, lockrect.pBits, tmp_dst_pitch, lockrect.Pitch,
+                    WINED3DFMT_B8G8R8A8_UNORM, dst_size.width, dst_size.height))
+            {
+                hr = E_FAIL;
+            }
         }
     }
 
-    return unlock_surface(dst_surface, &lockrect, surface, TRUE);
+done:
+    if (pre_convert)
+        HeapFree(GetProcessHeap(), 0, tmp_src_memory);
+    if (post_convert)
+        HeapFree(GetProcessHeap(), 0, tmp_dst_memory);
+
+    unlock_surface(dst_surface, &lockrect, surface, TRUE);
+    return hr;
 }
 
 /************************************************************
index 2c83dc2..95b64a0 100644 (file)
@@ -1224,7 +1224,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
-            todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT3 format.\n");
+            ok(SUCCEEDED(hr), "Failed to convert pixels to DXT3 format.\n");
             check_release((IUnknown*)newsurf, 1);
             check_release((IUnknown*)tex, 0);
         }
@@ -1250,7 +1250,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
-            todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT5 format.\n");
+            ok(SUCCEEDED(hr), "Failed to convert pixels to DXT5 format.\n");
             check_release((IUnknown*)newsurf, 1);
             check_release((IUnknown*)tex, 0);
         }
@@ -1263,10 +1263,10 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
-            todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT1 format.\n");
+            ok(SUCCEEDED(hr), "Failed to convert pixels to DXT1 format.\n");
 
             hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
-            todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels from DXT1 format.\n");
+            ok(SUCCEEDED(hr), "Failed to convert pixels from DXT1 format.\n");
 
             check_release((IUnknown*)newsurf, 1);
             check_release((IUnknown*)tex, 0);
diff --git a/sdk/tools/winesync/d3dx9_staging/0014-d3dx9_36__add_DXTn_support.diff b/sdk/tools/winesync/d3dx9_staging/0014-d3dx9_36__add_DXTn_support.diff
new file mode 100644 (file)
index 0000000..96b30a5
--- /dev/null
@@ -0,0 +1,203 @@
+diff --git a/dll/directx/wine/d3dx9_36/d3dx9.cmake b/dll/directx/wine/d3dx9_36/d3dx9.cmake
+index 77dd1cde..900a8bfe 100644
+--- a/dll/directx/wine/d3dx9_36/d3dx9.cmake
++++ b/dll/directx/wine/d3dx9_36/d3dx9.cmake
+@@ -35,7 +35,7 @@ function(add_d3dx9_target __version)
+     set_module_type(${module} win32dll)
+     add_dependencies(${module} d3d_idl_headers)
+     target_link_libraries(${module} dxguid wine)
+-    add_importlibs(${module} d3dcompiler_43 d3dxof user32 ole32 gdi32 msvcrt kernel32 ntdll)
++    add_importlibs(${module} d3dcompiler_43 d3dxof d3dwine user32 ole32 gdi32 msvcrt kernel32 ntdll)
+     add_delay_importlibs(${module} windowscodecs)
+     add_pch(${module} ../d3dx9_36/precomp.h SOURCE)
+     add_cd_file(TARGET ${module} DESTINATION reactos/system32 FOR all)
+diff --git a/dll/directx/wine/d3dx9_36/surface.c b/dll/directx/wine/d3dx9_36/surface.c
+index d236feb0..3c308d36 100644
+--- a/dll/directx/wine/d3dx9_36/surface.c
++++ b/dll/directx/wine/d3dx9_36/surface.c
+@@ -27,6 +27,8 @@
+ #include "ole2.h"
+ #include "wincodec.h"
++#include "wine/wined3d.h"
++
+ WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+ HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
+@@ -1876,6 +1878,24 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic
+     }
+ }
++typedef BOOL (*dxtn_conversion_func)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out,
++                                     enum wined3d_format_id format, unsigned int w, unsigned int h);
++
++static dxtn_conversion_func get_dxtn_conversion_func(D3DFORMAT format, BOOL encode)
++{
++    switch (format)
++    {
++        case D3DFMT_DXT1:
++            return encode ? wined3d_dxt1_encode : wined3d_dxt1_decode;
++        case D3DFMT_DXT3:
++            return encode ? wined3d_dxt3_encode : wined3d_dxt3_decode;
++        case D3DFMT_DXT5:
++            return encode ? wined3d_dxt5_encode : wined3d_dxt5_decode;
++        default:
++            return NULL;
++    }
++}
++
+ /************************************************************
+  * D3DXLoadSurfaceFromMemory
+  *
+@@ -1915,10 +1935,12 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
+ {
+     const struct pixel_format_desc *srcformatdesc, *destformatdesc;
+     IDirect3DSurface9 *surface;
++    void *tmp_src_memory = NULL, *tmp_dst_memory = NULL;
++    dxtn_conversion_func pre_convert = NULL, post_convert = NULL;
+     D3DSURFACE_DESC surfdesc;
+     D3DLOCKED_RECT lockrect;
+     struct volume src_size, dst_size;
+-    HRESULT hr;
++    HRESULT hr = D3D_OK;
+     TRACE("(%p, %p, %s, %p, %#x, %u, %p, %s, %#x, 0x%08x)\n",
+             dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_memory, src_format,
+@@ -1999,18 +2021,65 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
+     }
+     else /* Stretching or format conversion. */
+     {
+-        if (!is_conversion_from_supported(srcformatdesc)
+-                || !is_conversion_to_supported(destformatdesc))
++        UINT tmp_src_pitch, tmp_dst_pitch;
++
++        pre_convert  = get_dxtn_conversion_func(srcformatdesc->format, FALSE);
++        post_convert = get_dxtn_conversion_func(destformatdesc->format, TRUE);
++
++        if ((!pre_convert && !is_conversion_from_supported(srcformatdesc)) ||
++                (!post_convert && !is_conversion_to_supported(destformatdesc)))
+         {
+             FIXME("Unsupported format conversion %#x -> %#x.\n", src_format, surfdesc.Format);
+             unlock_surface(dst_surface, &lockrect, surface, FALSE);
+             return E_NOTIMPL;
+         }
++        /* handle pre-conversion */
++        if (pre_convert)
++        {
++            tmp_src_memory = HeapAlloc(GetProcessHeap(), 0, src_size.width * src_size.height * sizeof(DWORD));
++            if (!tmp_src_memory)
++            {
++                hr = E_OUTOFMEMORY;
++                goto done;
++            }
++            tmp_src_pitch = src_size.width * sizeof(DWORD);
++            if (!pre_convert(src_memory, tmp_src_memory, src_pitch, tmp_src_pitch,
++                    WINED3DFMT_B8G8R8A8_UNORM, src_size.width, src_size.height))
++            {
++                hr = E_FAIL;
++                goto done;
++            }
++            srcformatdesc = get_format_info(D3DFMT_A8R8G8B8);
++        }
++        else
++        {
++            tmp_src_memory = (void *)src_memory;
++            tmp_src_pitch  = src_pitch;
++        }
++
++        /* handle post-conversion */
++        if (post_convert)
++        {
++            tmp_dst_memory = HeapAlloc(GetProcessHeap(), 0, dst_size.width * dst_size.height * sizeof(DWORD));
++            if (!tmp_dst_memory)
++            {
++                hr = E_OUTOFMEMORY;
++                goto done;
++            }
++            tmp_dst_pitch = dst_size.width * sizeof(DWORD);
++            destformatdesc = get_format_info(D3DFMT_A8R8G8B8);
++        }
++        else
++        {
++            tmp_dst_memory = lockrect.pBits;
++            tmp_dst_pitch  = lockrect.Pitch;
++        }
++
+         if ((filter & 0xf) == D3DX_FILTER_NONE)
+         {
+-            convert_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
+-                    lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
++            convert_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, &src_size, srcformatdesc,
++                    tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
+         }
+         else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */
+         {
+@@ -2019,12 +2088,29 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
+             /* Always apply a point filter until D3DX_FILTER_LINEAR,
+              * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */
+-            point_filter_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
+-                    lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
++            point_filter_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, &src_size, srcformatdesc,
++                    tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
++        }
++
++        /* handle post-conversion */
++        if (post_convert)
++        {
++            if (!post_convert(tmp_dst_memory, lockrect.pBits, tmp_dst_pitch, lockrect.Pitch,
++                    WINED3DFMT_B8G8R8A8_UNORM, dst_size.width, dst_size.height))
++            {
++                hr = E_FAIL;
++            }
+         }
+     }
+-    return unlock_surface(dst_surface, &lockrect, surface, TRUE);
++done:
++    if (pre_convert)
++        HeapFree(GetProcessHeap(), 0, tmp_src_memory);
++    if (post_convert)
++        HeapFree(GetProcessHeap(), 0, tmp_dst_memory);
++
++    unlock_surface(dst_surface, &lockrect, surface, TRUE);
++    return hr;
+ }
+ /************************************************************
+diff --git a/modules/rostests/winetests/d3dx9_36/surface.c b/modules/rostests/winetests/d3dx9_36/surface.c
+index 2c83dc23..95b64a0f 100644
+--- a/modules/rostests/winetests/d3dx9_36/surface.c
++++ b/modules/rostests/winetests/d3dx9_36/surface.c
+@@ -1224,7 +1224,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
+             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
+             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
+             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
+-            todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT3 format.\n");
++            ok(SUCCEEDED(hr), "Failed to convert pixels to DXT3 format.\n");
+             check_release((IUnknown*)newsurf, 1);
+             check_release((IUnknown*)tex, 0);
+         }
+@@ -1250,7 +1250,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
+             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
+             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
+             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
+-            todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT5 format.\n");
++            ok(SUCCEEDED(hr), "Failed to convert pixels to DXT5 format.\n");
+             check_release((IUnknown*)newsurf, 1);
+             check_release((IUnknown*)tex, 0);
+         }
+@@ -1263,10 +1263,10 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
+             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
+             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
+             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
+-            todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT1 format.\n");
++            ok(SUCCEEDED(hr), "Failed to convert pixels to DXT1 format.\n");
+             hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
+-            todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels from DXT1 format.\n");
++            ok(SUCCEEDED(hr), "Failed to convert pixels from DXT1 format.\n");
+             check_release((IUnknown*)newsurf, 1);
+             check_release((IUnknown*)tex, 0);