Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- This is only relevant for the direct copy code path (where source and destination formats match), the other path has another, more thorough, check already.
The patch from Paul prompted me to recover and clean up a bunch of patches that have been stuck in my queue for years. So thank you Paul I guess :D
dlls/d3dx9_36/surface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 8e9b834d882..00a7694ab0b 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1890,9 +1890,9 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
srcformatdesc = get_format_info(src_format); destformatdesc = get_format_info(surfdesc.Format); - if (srcformatdesc->type == FORMAT_UNKNOWN || destformatdesc->type == FORMAT_UNKNOWN) + if (srcformatdesc->type == FORMAT_UNKNOWN) { - FIXME("Unsupported pixel format conversion %#x -> %#x\n", src_format, surfdesc.Format); + FIXME("Unsupported format %#x.\n", src_format); return E_NOTIMPL; }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/surface.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 00a7694ab0b..39dfbf16ac6 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1905,11 +1905,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, && color_key == 0) /* Simple copy. */ { if (src_rect->left & (srcformatdesc->block_width - 1) - || src_rect->top & (srcformatdesc->block_height - 1) - || (src_rect->right & (srcformatdesc->block_width - 1) - && src_size.width != surfdesc.Width) - || (src_rect->bottom & (srcformatdesc->block_height - 1) - && src_size.height != surfdesc.Height)) + || src_rect->top & (srcformatdesc->block_height - 1)) { WARN("Source rect %s is misaligned.\n", wine_dbgstr_rect(src_rect)); unlock_surface(dst_surface, dst_rect, surface, FALSE);
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/tests/surface.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 4a10492a08f..2f8149fd01a 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -167,6 +167,20 @@ static const unsigned char dds_volume_map[] = { 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x84,0xef,0x7b,0xaa,0xab,0xab,0xab };
+/* 4x2 dxt5 */ +static const BYTE dds_dxt5[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x02,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +}; + static HRESULT create_file(const char *filename, const unsigned char *data, const unsigned int size) { DWORD received; @@ -1269,6 +1283,26 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) 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"); + + SetRect(&rect, 0, 0, 4, 2); + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, &rect, surf, NULL, &rect, D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, &rect, &dds_dxt5[128], + D3DFMT_DXT5, 16, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + check_release((IUnknown *)newsurf, 1); + check_release((IUnknown *)tex, 0); + + /* Test a rect larger than but not an integer multiple of the block size. */ + hr = IDirect3DDevice9_CreateTexture(device, 4, 8, 1, 0, D3DFMT_DXT5, D3DPOOL_SYSTEMMEM, &tex, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + SetRect(&rect, 0, 0, 4, 6); + hr = D3DXLoadSurfaceFromMemory(newsurf, NULL, &rect, &dds_dxt5[112], + D3DFMT_DXT5, 16, NULL, &rect, D3DX_FILTER_POINT, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + check_release((IUnknown*)newsurf, 1); check_release((IUnknown*)tex, 0); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- This shows that the texture is stretched to the block size (i.e. minimum texture size) rather than just loading the data unchanged.
dlls/d3dx9_36/tests/texture.c | 79 +++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 6c25a158118..5c641913ce5 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -87,6 +87,20 @@ static const unsigned char dds_volume_map[] = { 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x84,0xef,0x7b,0xaa,0xab,0xab,0xab };
+/* 4x2 dxt5 */ +static const BYTE dds_dxt5[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x02,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +}; + static const unsigned char png_grayscale[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, @@ -400,6 +414,15 @@ static void test_D3DXCheckTextureRequirements(IDirect3DDevice9 *device) ok(height == 4, "Returned height %d, expected %d\n", height, 4); ok(mipmaps == 1, "Returned mipmaps %d, expected %d\n", mipmaps, 1); ok(format == D3DFMT_DXT5, "Returned format %u, expected %u\n", format, D3DFMT_DXT5); + + width = 4; + height = 2; + hr = D3DXCheckTextureRequirements(device, &width, &height, &mipmaps, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(width == 4, "Got unexpected width %u.\n", width); + ok(height == 4, "Got unexpected height %u.\n", height); + ok(mipmaps == 1, "Got unexpected mipmap level count %u.\n", mipmaps); + ok(format == D3DFMT_DXT5, "Got unexpected format %u.\n", format); } else { @@ -1526,13 +1549,21 @@ static void test_D3DXFillVolumeTexture(IDirect3DDevice9 *device)
static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) { - HRESULT hr; + static const DWORD dds_dxt5_expected[] = + { + 0xff7b207b, 0xff7b207b, 0xff84df7b, 0xff84df7b, + 0xff7b207b, 0xff7b207b, 0xff84df7b, 0xff84df7b, + 0xff7b207b, 0xff7b207b, 0xff84df7b, 0xff84df7b, + 0xff7b207b, 0xff7b207b, 0xff84df7b, 0xff84df7b, + }; + IDirect3DSurface9 *surface, *uncompressed_surface; IDirect3DTexture9 *texture; + D3DLOCKED_RECT lock_rect; D3DRESOURCETYPE type; D3DSURFACE_DESC desc; - D3DLOCKED_RECT lock_rect; - int i; + unsigned int i, x, y; DWORD level_count; + HRESULT hr;
hr = D3DXCreateTextureFromFileInMemory(device, dds_16bit, sizeof(dds_16bit), &texture); ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); @@ -1568,8 +1599,50 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) IDirect3DTexture9_UnlockRect(texture, 0); } IDirect3DTexture9_Release(texture); + }
+ /* Test with a DXT5 texture smaller than the block size. */ + hr = D3DXCreateTextureFromFileInMemory(device, dds_dxt5, sizeof(dds_dxt5), &texture); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr) && has_2d_dxt5) + { + type = IDirect3DTexture9_GetType(texture); + ok(type == D3DRTYPE_TEXTURE, "Got unexpected type %u.\n", type); + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(desc.Width == 4, "Got unexpected width %u.\n", desc.Width); + ok(desc.Height == 4, "Got unexpected height %u.\n", desc.Height); + + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, &uncompressed_surface, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = D3DXLoadSurfaceFromSurface(uncompressed_surface, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(uncompressed_surface, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + for (y = 0; y < 4; ++y) + { + for (x = 0; x < 4; ++x) + { + /* Use a large tolerance, decompression + stretching + + * compression + decompression again introduce quite a bit of + * precision loss. */ + ok(compare_color(((DWORD *)lock_rect.pBits)[lock_rect.Pitch / 4 * y + x], + dds_dxt5_expected[y * 4 + x], 32), + "Color at position %u, %u is 0x%08x, expected 0x%08x.\n", + x, y, ((DWORD *)lock_rect.pBits)[lock_rect.Pitch / 4 * y + x], + dds_dxt5_expected[y * 4 + x]); + } + } + hr = IDirect3DSurface9_UnlockRect(uncompressed_surface); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + IDirect3DSurface9_Release(uncompressed_surface); + IDirect3DSurface9_Release(surface); } + if (SUCCEEDED(hr)) + IDirect3DTexture9_Release(texture);
/* Volume textures work too. */ hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), &texture);
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/tests/texture.c | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+)
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 5c641913ce5..68bbd37f8ac 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -101,6 +101,22 @@ static const BYTE dds_dxt5[] = 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, };
+static const BYTE dds_dxt5_8_8[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x08,0x00,0x00,0x00, + 0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0xe0,0x07,0x05,0x05,0x50,0x50, + 0x3f,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x07,0x05,0x05,0x50,0x50, + 0x7f,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xf8,0xe0,0xff,0x05,0x05,0x50,0x50, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x05,0x05,0x50,0x50, +}; + static const unsigned char png_grayscale[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, @@ -1556,6 +1572,17 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) 0xff7b207b, 0xff7b207b, 0xff84df7b, 0xff84df7b, 0xff7b207b, 0xff7b207b, 0xff84df7b, 0xff84df7b, }; + static const DWORD dds_dxt5_8_8_expected[] = + { + 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x3f00ffff, 0x3f00ffff, 0x3fff0000, 0x3fff0000, + 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x3f00ffff, 0x3f00ffff, 0x3fff0000, 0x3fff0000, + 0x000000ff, 0x000000ff, 0x0000ff00, 0x0000ff00, 0x3fff0000, 0x3fff0000, 0x3f00ffff, 0x3f00ffff, + 0x000000ff, 0x000000ff, 0x0000ff00, 0x0000ff00, 0x3fff0000, 0x3fff0000, 0x3f00ffff, 0x3f00ffff, + 0x7fffff00, 0x7fffff00, 0x7fff00ff, 0x7fff00ff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0x7fffff00, 0x7fffff00, 0x7fff00ff, 0x7fff00ff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, + 0x7fff00ff, 0x7fff00ff, 0x7fffff00, 0x7fffff00, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, + 0x7fff00ff, 0x7fff00ff, 0x7fffff00, 0x7fffff00, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, + }; IDirect3DSurface9 *surface, *uncompressed_surface; IDirect3DTexture9 *texture; D3DLOCKED_RECT lock_rect; @@ -1644,6 +1671,45 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) if (SUCCEEDED(hr)) IDirect3DTexture9_Release(texture);
+ /* Test with a larger DXT5 texture. */ + hr = D3DXCreateTextureFromFileInMemory(device, dds_dxt5_8_8, sizeof(dds_dxt5_8_8), &texture); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + type = IDirect3DTexture9_GetType(texture); + ok(type == D3DRTYPE_TEXTURE, "Got unexpected type %u.\n", type); + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ok(desc.Width == 8, "Got unexpected width %u.\n", desc.Width); + ok(desc.Height == 8, "Got unexpected height %u.\n", desc.Height); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 8, 8, D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, &uncompressed_surface, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = D3DXLoadSurfaceFromSurface(uncompressed_surface, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDirect3DSurface9_LockRect(uncompressed_surface, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + for (y = 0; y < 8; ++y) + { + for (x = 0; x < 8; ++x) + { + ok(compare_color(((DWORD *)lock_rect.pBits)[lock_rect.Pitch / 4 * y + x], + dds_dxt5_8_8_expected[y * 8 + x], 0), + "Color at position %u, %u is 0x%08x, expected 0x%08x.\n", + x, y, ((DWORD *)lock_rect.pBits)[lock_rect.Pitch / 4 * y + x], + dds_dxt5_8_8_expected[y * 8 + x]); + } + } + hr = IDirect3DSurface9_UnlockRect(uncompressed_surface); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + } + + IDirect3DSurface9_Release(uncompressed_surface); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + /* Volume textures work too. */ hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), &texture); todo_wine_if (!has_2d_dxt3)