From: Paul Gofman gofmanp@gmail.com
Signed-off-by: Paul Gofman gofmanp@gmail.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/surface.c | 75 ++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 23 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 11a0ee1a2fe..2d00cd1dcdc 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -199,6 +199,53 @@ static const struct { { 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, D3DFMT_X8B8G8R8 }, };
+static HRESULT lock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock, + IDirect3DSurface9 **temp_surface) +{ + IDirect3DDevice9 *device; + D3DSURFACE_DESC desc; + HRESULT hr; + + *temp_surface = NULL; + if (FAILED(hr = IDirect3DSurface9_LockRect(surface, lock, NULL, D3DLOCK_READONLY))) + { + IDirect3DSurface9_GetDevice(surface, &device); + IDirect3DSurface9_GetDesc(surface, &desc); + if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(device, desc.Width, desc.Height, + desc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, temp_surface, NULL))) + { + IDirect3DDevice9_Release(device); + return hr; + } + + if (SUCCEEDED(hr = IDirect3DDevice9_StretchRect(device, surface, NULL, *temp_surface, NULL, D3DTEXF_NONE))) + hr = IDirect3DSurface9_LockRect(*temp_surface, lock, NULL, D3DLOCK_READONLY); + IDirect3DDevice9_Release(device); + if (FAILED(hr)) + { + WARN("Failed to lock surface %p, usage %#x, pool %#x.\n", + surface, desc.Usage, desc.Pool); + IDirect3DSurface9_Release(*temp_surface); + *temp_surface = NULL; + return hr; + } + } + return hr; +} + +static HRESULT unlock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock, + IDirect3DSurface9 *temp_surface) +{ + HRESULT hr; + + if (!temp_surface) + return IDirect3DSurface9_UnlockRect(surface); + + hr = IDirect3DSurface9_UnlockRect(temp_surface); + IDirect3DSurface9_Release(temp_surface); + return hr; +} + static D3DFORMAT dds_rgb_to_d3dformat(const struct dds_pixel_format *pixel_format) { unsigned int i; @@ -1924,7 +1971,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromSurface(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect, DWORD filter, D3DCOLOR color_key) { - IDirect3DSurface9 *surface = src_surface; + IDirect3DSurface9 *temp_surface; D3DTEXTUREFILTERTYPE d3d_filter; IDirect3DDevice9 *device; D3DSURFACE_DESC src_desc; @@ -1979,32 +2026,14 @@ HRESULT WINAPI D3DXLoadSurfaceFromSurface(IDirect3DSurface9 *dst_surface, src_rect = &s; }
- if (FAILED(IDirect3DSurface9_LockRect(surface, &lock, NULL, D3DLOCK_READONLY))) - { - IDirect3DSurface9_GetDevice(src_surface, &device); - if (FAILED(IDirect3DDevice9_CreateRenderTarget(device, src_desc.Width, src_desc.Height, - src_desc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL))) - { - IDirect3DDevice9_Release(device); - return D3DXERR_INVALIDDATA; - } - - if (SUCCEEDED(hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, surface, NULL, D3DTEXF_NONE))) - hr = IDirect3DSurface9_LockRect(surface, &lock, NULL, D3DLOCK_READONLY); - IDirect3DDevice9_Release(device); - if (FAILED(hr)) - { - IDirect3DSurface9_Release(surface); - return D3DXERR_INVALIDDATA; - } - } + if (FAILED(lock_surface(src_surface, &lock, &temp_surface))) + return D3DXERR_INVALIDDATA;
hr = D3DXLoadSurfaceFromMemory(dst_surface, dst_palette, dst_rect, lock.pBits, src_desc.Format, lock.Pitch, src_palette, src_rect, filter, color_key);
- IDirect3DSurface9_UnlockRect(surface); - if (surface != src_surface) - IDirect3DSurface9_Release(surface); + if (FAILED(unlock_surface(src_surface, &lock, temp_surface))) + return D3DXERR_INVALIDDATA;
return hr; }
From: Paul Gofman gofmanp@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46453
Fixes a regression triggered by commit 949dbbd31f450178c90ea8267097a975b77c3219.
Signed-off-by: Paul Gofman gofmanp@gmail.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Make [un]lock_surface() return back the d3d9 HRESULT, some small cleanup.
In general, I'm not a fan of the todo_wine on its own line. I don't see the problem in updating the ok() line when removing the todo_wine; on the contrary I think leaving a trace in "git blame" can be helpful sometimes.
dlls/d3dx9_36/d3dx9_private.h | 4 ++ dlls/d3dx9_36/surface.c | 47 ++++++++++----- dlls/d3dx9_36/tests/texture.c | 106 ++++++++++++++++++++++++---------- dlls/d3dx9_36/texture.c | 28 ++++++--- 4 files changed, 134 insertions(+), 51 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 930fce3ddfb..5a28f2eff76 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -121,6 +121,10 @@ HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *d const D3DXIMAGE_INFO *src_info) DECLSPEC_HIDDEN; HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info) DECLSPEC_HIDDEN; +HRESULT lock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock, + IDirect3DSurface9 **temp_surface, BOOL write) DECLSPEC_HIDDEN; +HRESULT unlock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock, + IDirect3DSurface9 *temp_surface, BOOL update) DECLSPEC_HIDDEN;
unsigned short float_32_to_16(const float in) DECLSPEC_HIDDEN; float float_16_to_32(const unsigned short in) DECLSPEC_HIDDEN; diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 2d00cd1dcdc..a6eb5482f71 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -199,49 +199,70 @@ static const struct { { 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, D3DFMT_X8B8G8R8 }, };
-static HRESULT lock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock, - IDirect3DSurface9 **temp_surface) +HRESULT lock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock, + IDirect3DSurface9 **temp_surface, BOOL write) { IDirect3DDevice9 *device; D3DSURFACE_DESC desc; + DWORD lock_flag; HRESULT hr;
+ lock_flag = write ? D3DLOCK_DISCARD : D3DLOCK_READONLY; *temp_surface = NULL; - if (FAILED(hr = IDirect3DSurface9_LockRect(surface, lock, NULL, D3DLOCK_READONLY))) + if (FAILED(hr = IDirect3DSurface9_LockRect(surface, lock, NULL, lock_flag))) { IDirect3DSurface9_GetDevice(surface, &device); IDirect3DSurface9_GetDesc(surface, &desc); - if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(device, desc.Width, desc.Height, - desc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, temp_surface, NULL))) + + hr = write ? IDirect3DDevice9_CreateOffscreenPlainSurface(device, desc.Width, desc.Height, + desc.Format, D3DPOOL_SYSTEMMEM, temp_surface, NULL) + : IDirect3DDevice9_CreateRenderTarget(device, desc.Width, desc.Height, + desc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, temp_surface, NULL); + if (FAILED(hr)) { + WARN("Failed to create temporary surface, surface %p, format %#x," + " usage %#x, pool %#x, write %#x, width %u, height %u.\n", + surface, desc.Format, desc.Usage, desc.Pool, write, desc.Width, desc.Height); IDirect3DDevice9_Release(device); return hr; }
- if (SUCCEEDED(hr = IDirect3DDevice9_StretchRect(device, surface, NULL, *temp_surface, NULL, D3DTEXF_NONE))) - hr = IDirect3DSurface9_LockRect(*temp_surface, lock, NULL, D3DLOCK_READONLY); + if (write || SUCCEEDED(hr = IDirect3DDevice9_StretchRect(device, surface, NULL, + *temp_surface, NULL, D3DTEXF_NONE))) + hr = IDirect3DSurface9_LockRect(*temp_surface, lock, NULL, lock_flag); + IDirect3DDevice9_Release(device); if (FAILED(hr)) { - WARN("Failed to lock surface %p, usage %#x, pool %#x.\n", - surface, desc.Usage, desc.Pool); + WARN("Failed to lock surface %p, write %#x, usage %#x, pool %#x.\n", + surface, write, desc.Usage, desc.Pool); IDirect3DSurface9_Release(*temp_surface); *temp_surface = NULL; return hr; } + TRACE("Created temporary surface %p.\n", surface); } return hr; }
-static HRESULT unlock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock, - IDirect3DSurface9 *temp_surface) +HRESULT unlock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock, + IDirect3DSurface9 *temp_surface, BOOL update) { + IDirect3DDevice9 *device; HRESULT hr;
if (!temp_surface) return IDirect3DSurface9_UnlockRect(surface);
hr = IDirect3DSurface9_UnlockRect(temp_surface); + if (update) + { + IDirect3DSurface9_GetDevice(surface, &device); + if (FAILED(hr = IDirect3DDevice9_UpdateSurface(device, temp_surface, NULL, surface, NULL))) + WARN("Updating surface failed, hr %#x, surface %p, temp_surface %p.\n", + hr, surface, temp_surface); + IDirect3DDevice9_Release(device); + } IDirect3DSurface9_Release(temp_surface); return hr; } @@ -2026,13 +2047,13 @@ HRESULT WINAPI D3DXLoadSurfaceFromSurface(IDirect3DSurface9 *dst_surface, src_rect = &s; }
- if (FAILED(lock_surface(src_surface, &lock, &temp_surface))) + if (FAILED(lock_surface(src_surface, &lock, &temp_surface, FALSE))) return D3DXERR_INVALIDDATA;
hr = D3DXLoadSurfaceFromMemory(dst_surface, dst_palette, dst_rect, lock.pBits, src_desc.Format, lock.Pitch, src_palette, src_rect, filter, color_key);
- if (FAILED(unlock_surface(src_surface, &lock, temp_surface))) + if (FAILED(unlock_surface(src_surface, &lock, temp_surface, FALSE))) return D3DXERR_INVALIDDATA;
return hr; diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 79cddc73ab6..1a92a85b63e 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -1007,59 +1007,103 @@ static void WINAPI fillfunc(D3DXVECTOR4 *value, const D3DXVECTOR2 *texcoord,
static void test_D3DXFillTexture(IDirect3DDevice9 *device) { + static const struct + { + DWORD usage; + D3DPOOL pool; + } + test_access_types[] = + { + {0, D3DPOOL_MANAGED}, + {0, D3DPOOL_DEFAULT}, + {D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT}, + }; + IDirect3DTexture9 *tex; HRESULT hr; D3DLOCKED_RECT lock_rect; DWORD x, y, m; DWORD v[4], e[4]; DWORD value, expected, size, pitch; + unsigned int i;
- size = 4; - hr = IDirect3DDevice9_CreateTexture(device, size, size, 0, 0, D3DFMT_A8R8G8B8, - D3DPOOL_MANAGED, &tex, NULL); - - if (SUCCEEDED(hr)) + for (i = 0; i < ARRAY_SIZE(test_access_types); ++i) { + size = 4; + hr = IDirect3DDevice9_CreateTexture(device, size, size, 0, test_access_types[i].usage, + D3DFMT_A8R8G8B8, test_access_types[i].pool, &tex, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i); + hr = D3DXFillTexture(tex, fillfunc, NULL); - ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i);
for (m = 0; m < 3; m++) { - hr = IDirect3DTexture9_LockRect(tex, m, &lock_rect, NULL, D3DLOCK_READONLY); - ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); - if (SUCCEEDED(hr)) + IDirect3DSurface9 *src_surface, *temp_surface; + + hr = IDirect3DTexture9_GetSurfaceLevel(tex, m, &src_surface); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u, m %u.\n", hr, i, m); + temp_surface = src_surface; + + if (FAILED(hr = IDirect3DSurface9_LockRect(src_surface, &lock_rect, NULL, D3DLOCK_READONLY))) { - pitch = lock_rect.Pitch / sizeof(DWORD); - for (y = 0; y < size; y++) + hr = IDirect3DDevice9_CreateRenderTarget(device, size, size, + D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &temp_surface, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u, m %u.\n", hr, i, m); + hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, temp_surface, NULL, D3DTEXF_NONE); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u, m %u.\n", hr, i, m); + hr = IDirect3DSurface9_LockRect(temp_surface, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u, m %u.\n", hr, i, m); + } + + pitch = lock_rect.Pitch / sizeof(DWORD); + for (y = 0; y < size; y++) + { + for (x = 0; x < size; x++) { - for (x = 0; x < size; x++) - { - value = ((DWORD *)lock_rect.pBits)[y * pitch + x]; - v[0] = (value >> 24) & 0xff; - v[1] = (value >> 16) & 0xff; - v[2] = (value >> 8) & 0xff; - v[3] = value & 0xff; - - e[0] = 0xff; - e[1] = (x + 0.5f) / size * 255.0f + 0.5f; - e[2] = (y + 0.5f) / size * 255.0f + 0.5f; - e[3] = 255.0f / size + 0.5f; - expected = e[0] << 24 | e[1] << 16 | e[2] << 8 | e[3]; + value = ((DWORD *)lock_rect.pBits)[y * pitch + x]; + v[0] = (value >> 24) & 0xff; + v[1] = (value >> 16) & 0xff; + v[2] = (value >> 8) & 0xff; + v[3] = value & 0xff; + + e[0] = 0xff; + e[1] = (x + 0.5f) / size * 255.0f + 0.5f; + e[2] = (y + 0.5f) / size * 255.0f + 0.5f; + e[3] = 255.0f / size + 0.5f; + expected = e[0] << 24 | e[1] << 16 | e[2] << 8 | e[3];
- ok(color_match(v, e), - "Texel at (%u, %u) doesn't match: %#x, expected %#x\n", - x, y, value, expected); - } + ok(color_match(v, e), + "Texel at (%u, %u) doesn't match: %#x, expected %#x, i %u, m %u.\n", + x, y, value, expected, i, m); } - IDirect3DTexture9_UnlockRect(tex, m); } + IDirect3DSurface9_UnlockRect(temp_surface); + if (temp_surface != src_surface) + IDirect3DSurface9_Release(temp_surface); + IDirect3DSurface9_Release(src_surface); size >>= 1; } + IDirect3DTexture9_Release(tex); + } + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 1, D3DUSAGE_DEPTHSTENCIL, + D3DFMT_D16_LOCKABLE, D3DPOOL_DEFAULT, &tex, NULL); + if (hr == D3D_OK) + { + hr = D3DXFillTexture(tex, fillfunc, NULL); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + IDirect3DTexture9_Release(tex); + }
+ hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 1, D3DUSAGE_DEPTHSTENCIL, + D3DFMT_D16, D3DPOOL_DEFAULT, &tex, NULL); + if (hr == D3D_OK) + { + hr = D3DXFillTexture(tex, fillfunc, NULL); + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr); IDirect3DTexture9_Release(tex); } - else - skip("Failed to create texture\n");
hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, &tex, NULL); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 0f53d95bf1f..e2dfab84205 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -1323,6 +1323,7 @@ static inline void fill_texture(const struct pixel_format_desc *format, BYTE *po
HRESULT WINAPI D3DXFillTexture(struct IDirect3DTexture9 *texture, LPD3DXFILL2D function, void *funcdata) { + IDirect3DSurface9 *surface, *temp_surface; DWORD miplevels; DWORD m, x, y; D3DSURFACE_DESC desc; @@ -1331,26 +1332,34 @@ HRESULT WINAPI D3DXFillTexture(struct IDirect3DTexture9 *texture, LPD3DXFILL2D f D3DXVECTOR2 coord, size; const struct pixel_format_desc *format; BYTE *data; + HRESULT hr;
- if (texture == NULL || function == NULL) + TRACE("texture %p, function %p, funcdata %p.\n", texture, function, funcdata); + + if (!texture || !function) return D3DERR_INVALIDCALL;
miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
for (m = 0; m < miplevels; m++) { - if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc))) - return D3DERR_INVALIDCALL; + if (FAILED(hr = IDirect3DTexture9_GetLevelDesc(texture, m, &desc))) + return hr;
format = get_format_info(desc.Format); if (format->type != FORMAT_ARGB && format->type != FORMAT_ARGBF16 && format->type != FORMAT_ARGBF) { - FIXME("Unsupported texture format %#x\n", desc.Format); + FIXME("Unsupported texture format %#x.\n", desc.Format); return D3DERR_INVALIDCALL; }
- if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD))) - return D3DERR_INVALIDCALL; + if (FAILED(hr = IDirect3DTexture9_GetSurfaceLevel(texture, m, &surface))) + return hr; + if (FAILED(hr = lock_surface(surface, &lock_rect, &temp_surface, TRUE))) + { + IDirect3DSurface9_Release(surface); + return hr; + }
size.x = 1.0f / desc.Width; size.y = 1.0f / desc.Height; @@ -1372,7 +1381,12 @@ HRESULT WINAPI D3DXFillTexture(struct IDirect3DTexture9 *texture, LPD3DXFILL2D f fill_texture(format, data + y * lock_rect.Pitch + x * format->bytes_per_pixel, &value); } } - IDirect3DTexture9_UnlockRect(texture, m); + if (FAILED(hr = unlock_surface(surface, &lock_rect, temp_surface, TRUE))) + { + IDirect3DSurface9_Release(surface); + return hr; + } + IDirect3DSurface9_Release(surface); }
return D3D_OK;
From: Paul Gofman gofmanp@gmail.com
Signed-off-by: Paul Gofman gofmanp@gmail.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/tests/texture.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 1a92a85b63e..6c25a158118 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -1423,8 +1423,14 @@ static void test_D3DXFillVolumeTexture(IDirect3DDevice9 *device)
size = 4; hr = IDirect3DDevice9_CreateVolumeTexture(device, size, size, size, 0, 0, D3DFMT_A8R8G8B8, - D3DPOOL_MANAGED, &tex, NULL); + D3DPOOL_DEFAULT, &tex, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + hr = D3DXFillVolumeTexture(tex, fillfunc_volume, NULL); + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr); + IDirect3DVolumeTexture9_Release(tex);
+ hr = IDirect3DDevice9_CreateVolumeTexture(device, size, size, size, 0, 0, D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, &tex, NULL); if (SUCCEEDED(hr)) { hr = D3DXFillVolumeTexture(tex, fillfunc_volume, NULL);
From: Paul Gofman gofmanp@gmail.com
Signed-off-by: Paul Gofman gofmanp@gmail.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/surface.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index a6eb5482f71..faac1419517 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -2229,12 +2229,12 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE if (src_surface_desc.Format == d3d_pixel_format) /* Simple copy */ { hr = IDirect3DSurface9_LockRect(src_surface, &locked_rect, src_rect, D3DLOCK_READONLY); - if (SUCCEEDED(hr)) - { - IWICBitmapFrameEncode_WritePixels(frame, height, - locked_rect.Pitch, height * locked_rect.Pitch, locked_rect.pBits); - IDirect3DSurface9_UnlockRect(src_surface); - } + if (FAILED(hr)) + goto cleanup; + + IWICBitmapFrameEncode_WritePixels(frame, height, + locked_rect.Pitch, height * locked_rect.Pitch, locked_rect.pBits); + IDirect3DSurface9_UnlockRect(src_surface); } else /* Pixel format conversion */ { @@ -2266,12 +2266,14 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE }
hr = IDirect3DSurface9_LockRect(src_surface, &locked_rect, src_rect, D3DLOCK_READONLY); - if (SUCCEEDED(hr)) + if (FAILED(hr)) { - convert_argb_pixels(locked_rect.pBits, locked_rect.Pitch, 0, &size, src_format_desc, - dst_data, dst_pitch, 0, &size, dst_format_desc, 0, NULL); - IDirect3DSurface9_UnlockRect(src_surface); + HeapFree(GetProcessHeap(), 0, dst_data); + goto cleanup; } + convert_argb_pixels(locked_rect.pBits, locked_rect.Pitch, 0, &size, src_format_desc, + dst_data, dst_pitch, 0, &size, dst_format_desc, 0, NULL); + IDirect3DSurface9_UnlockRect(src_surface);
IWICBitmapFrameEncode_WritePixels(frame, height, dst_pitch, dst_pitch * height, dst_data); HeapFree(GetProcessHeap(), 0, dst_data);
From: Paul Gofman gofmanp@gmail.com
Fixes a regression triggered by commit 949dbbd31f450178c90ea8267097a975b77c3219.
Signed-off-by: Paul Gofman gofmanp@gmail.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/surface.c | 20 ++++++++-------- dlls/d3dx9_36/tests/surface.c | 43 +++++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 15 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index faac1419517..23e8f7691f2 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -530,6 +530,7 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSur BYTE *pixels; struct volume volume; const struct pixel_format_desc *pixel_format; + IDirect3DSurface9 *temp_surface;
if (src_rect) { @@ -569,7 +570,7 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSur return hr; }
- hr = IDirect3DSurface9_LockRect(src_surface, &locked_rect, NULL, D3DLOCK_READONLY); + hr = lock_surface(src_surface, &locked_rect, &temp_surface, FALSE); if (FAILED(hr)) { ID3DXBuffer_Release(buffer); @@ -582,7 +583,7 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSur copy_pixels(locked_rect.pBits, locked_rect.Pitch, 0, pixels, dst_pitch, 0, &volume, pixel_format);
- IDirect3DSurface9_UnlockRect(src_surface); + unlock_surface(src_surface, &locked_rect, temp_surface, FALSE);
*dst_buffer = buffer; return D3D_OK; @@ -2124,6 +2125,7 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE WICPixelFormatGUID wic_pixel_format; D3DFORMAT d3d_pixel_format; D3DSURFACE_DESC src_surface_desc; + IDirect3DSurface9 *temp_surface; D3DLOCKED_RECT locked_rect; int width, height; STATSTG stream_stats; @@ -2131,7 +2133,7 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE ID3DXBuffer *buffer; DWORD size;
- TRACE("(%p, %#x, %p, %p, %s)\n", + TRACE("dst_buffer %p, file_format %#x, src_surface %p, src_palette %p, src_rect %s.\n", dst_buffer, file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
if (!dst_buffer || !src_surface) return D3DERR_INVALIDCALL; @@ -2225,16 +2227,14 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE if (SUCCEEDED(hr) && d3d_pixel_format != D3DFMT_UNKNOWN) { TRACE("Using pixel format %s %#x\n", debugstr_guid(&wic_pixel_format), d3d_pixel_format); - if (src_surface_desc.Format == d3d_pixel_format) /* Simple copy */ { - hr = IDirect3DSurface9_LockRect(src_surface, &locked_rect, src_rect, D3DLOCK_READONLY); - if (FAILED(hr)) + if (FAILED(hr = lock_surface(src_surface, &locked_rect, &temp_surface, FALSE))) goto cleanup;
IWICBitmapFrameEncode_WritePixels(frame, height, locked_rect.Pitch, height * locked_rect.Pitch, locked_rect.pBits); - IDirect3DSurface9_UnlockRect(src_surface); + unlock_surface(src_surface, &locked_rect, temp_surface, FALSE); } else /* Pixel format conversion */ { @@ -2264,16 +2264,14 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE hr = E_OUTOFMEMORY; goto cleanup; } - - hr = IDirect3DSurface9_LockRect(src_surface, &locked_rect, src_rect, D3DLOCK_READONLY); - if (FAILED(hr)) + if (FAILED(hr = lock_surface(src_surface, &locked_rect, &temp_surface, FALSE))) { HeapFree(GetProcessHeap(), 0, dst_data); goto cleanup; } convert_argb_pixels(locked_rect.pBits, locked_rect.Pitch, 0, &size, src_format_desc, dst_data, dst_pitch, 0, &size, dst_format_desc, 0, NULL); - IDirect3DSurface9_UnlockRect(src_surface); + unlock_surface(src_surface, &locked_rect, temp_surface, FALSE);
IWICBitmapFrameEncode_WritePixels(frame, height, dst_pitch, dst_pitch * height, dst_data); HeapFree(GetProcessHeap(), 0, dst_data); diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index d3450722ef7..6cb1ddb73ce 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -1253,16 +1253,30 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) { - HRESULT hr; - RECT rect; - ID3DXBuffer *buffer; - IDirect3DSurface9 *surface; + static const struct + { + DWORD usage; + D3DPOOL pool; + } + test_access_types[] = + { + {0, D3DPOOL_MANAGED}, + {0, D3DPOOL_DEFAULT}, + {D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT}, + }; + struct { DWORD magic; struct dds_header header; BYTE *data; } *dds; + IDirect3DSurface9 *surface; + IDirect3DTexture9 *texture; + ID3DXBuffer *buffer; + unsigned int i; + HRESULT hr; + RECT rect;
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL); if (FAILED(hr)) { @@ -1317,6 +1331,27 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) ID3DXBuffer_Release(buffer);
IDirect3DSurface9_Release(surface); + + for (i = 0; i < ARRAY_SIZE(test_access_types); ++i) + { + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 0, test_access_types[i].usage, + D3DFMT_A8R8G8B8, test_access_types[i].pool, &texture, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i); + + hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i); + + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i); + ID3DXBuffer_Release(buffer); + + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_BMP, surface, NULL, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i); + ID3DXBuffer_Release(buffer); + + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + } }
static void test_D3DXSaveSurfaceToFile(IDirect3DDevice9 *device)
From: Paul Gofman gofmanp@gmail.com
Signed-off-by: Paul Gofman gofmanp@gmail.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/surface.c | 48 +++++++---------------------------------- 1 file changed, 8 insertions(+), 40 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 23e8f7691f2..cae80a8689b 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1822,8 +1822,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, DWORD filter, D3DCOLOR color_key) { const struct pixel_format_desc *srcformatdesc, *destformatdesc; - IDirect3DSurface9 *surface = dst_surface; - IDirect3DDevice9 *device; + IDirect3DSurface9 *surface; D3DSURFACE_DESC surfdesc; D3DLOCKED_RECT lockrect; struct volume src_size, dst_size; @@ -1883,25 +1882,8 @@ 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 (FAILED(hr = lock_surface(dst_surface, &lockrect, &surface, TRUE))) + return hr;
if (src_format == surfdesc.Format && dst_size.width == src_size.width @@ -1916,8 +1898,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, && src_size.height != surfdesc.Height)) { WARN("Source rect %s is misaligned.\n", wine_dbgstr_rect(src_rect)); - hr = D3DXERR_INVALIDDATA; - goto done; + unlock_surface(dst_surface, &lockrect, surface, FALSE); + return D3DXERR_INVALIDDATA; }
copy_pixels(src_memory, src_pitch, 0, lockrect.pBits, lockrect.Pitch, 0, @@ -1929,8 +1911,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, || !is_conversion_to_supported(destformatdesc)) { FIXME("Unsupported format conversion %#x -> %#x.\n", src_format, surfdesc.Format); - hr = E_NOTIMPL; - goto done; + unlock_surface(dst_surface, &lockrect, surface, FALSE); + return E_NOTIMPL; }
if ((filter & 0xf) == D3DX_FILTER_NONE) @@ -1950,21 +1932,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *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 hr; + return unlock_surface(dst_surface, &lockrect, surface, TRUE); }
/************************************************************