Henri Verbeet : d3dx9: Use a staging texture to update unmappable surfaces in D3DXLoadSurfaceFromMemory ().

Alexandre Julliard julliard at winehq.org
Mon Nov 19 15:59:38 CST 2018


Module: wine
Branch: master
Commit: 9ab14dff87c7d3ddae18d9e862cbe3edca81d8c0
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=9ab14dff87c7d3ddae18d9e862cbe3edca81d8c0

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Sun Nov 18 22:27:19 2018 +0330

d3dx9: Use a staging texture to update unmappable surfaces in D3DXLoadSurfaceFromMemory().

Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3dx9_36/surface.c       | 53 +++++++++++++++++++++++++++++++++----------
 dlls/d3dx9_36/tests/surface.c |  1 -
 2 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index a44398c..7d48cc6 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -1753,9 +1753,12 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
         DWORD filter, D3DCOLOR color_key)
 {
     const struct pixel_format_desc *srcformatdesc, *destformatdesc;
+    IDirect3DSurface9 *surface = dst_surface;
+    IDirect3DDevice9 *device;
     D3DSURFACE_DESC surfdesc;
     D3DLOCKED_RECT lockrect;
     struct volume src_size, dst_size;
+    HRESULT hr;
 
     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,
@@ -1811,6 +1814,26 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
         return E_NOTIMPL;
     }
 
+    if (surfdesc.Pool == D3DPOOL_DEFAULT && !(surfdesc.Usage & D3DUSAGE_DYNAMIC))
+    {
+        IDirect3DSurface9_GetDevice(dst_surface, &device);
+        hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, surfdesc.Width,
+                surfdesc.Height, surfdesc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
+        IDirect3DDevice9_Release(device);
+        if (FAILED(hr))
+        {
+            WARN("Failed to create staging surface, hr %#x.\n", hr);
+            return D3DERR_INVALIDCALL;
+        }
+    }
+
+    if (FAILED(IDirect3DSurface9_LockRect(surface, &lockrect, dst_rect, 0)))
+    {
+        if (surface != dst_surface)
+            IDirect3DSurface9_Release(surface);
+        return D3DXERR_INVALIDDATA;
+    }
+
     if (src_format == surfdesc.Format
             && dst_size.width == src_size.width
             && dst_size.height == src_size.height
@@ -1824,16 +1847,12 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
                     && src_size.height != surfdesc.Height))
         {
             WARN("Source rect %s is misaligned.\n", wine_dbgstr_rect(src_rect));
-            return D3DXERR_INVALIDDATA;
+            hr = D3DXERR_INVALIDDATA;
+            goto done;
         }
 
-        if (FAILED(IDirect3DSurface9_LockRect(dst_surface, &lockrect, dst_rect, 0)))
-            return D3DXERR_INVALIDDATA;
-
         copy_pixels(src_memory, src_pitch, 0, lockrect.pBits, lockrect.Pitch, 0,
                 &src_size, srcformatdesc);
-
-        IDirect3DSurface9_UnlockRect(dst_surface);
     }
     else /* Stretching or format conversion. */
     {
@@ -1841,12 +1860,10 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
                 || !is_conversion_to_supported(destformatdesc))
         {
             FIXME("Unsupported format conversion %#x -> %#x.\n", src_format, surfdesc.Format);
-            return E_NOTIMPL;
+            hr = E_NOTIMPL;
+            goto done;
         }
 
-        if (FAILED(IDirect3DSurface9_LockRect(dst_surface, &lockrect, dst_rect, 0)))
-            return D3DXERR_INVALIDDATA;
-
         if ((filter & 0xf) == D3DX_FILTER_NONE)
         {
             convert_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
@@ -1862,11 +1879,23 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
             point_filter_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
                     lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
         }
+    }
 
-        IDirect3DSurface9_UnlockRect(dst_surface);
+    hr = D3D_OK;
+done:
+    IDirect3DSurface9_UnlockRect(surface);
+    if (surface != dst_surface)
+    {
+        if (SUCCEEDED(hr))
+        {
+            IDirect3DSurface9_GetDevice(dst_surface, &device);
+            hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, dst_surface, NULL);
+            IDirect3DDevice9_Release(device);
+        }
+        IDirect3DSurface9_Release(surface);
     }
 
-    return D3D_OK;
+    return hr;
 }
 
 /************************************************************
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c
index 469c864..f153cd9 100644
--- a/dlls/d3dx9_36/tests/surface.c
+++ b/dlls/d3dx9_36/tests/surface.c
@@ -867,7 +867,6 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget returned %#x, expected %#x.\n", hr, D3D_OK);
 
     hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
-    todo_wine
     ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK);
     hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
     todo_wine




More information about the wine-cvs mailing list