[PATCH 2/6] d3dx9: Use temporary surface in D3DXFillTexture() for unmappable textures.
Paul Gofman
gofmanp at gmail.com
Mon Jan 14 06:12:23 CST 2019
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46453
Fixes a regression triggered by commit 949dbbd31f450178c90ea8267097a975b77c3219.
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
dlls/d3dx9_36/d3dx9_private.h | 4 ++
dlls/d3dx9_36/surface.c | 50 +++++++++++++++++------
dlls/d3dx9_36/tests/texture.c | 74 +++++++++++++++++++++++++++++------
dlls/d3dx9_36/texture.c | 19 +++++++--
4 files changed, 118 insertions(+), 29 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h
index 52b0d80be0..f91916062d 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 dir_write) DECLSPEC_HIDDEN;
+HRESULT unlock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock,
+ IDirect3DSurface9 *temp_surface, BOOL dir_write) 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 83c6f6dd4d..cf632a4c23 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -199,49 +199,73 @@ 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 dir_write)
{
IDirect3DDevice9 *device;
D3DSURFACE_DESC desc;
+ DWORD lock_flag;
HRESULT hr;
+ lock_flag = dir_write ? D3DLOCK_DISCARD : D3DLOCK_READONLY;
*temp_surface = NULL;
- if (FAILED(IDirect3DSurface9_LockRect(surface, lock, NULL, D3DLOCK_READONLY)))
+ if (FAILED(IDirect3DSurface9_LockRect(surface, lock, NULL, lock_flag)))
{
IDirect3DSurface9_GetDevice(surface, &device);
IDirect3DSurface9_GetDesc(surface, &desc);
- if (FAILED(IDirect3DDevice9_CreateRenderTarget(device, desc.Width, desc.Height,
- desc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, temp_surface, NULL)))
+
+ hr = dir_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, dir_write %#x, width %u, height %u.\n",
+ surface, desc.Format, desc.Usage, desc.Pool, dir_write, desc.Width, desc.Height);
IDirect3DDevice9_Release(device);
return D3DERR_INVALIDCALL;
}
- if (SUCCEEDED(hr = IDirect3DDevice9_StretchRect(device, surface, NULL, *temp_surface, NULL, D3DTEXF_NONE)))
- hr = IDirect3DSurface9_LockRect(*temp_surface, lock, NULL, D3DLOCK_READONLY);
+ if (dir_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, dir_write %#x, usage %#x, pool %#x.\n",
+ surface, dir_write, desc.Usage, desc.Pool);
IDirect3DSurface9_Release(*temp_surface);
*temp_surface = NULL;
return D3DERR_INVALIDCALL;
}
+ TRACE("Created temporary surface %p.\n", surface);
}
return D3D_OK;
}
-static HRESULT unlock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock,
- IDirect3DSurface9 *temp_surface)
+HRESULT unlock_surface(IDirect3DSurface9 *surface, D3DLOCKED_RECT *lock,
+ IDirect3DSurface9 *temp_surface, BOOL dir_write)
{
+ IDirect3DDevice9 *device;
HRESULT hr = D3D_OK;
if (!temp_surface)
return IDirect3DSurface9_UnlockRect(surface);
IDirect3DSurface9_UnlockRect(temp_surface);
+ if (dir_write)
+ {
+ IDirect3DSurface9_GetDevice(surface, &device);
+ if (FAILED(hr = IDirect3DDevice9_UpdateSurface(device, temp_surface, NULL, surface, NULL)))
+ {
+ WARN("UpdateSurface failed, hr %#x, surface %p, temp_surface %p.\n",
+ hr, surface, temp_surface);
+ hr = D3DERR_INVALIDCALL;
+ }
+ IDirect3DDevice9_Release(device);
+ }
IDirect3DSurface9_Release(temp_surface);
return hr;
}
@@ -2026,13 +2050,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 79cddc73ab..60800a32d0 100644
--- a/dlls/d3dx9_36/tests/texture.c
+++ b/dlls/d3dx9_36/tests/texture.c
@@ -1007,26 +1007,55 @@ 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, "IDirect3DDevice9_CreateTexture failed, 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, "D3DXFillTexture() failed, 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);
+ IDirect3DSurface9 *src_surface, *temp_surface;
+
+ hr = IDirect3DTexture9_GetSurfaceLevel(tex, m, &src_surface);
+ ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr %#x.\n", hr);
+ temp_surface = src_surface;
+
+ if (FAILED(hr = IDirect3DSurface9_LockRect(src_surface, &lock_rect, NULL, D3DLOCK_READONLY)))
+ {
+ hr = IDirect3DDevice9_CreateRenderTarget(device, size, size,
+ D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &temp_surface, NULL);
+ ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, temp_surface, NULL, D3DTEXF_NONE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed, hr %#x.\n", hr);
+ hr = IDirect3DSurface9_LockRect(temp_surface, &lock_rect, NULL, D3DLOCK_READONLY);
+ ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr %#x.\n", hr);
+ }
+
if (SUCCEEDED(hr))
{
pitch = lock_rect.Pitch / sizeof(DWORD);
@@ -1047,19 +1076,38 @@ static void test_D3DXFillTexture(IDirect3DDevice9 *device)
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);
+ "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 /* unsupported format. */
+ ok(hr == D3D_OK, "D3DXFillTexture returned %#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, "D3DXFillTexture returned %#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 0f53d95bf1..5edc98b361 100644
--- a/dlls/d3dx9_36/texture.c
+++ b/dlls/d3dx9_36/texture.c
@@ -1331,6 +1331,9 @@ HRESULT WINAPI D3DXFillTexture(struct IDirect3DTexture9 *texture, LPD3DXFILL2D f
D3DXVECTOR2 coord, size;
const struct pixel_format_desc *format;
BYTE *data;
+ IDirect3DSurface9 *surface, *temp_surface;
+
+ TRACE("texture %p, function %p, funcdata %p.\n", texture, function, funcdata);
if (texture == NULL || function == NULL)
return D3DERR_INVALIDCALL;
@@ -1345,12 +1348,17 @@ HRESULT WINAPI D3DXFillTexture(struct IDirect3DTexture9 *texture, LPD3DXFILL2D f
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)))
+ if (FAILED(IDirect3DTexture9_GetSurfaceLevel(texture, m, &surface)))
return D3DERR_INVALIDCALL;
+ if (FAILED(lock_surface(surface, &lock_rect, &temp_surface, TRUE)))
+ {
+ IDirect3DSurface9_Release(surface);
+ return D3DERR_INVALIDCALL;
+ }
size.x = 1.0f / desc.Width;
size.y = 1.0f / desc.Height;
@@ -1372,7 +1380,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(unlock_surface(surface, &lock_rect, temp_surface, TRUE)))
+ {
+ IDirect3DSurface9_Release(surface);
+ return D3DERR_INVALIDCALL;
+ }
+ IDirect3DSurface9_Release(surface);
}
return D3D_OK;
--
2.20.1
More information about the wine-devel
mailing list