This patch series adds quite a few new tests for saving to image file formats that aren't DDS, and adds partial support for saving surfaces to targa files.
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/surface.c | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 80343934cea..e6a7d490ac3 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3852,6 +3852,11 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) struct dds_header header; BYTE *data; } *dds; + struct + { + struct tga_header header; + BYTE *data; + } *tga; IDirect3DSurface9 *surface; IDirect3DTexture9 *texture; unsigned int i, x, y; @@ -3934,6 +3939,39 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, FALSE); ID3DXBuffer_Release(buffer);
+ /* Test saved targa file headers. */ + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_TGA, surface, NULL, NULL); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + tga = ID3DXBuffer_GetBufferPointer(buffer); + ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length + (4 * 4 * 4)), "Unexpected buffer size %lu.\n", + ID3DXBuffer_GetBufferSize(buffer)); + ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); + ok(tga->header.height == 4, "Got unexpected height %u.\n", tga->header.height); + ok(tga->header.width == 4, "Got unexpected width %u.\n", tga->header.width); + ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); + ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); + ID3DXBuffer_Release(buffer); + } + + /* Size 0 rectangle. */ + SetRectEmpty(&rect); + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_TGA, surface, NULL, &rect); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + tga = ID3DXBuffer_GetBufferPointer(buffer); + ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length), "Unexpected buffer size %lu.\n", + ID3DXBuffer_GetBufferSize(buffer)); + ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); + ok(!tga->header.height, "Got unexpected height %u.\n", tga->header.height); + ok(!tga->header.width, "Got unexpected width %u.\n", tga->header.width); + ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); + ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); + ID3DXBuffer_Release(buffer); + } + IDirect3DSurface9_Release(surface);
for (i = 0; i < ARRAY_SIZE(test_access_types); ++i)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/surface.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index e6a7d490ac3..31f09cb0600 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3857,10 +3857,11 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) struct tga_header header; BYTE *data; } *tga; + ID3DXBuffer *buffer, *buffer2; IDirect3DSurface9 *surface; IDirect3DTexture9 *texture; unsigned int i, x, y; - ID3DXBuffer *buffer; + D3DXIMAGE_INFO info; HRESULT hr; RECT rect;
@@ -3972,6 +3973,26 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) ID3DXBuffer_Release(buffer); }
+ /* Saving as D3DXIFF_DIB actually saves as a BMP. */ + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DIB, surface, NULL, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = D3DXSaveSurfaceToFileInMemory(&buffer2, D3DXIFF_BMP, surface, NULL, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = D3DXGetImageInfoFromFileInMemory(ID3DXBuffer_GetBufferPointer(buffer), ID3DXBuffer_GetBufferSize(buffer), &info); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(info.ImageFileFormat == D3DXIFF_BMP, "Unexpected ImageFileFormat %d.\n", info.ImageFileFormat); + todo_wine ok(ID3DXBuffer_GetBufferSize(buffer) == ID3DXBuffer_GetBufferSize(buffer2), "Unexpected buffer size.\n"); + if (ID3DXBuffer_GetBufferSize(buffer) == ID3DXBuffer_GetBufferSize(buffer2)) + { + ok(!memcmp(ID3DXBuffer_GetBufferPointer(buffer), ID3DXBuffer_GetBufferPointer(buffer2), ID3DXBuffer_GetBufferSize(buffer)), + "Files do not match.\n"); + } + + ID3DXBuffer_Release(buffer); + ID3DXBuffer_Release(buffer2); + IDirect3DSurface9_Release(surface);
for (i = 0; i < ARRAY_SIZE(test_access_types); ++i)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/surface.c | 644 ++++++++++++++++++++++++++++++++++ 1 file changed, 644 insertions(+)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 31f09cb0600..5ac4d083a96 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3826,6 +3826,649 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) } }
+static BOOL is_dxt_d3dformat(D3DFORMAT fmt) +{ + return (fmt & 0x00ffffff) == MAKEFOURCC('D','X','T',0); +} + +static void test_save_surface_iffs(IDirect3DDevice9 *device) +{ + static const D3DXIMAGE_FILEFORMAT test_iff[] = { D3DXIFF_BMP, D3DXIFF_JPG, D3DXIFF_TGA, D3DXIFF_PNG, + D3DXIFF_PPM, D3DXIFF_DIB, D3DXIFF_HDR, D3DXIFF_PFM }; + static const char *test_iff_str[] = { "D3DXIFF_BMP", "D3DXIFF_JPG", "D3DXIFF_TGA", "D3DXIFF_PNG", + "D3DXIFF_PPM", "D3DXIFF_DIB", "D3DXIFF_HDR", "D3DXIFF_PFM" }; + static const struct + { + D3DFORMAT format; + const PALETTEENTRY *palette; + struct + { + HRESULT hr; + D3DFORMAT format; + BOOL todo_hr; + BOOL todo_format; + } + iff_expected[8]; + uint8_t init_pixel_value; + } iff_tests[] = { + { D3DFMT_P8, test_palette, + { { D3D_OK, D3DFMT_P8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_P8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A8P8, test_palette, + { { D3D_OK, D3DFMT_P8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_P8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_P8, NULL, + { { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A8P8, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A8P8, NULL, + { { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, 0xff + }, + { D3DFMT_R8G8B8, NULL, + { { D3D_OK, D3DFMT_R8G8B8, }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + /* + * We don't match formats here because we encode our BMP headers + * differently. Native encodes with the same header as + * D3DFMT_X8R8G8B8, it just sets the values in the alpha channel. The + * format is distinguished by checking the image. We encode a bitmap + * V4 header with a dedicated alpha mask, so we'll always report + * D3DFMT_A8R8G8B8, regardless of whether or not any alpha channel + * values are non-zero. + */ + { D3DFMT_A8R8G8B8, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + /* + * Same as decoding for BMP/DIB, if the alpha channel is set to a + * non-zero value on any pixel we get a different format. + */ + { D3DFMT_A8R8G8B8, NULL, + { { D3D_OK, D3DFMT_A8R8G8B8 }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8 }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, 0xff + }, + { D3DFMT_X8R8G8B8, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + /* + * Unlike D3DFMT_A8R8G8B8, even if the alpha channel is all 0, + * D3DFMT_A8B8G8R8 doesn't get replaced with D3DFMT_X8B8G8R8 + * for BMP/DIB. + */ + { D3DFMT_A8B8G8R8, NULL, + { { D3D_OK, D3DFMT_A8B8G8R8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8B8G8R8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_X8B8G8R8, NULL, + { { D3D_OK, D3DFMT_X8B8G8R8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8B8G8R8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_R5G6B5, NULL, + { { D3D_OK, D3DFMT_R5G6B5, }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R5G6B5, }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_X1R5G5B5, NULL, + { { D3D_OK, D3DFMT_X1R5G5B5, }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X1R5G5B5, }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A1R5G5B5, NULL, + { { D3D_OK, D3DFMT_A1R5G5B5, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A1R5G5B5, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_R3G3B2, NULL, + { { D3D_OK, D3DFMT_P8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_P8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A8R3G3B2, NULL, + { { D3D_OK, D3DFMT_A8R3G3B2, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R3G3B2, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A4R4G4B4, NULL, + { { D3D_OK, D3DFMT_A4R4G4B4, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A4R4G4B4, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_X4R4G4B4, NULL, + { { D3D_OK, D3DFMT_X4R4G4B4, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X4R4G4B4, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A2R10G10B10, NULL, + { { D3D_OK, D3DFMT_A2R10G10B10, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A2R10G10B10, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A2B10G10R10, NULL, + { { D3D_OK, D3DFMT_A2B10G10R10, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A2B10G10R10, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A16B16G16R16, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8 }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16 }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_G16R16, NULL, + { { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A8, NULL, + { { D3D_OK, D3DFMT_A8R3G3B2, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R3G3B2, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A8L8, NULL, + { { D3D_OK, D3DFMT_A8L8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8L8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A4L4, NULL, + { { D3D_OK, D3DFMT_A4R4G4B4, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A4R4G4B4, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + /* + * For BMP/DIB, this ends up as a paletted bitmap file where the + * palette consists of RGB values of 0x00->0xff. Essentially, the luma + * value acts as an index into this palette. Weird that there are L16 + * and A8L8 representations, but this is done in a unique way. + */ + { D3DFMT_L8, NULL, + { { D3D_OK, D3DFMT_P8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_P8, .todo_format = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_L16, NULL, + { { D3D_OK, D3DFMT_L16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_L16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_DXT1, NULL, + { { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_DXT2, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_DXT2, NULL, + { { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, 0xff + }, + { D3DFMT_DXT3, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_DXT4, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_DXT5, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_R16F, NULL, + { { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_G16R16F, NULL, + { { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A16B16G16R16F, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_R32F, NULL, + { { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_G32R32F, NULL, + { { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A32B32G32R32F, NULL, + { { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A16B16G16R16, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_Q8W8V8U8, NULL, + { { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + }, + }, + { D3DFMT_V8U8, NULL, + { { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + }, + }, + { D3DFMT_V16U16, NULL, + { { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + }, + }, + { D3DFMT_X8L8V8U8, NULL, + { { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + }, + }, + { D3DFMT_A2W10V10U10, NULL, + { { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + }, + }, + { D3DFMT_Q16W16V16U16, NULL, + { { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + { D3DERR_INVALIDCALL, .todo_hr = TRUE }, + }, + }, + { D3DFMT_R8G8_B8G8, NULL, + { { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_G8R8_G8B8, NULL, + { { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_UYVY, NULL, + { { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + { D3DFMT_YUY2, NULL, + { { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE }, + }, + }, + }; + IDirect3DSurface9 *surface; + ID3DXBuffer *buffer; + unsigned int i, j; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(iff_tests); ++i) + { + D3DLOCKED_RECT lockrect; + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, iff_tests[i].format, + D3DPOOL_SCRATCH, &surface, NULL); + if (FAILED(hr)) + { + skip("Couldn't create surface for format %#x.\n", iff_tests[i].format); + continue; + } + + hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, 0); + if (SUCCEEDED(hr)) + { + const uint32_t tmp_height = is_dxt_d3dformat(iff_tests[i].format) ? 1 : 4; + + for (j = 0; j < tmp_height; ++j) + memset(((uint8_t *)lockrect.pBits) + (j * lockrect.Pitch), iff_tests[i].init_pixel_value, lockrect.Pitch); + IDirect3DSurface9_UnlockRect(surface); + } + + winetest_push_context("Test %u (%s)", i, debug_d3dformat(iff_tests[i].format)); + for (j = 0; j < ARRAY_SIZE(test_iff); ++j) + { + winetest_push_context("File format %u (%s)", j, test_iff_str[j]); + + buffer = NULL; + hr = D3DXSaveSurfaceToFileInMemory(&buffer, test_iff[j], surface, iff_tests[i].palette, NULL); + todo_wine_if(iff_tests[i].iff_expected[j].todo_hr) ok(hr == iff_tests[i].iff_expected[j].hr, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + D3DXIMAGE_INFO info = { 0 }; + + hr = D3DXGetImageInfoFromFileInMemory(ID3DXBuffer_GetBufferPointer(buffer), ID3DXBuffer_GetBufferSize(buffer), &info); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + todo_wine_if(iff_tests[i].iff_expected[j].todo_format) ok(info.Format == iff_tests[i].iff_expected[j].format, + "Unexpected image format %u (%s), expected %u (%s).\n", info.Format, debug_d3dformat(info.Format), + iff_tests[i].iff_expected[j].format, debug_d3dformat(iff_tests[i].iff_expected[j].format)); + ID3DXBuffer_Release(buffer); + } + winetest_pop_context(); + } + + IDirect3DSurface9_Release(surface); + winetest_pop_context(); + } +} + static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) { static const struct dds_pixel_format d3dfmt_a8r8g8b8_pf = { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, @@ -4017,6 +4660,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) }
test_save_surface_to_dds(device); + test_save_surface_iffs(device); }
static void test_D3DXSaveSurfaceToFile(IDirect3DDevice9 *device)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 124 ++++++++++++++++++++++------------ dlls/d3dx9_36/tests/surface.c | 59 ++++++++-------- 2 files changed, 109 insertions(+), 74 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 9d2dc96a979..472f26cec20 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -153,6 +153,33 @@ struct dds_header DWORD reserved2; };
+#define IMAGETYPE_COLORMAPPED 1 +#define IMAGETYPE_TRUECOLOR 2 +#define IMAGETYPE_GRAYSCALE 3 +#define IMAGETYPE_MASK 0x07 +#define IMAGETYPE_RLE 8 + +#define IMAGE_RIGHTTOLEFT 0x10 +#define IMAGE_TOPTOBOTTOM 0x20 + +#include "pshpack1.h" +struct tga_header +{ + uint8_t id_length; + uint8_t color_map_type; + uint8_t image_type; + uint16_t color_map_firstentry; + uint16_t color_map_length; + uint8_t color_map_entrysize; + uint16_t xorigin; + uint16_t yorigin; + uint16_t width; + uint16_t height; + uint8_t depth; + uint8_t image_descriptor; +}; +#include "poppack.h" + HRESULT lock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, D3DLOCKED_RECT *lock, IDirect3DSurface9 **temp_surface, BOOL write) { @@ -505,19 +532,36 @@ static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const switch (file_format) { case D3DXIFF_DDS: - { - struct dds_header *header; - uint32_t header_size; - hr = dds_pixel_format_from_d3dx_pixel_format_id(NULL, dst_format); if (FAILED(hr)) return hr; + break;
- dst_fmt_desc = get_d3dx_pixel_format_info(dst_format); - hr = d3dx_calculate_pixels_size(dst_format, src_pixels->size.width, src_pixels->size.height, &dst_row_pitch, - &dst_slice_pitch); - if (FAILED(hr)) - return hr; + case D3DXIFF_TGA: + if ((dst_format != D3DX_PIXEL_FORMAT_B8G8R8_UNORM) && (dst_format != D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM)) + { + FIXME("Format replacement for TGA files is currently unimplemented.\n"); + return E_NOTIMPL; + } + break; + + default: + assert(0 && "Unexpected file format."); + return E_FAIL; + } + + dst_fmt_desc = get_d3dx_pixel_format_info(dst_format); + hr = d3dx_calculate_pixels_size(dst_format, src_pixels->size.width, src_pixels->size.height, &dst_row_pitch, + &dst_slice_pitch); + if (FAILED(hr)) + return hr; + + switch (file_format) + { + case D3DXIFF_DDS: + { + struct dds_header *header; + uint32_t header_size;
header_size = is_index_format(dst_fmt_desc) ? sizeof(*header) + DDS_PALETTE_SIZE : sizeof(*header); hr = D3DXCreateBuffer(dst_slice_pitch + header_size, &buffer); @@ -535,9 +579,30 @@ static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const break; }
+ case D3DXIFF_TGA: + { + struct tga_header *header; + + hr = D3DXCreateBuffer(dst_slice_pitch + sizeof(*header), &buffer); + if (FAILED(hr)) + return hr; + + header = ID3DXBuffer_GetBufferPointer(buffer); + pixels = (uint8_t *)ID3DXBuffer_GetBufferPointer(buffer) + sizeof(*header); + + memset(header, 0, sizeof(*header)); + header->image_type = IMAGETYPE_TRUECOLOR; + header->width = src_pixels->size.width; + header->height = src_pixels->size.height; + header->image_descriptor = IMAGE_TOPTOBOTTOM; + header->depth = dst_fmt_desc->bytes_per_pixel * 8; + if (dst_fmt_desc->format == D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM) + header->image_descriptor |= 0x08; + break; + } + default: - assert(0 && "Unexpected file format."); - return E_FAIL; + break; }
if (src_pixels->size.width != 0 && src_pixels->size.height != 0) @@ -559,8 +624,8 @@ exit: return hr; }
-static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, - const PALETTEENTRY *src_palette, const RECT *src_rect) +static HRESULT save_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, + const PALETTEENTRY *src_palette, const RECT *src_rect, D3DXIMAGE_FILEFORMAT file_format) { const struct pixel_format_desc *src_fmt_desc; D3DSURFACE_DESC src_surface_desc; @@ -610,7 +675,7 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSur return hr; }
- hr = d3dx_save_pixels_to_memory(&src_pixels, src_fmt_desc, D3DXIFF_DDS, &buffer); + hr = d3dx_save_pixels_to_memory(&src_pixels, src_fmt_desc, file_format, &buffer); if (FAILED(hr)) { unlock_surface(src_surface, NULL, temp_surface, FALSE); @@ -1085,33 +1150,6 @@ static enum d3dx_pixel_format_id d3dx_get_tga_format_for_bpp(uint8_t bpp) } }
-#define IMAGETYPE_COLORMAPPED 1 -#define IMAGETYPE_TRUECOLOR 2 -#define IMAGETYPE_GRAYSCALE 3 -#define IMAGETYPE_MASK 0x07 -#define IMAGETYPE_RLE 8 - -#define IMAGE_RIGHTTOLEFT 0x10 -#define IMAGE_TOPTOBOTTOM 0x20 - -#include "pshpack1.h" -struct tga_header -{ - uint8_t id_length; - uint8_t color_map_type; - uint8_t image_type; - uint16_t color_map_firstentry; - uint16_t color_map_length; - uint8_t color_map_entrysize; - uint16_t xorigin; - uint16_t yorigin; - uint16_t width; - uint16_t height; - uint8_t depth; - uint8_t image_descriptor; -}; -#include "poppack.h" - static HRESULT d3dx_image_tga_rle_decode_row(const uint8_t **src, uint32_t src_bytes_left, uint32_t row_width, uint32_t bytes_per_pixel, uint8_t *dst_row) { @@ -2993,10 +3031,10 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE container_format = &GUID_ContainerFormatJpeg; break; case D3DXIFF_DDS: - return save_dds_surface_to_memory(dst_buffer, src_surface, src_palette, src_rect); + case D3DXIFF_TGA: + return save_surface_to_memory(dst_buffer, src_surface, src_palette, src_rect, file_format); case D3DXIFF_HDR: case D3DXIFF_PFM: - case D3DXIFF_TGA: case D3DXIFF_PPM: FIXME("File format %#x is not supported yet\n", file_format); return E_NOTIMPL; diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 5ac4d083a96..9e64a205a25 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3909,7 +3909,7 @@ static void test_save_surface_iffs(IDirect3DDevice9 *device) { D3DFMT_R8G8B8, NULL, { { D3D_OK, D3DFMT_R8G8B8, }, { D3D_OK, D3DFMT_X8R8G8B8 }, - { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8 }, { D3D_OK, D3DFMT_X8R8G8B8 }, { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, { D3D_OK, D3DFMT_R8G8B8, }, @@ -3929,7 +3929,7 @@ static void test_save_surface_iffs(IDirect3DDevice9 *device) { D3DFMT_A8R8G8B8, NULL, { { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, { D3D_OK, D3DFMT_X8R8G8B8 }, - { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8 }, { D3D_OK, D3DFMT_A8R8G8B8, }, { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, @@ -3944,7 +3944,7 @@ static void test_save_surface_iffs(IDirect3DDevice9 *device) { D3DFMT_A8R8G8B8, NULL, { { D3D_OK, D3DFMT_A8R8G8B8 }, { D3D_OK, D3DFMT_X8R8G8B8 }, - { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8 }, { D3D_OK, D3DFMT_A8R8G8B8, }, { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, { D3D_OK, D3DFMT_A8R8G8B8 }, @@ -4585,36 +4585,32 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
/* Test saved targa file headers. */ hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_TGA, surface, NULL, NULL); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - tga = ID3DXBuffer_GetBufferPointer(buffer); - ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length + (4 * 4 * 4)), "Unexpected buffer size %lu.\n", - ID3DXBuffer_GetBufferSize(buffer)); - ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); - ok(tga->header.height == 4, "Got unexpected height %u.\n", tga->header.height); - ok(tga->header.width == 4, "Got unexpected width %u.\n", tga->header.width); - ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); - ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); - ID3DXBuffer_Release(buffer); - } + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + tga = ID3DXBuffer_GetBufferPointer(buffer); + ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length + (4 * 4 * 4)), "Unexpected buffer size %lu.\n", + ID3DXBuffer_GetBufferSize(buffer)); + ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); + ok(tga->header.height == 4, "Got unexpected height %u.\n", tga->header.height); + ok(tga->header.width == 4, "Got unexpected width %u.\n", tga->header.width); + ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); + ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); + ID3DXBuffer_Release(buffer);
/* Size 0 rectangle. */ SetRectEmpty(&rect); hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_TGA, surface, NULL, &rect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - tga = ID3DXBuffer_GetBufferPointer(buffer); - ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length), "Unexpected buffer size %lu.\n", - ID3DXBuffer_GetBufferSize(buffer)); - ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); - ok(!tga->header.height, "Got unexpected height %u.\n", tga->header.height); - ok(!tga->header.width, "Got unexpected width %u.\n", tga->header.width); - ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); - ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); - ID3DXBuffer_Release(buffer); - } + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + tga = ID3DXBuffer_GetBufferPointer(buffer); + ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length), "Unexpected buffer size %lu.\n", + ID3DXBuffer_GetBufferSize(buffer)); + ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); + ok(!tga->header.height, "Got unexpected height %u.\n", tga->header.height); + ok(!tga->header.width, "Got unexpected width %u.\n", tga->header.width); + ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); + ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); + ID3DXBuffer_Release(buffer);
/* Saving as D3DXIFF_DIB actually saves as a BMP. */ hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DIB, surface, NULL, NULL); @@ -4738,10 +4734,11 @@ static void test_D3DXSaveSurfaceToFile(IDirect3DDevice9 *device) { hr = D3DXSaveSurfaceToFileA("saved_surface.ppm", D3DXIFF_PPM, surface, NULL, NULL); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - hr = D3DXSaveSurfaceToFileA("saved_surface.tga", D3DXIFF_TGA, surface, NULL, NULL); - ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); }
+ hr = D3DXSaveSurfaceToFileA("saved_surface.tga", D3DXIFF_TGA, surface, NULL, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + hr = D3DXSaveSurfaceToFileA("saved_surface.dds", D3DXIFF_DDS, surface, NULL, NULL); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
}
}
+static BOOL is_dxt_d3dformat(D3DFORMAT fmt) +{
- return (fmt & 0x00ffffff) == MAKEFOURCC('D','X','T',0);
+}
+static void test_save_surface_iffs(IDirect3DDevice9 *device) +{
- static const D3DXIMAGE_FILEFORMAT test_iff[] = { D3DXIFF_BMP, D3DXIFF_JPG, D3DXIFF_TGA, D3DXIFF_PNG,
D3DXIFF_PPM, D3DXIFF_DIB, D3DXIFF_HDR, D3DXIFF_PFM };
- static const char *test_iff_str[] = { "D3DXIFF_BMP", "D3DXIFF_JPG", "D3DXIFF_TGA", "D3DXIFF_PNG",
"D3DXIFF_PPM", "D3DXIFF_DIB", "D3DXIFF_HDR", "D3DXIFF_PFM" };
It might be nicer to have that together as an array of structures: ```suggestion:-3+0 static const struct { D3DXIMAGE_FILEFORMAT format; const char *name; } test_iffs[] = { {D3DXIFF_BMP, "D3DXIFF_BMP"}, {D3DXIFF_JPG, "D3DXIFF_JPG"}, ... ```
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
},
},
/*
* Same as decoding for BMP/DIB, if the alpha channel is set to a
* non-zero value on any pixel we get a different format.
*/
{ D3DFMT_A8R8G8B8, NULL,
{ { D3D_OK, D3DFMT_A8R8G8B8 },
{ D3D_OK, D3DFMT_X8R8G8B8 },
{ D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A8R8G8B8, },
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A8R8G8B8 },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
}, 0xff
Let's put the initial value before the expected results, the difference between this block and the previous one wasn't immediately noticeable to me (the comment helped sort it out quickly enough, but still I think it would be an improvement). I'd even explicitly write out the value `0` instead of e.g. using designated initializers for the `expected` part.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
*/
{ D3DFMT_A8R8G8B8, NULL,
{ { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE },
{ D3D_OK, D3DFMT_X8R8G8B8 },
{ D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A8R8G8B8, },
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
},
},
/*
* Same as decoding for BMP/DIB, if the alpha channel is set to a
* non-zero value on any pixel we get a different format.
*/
This comment seems a bit confusing to me, is it missing an "above" or something? Either way, maybe the previous comment is enough already.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
},
},
{ D3DFMT_DXT2, NULL,
{ { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
}, 0xff
},
I assume the same (i.e. non-zero alpha values mandating alpha in the BMP image formats) applies to the other compressed texture formats, right?
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
{ D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
},
},
{ D3DFMT_YUY2, NULL,
{ { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
{ D3D_OK, D3DFMT_A32B32G32R32F, .todo_hr = TRUE },
},
},
Oh, very interesting! I don't know if I'd have thought of testing those.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
buffer = NULL;
hr = D3DXSaveSurfaceToFileInMemory(&buffer, test_iff[j], surface, iff_tests[i].palette, NULL);
todo_wine_if(iff_tests[i].iff_expected[j].todo_hr) ok(hr == iff_tests[i].iff_expected[j].hr, "Unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
{
D3DXIMAGE_INFO info = { 0 };
hr = D3DXGetImageInfoFromFileInMemory(ID3DXBuffer_GetBufferPointer(buffer), ID3DXBuffer_GetBufferSize(buffer), &info);
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
todo_wine_if(iff_tests[i].iff_expected[j].todo_format) ok(info.Format == iff_tests[i].iff_expected[j].format,
"Unexpected image format %u (%s), expected %u (%s).\n", info.Format, debug_d3dformat(info.Format),
iff_tests[i].iff_expected[j].format, debug_d3dformat(iff_tests[i].iff_expected[j].format));
ID3DXBuffer_Release(buffer);
}
winetest_pop_context();
}
There are some very long lines here, in general let's try to stay under 100-120 columns (no specific hard limit, more of a rough guideline).
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
DWORD reserved2;
};
+#define IMAGETYPE_COLORMAPPED 1 +#define IMAGETYPE_TRUECOLOR 2 +#define IMAGETYPE_GRAYSCALE 3 +#define IMAGETYPE_MASK 0x07 +#define IMAGETYPE_RLE 8
+#define IMAGE_RIGHTTOLEFT 0x10 +#define IMAGE_TOPTOBOTTOM 0x20
Minor, but it's probably better to prefix those with `TGA_` or something as this file is not limited to just the `D3DXIFF_TGA` format.
I only had style comments I think, it largely looks good. I really like the tests in patch 3/4!
Nikolay pointed out to me that this also fails compilation with clang: https://gitlab.winehq.org/cmcadams/wine/-/jobs/135360