This is the first of 3 planned MRs reworking how `D3DXSaveSurfaceToFileInMemory()` functions, starting with DDS files.
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 23af0f6f816..f9d0fad1ad3 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -2895,9 +2895,10 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE
if (!dst_buffer || !src_surface) return D3DERR_INVALIDCALL;
- if (src_palette) + IDirect3DSurface9_GetDesc(src_surface, &src_surface_desc); + if (src_palette || is_index_format(get_format_info(src_surface_desc.Format))) { - FIXME("Saving surfaces with palettized pixel formats is not implemented yet\n"); + FIXME("Saving surfaces with palettized pixel formats is not implemented yet.\n"); return D3DERR_INVALIDCALL; }
@@ -2925,7 +2926,6 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE return D3DERR_INVALIDCALL; }
- IDirect3DSurface9_GetDesc(src_surface, &src_surface_desc); if (src_rect) { if (src_rect->left == src_rect->right || src_rect->top == src_rect->bottom)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/surface.c | 412 +++++++++++++++++++++++++++++++++- 1 file changed, 411 insertions(+), 1 deletion(-)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 98408d026ed..fa915715907 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -153,6 +153,7 @@ static HRESULT create_file(const char *filename, const unsigned char *data, cons
/* dds_header.caps */ #define DDSCAPS_ALPHA 0x00000002 +#define DDSCAPS_PALETTE 0x00000100 #define DDS_CAPS_TEXTURE 0x00001000 #define DDS_CAPS_COMPLEX 0x00000008
@@ -3444,8 +3445,367 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) if(testbitmap_ok) DeleteFileA("testbitmap.bmp"); }
+#define check_dds_pixel_format_struct(pixel_format, expected_pixel_format, wine_todo) \ + check_dds_pixel_format_struct_(__FILE__, __LINE__, pixel_format, expected_pixel_format, wine_todo) +static void check_dds_pixel_format_struct_(const char *file, uint32_t line, const struct dds_pixel_format *pixel_format, + const struct dds_pixel_format *expected_pixel_format, BOOL wine_todo) +{ + BOOL matched; + + matched = !memcmp(expected_pixel_format, pixel_format, sizeof(*pixel_format)); + todo_wine_if(wine_todo) ok_(file, line)(matched, "Got unexpected dds pixel format values.\n"); + if (matched) + return; + + todo_wine_if(wine_todo && pixel_format->flags != expected_pixel_format->flags) + ok_(file, line)(pixel_format->flags == expected_pixel_format->flags, "Unexpected DDS pixel format flags %#lx.\n", + pixel_format->flags); + todo_wine_if(wine_todo && pixel_format->fourcc != expected_pixel_format->fourcc) + ok_(file, line)(pixel_format->fourcc == expected_pixel_format->fourcc, "Unexpected DDS pixel format fourcc %#lx.\n", + pixel_format->fourcc); + todo_wine_if(wine_todo && pixel_format->bpp != expected_pixel_format->bpp) + ok_(file, line)(pixel_format->bpp == expected_pixel_format->bpp, "Unexpected DDS pixel format bpp %#lx.\n", + pixel_format->bpp); + todo_wine_if(wine_todo && pixel_format->rmask != expected_pixel_format->rmask) + ok_(file, line)(pixel_format->rmask == expected_pixel_format->rmask, "Unexpected DDS pixel format rmask %#lx.\n", + pixel_format->rmask); + todo_wine_if(wine_todo && pixel_format->gmask != expected_pixel_format->gmask) + ok_(file, line)(pixel_format->gmask == expected_pixel_format->gmask, "Unexpected DDS pixel format gmask %#lx.\n", + pixel_format->gmask); + todo_wine_if(wine_todo && pixel_format->bmask != expected_pixel_format->bmask) + ok_(file, line)(pixel_format->bmask == expected_pixel_format->bmask, "Unexpected DDS pixel format bmask %#lx.\n", + pixel_format->bmask); + todo_wine_if(wine_todo && pixel_format->amask != expected_pixel_format->amask) + ok_(file, line)(pixel_format->amask == expected_pixel_format->amask, "Unexpected DDS pixel format amask %#lx.\n", + pixel_format->amask); +} + +#define check_dds_header(header, flags, height, width, pitch, depth, mip_levels, pixel_format, caps, caps2, wine_todo) \ + check_dds_header_(__FILE__, __LINE__, header, flags, height, width, pitch, depth, mip_levels, pixel_format, \ + caps, caps2, wine_todo) +static void check_dds_header_(const char *file, uint32_t line, const struct dds_header *header, uint32_t flags, + uint32_t height, uint32_t width, uint32_t pitch, uint32_t depth, uint32_t mip_levels, + const struct dds_pixel_format *pixel_format, uint32_t caps, uint32_t caps2, BOOL wine_todo) +{ + const struct dds_header expected_header = { sizeof(*header), flags, height, width, pitch, depth, mip_levels, { 0 }, + *pixel_format, caps, caps2, 0, 0, 0 }; + BOOL matched; + + matched = !memcmp(&expected_header, header, sizeof(*header)); + todo_wine_if(wine_todo) ok_(file, line)(matched, "Got unexpected dds header values.\n"); + if (matched) + return; + + todo_wine_if(wine_todo && header->flags != flags) + ok_(file, line)(header->flags == flags, "Unexpected DDS header flags %#lx.\n", header->flags); + todo_wine_if(wine_todo && header->width != width) + ok_(file, line)(header->width == width, "Unexpected DDS header width %#lx.\n", header->width); + todo_wine_if(wine_todo && header->height != height) + ok_(file, line)(header->height == height, "Unexpected DDS header height %#lx.\n", header->height); + todo_wine_if(wine_todo && header->pitch_or_linear_size != pitch) + ok_(file, line)(header->pitch_or_linear_size == pitch, "Unexpected DDS header pitch %#lx.\n", header->pitch_or_linear_size); + todo_wine_if(wine_todo && header->depth != depth) + ok_(file, line)(header->depth == depth, "Unexpected DDS header depth %#lx.\n", header->depth); + todo_wine_if(wine_todo && header->miplevels != mip_levels) + ok_(file, line)(header->miplevels == mip_levels, "Unexpected DDS header mip levels %#lx.\n", header->miplevels); + ok_(file, line)(!memcmp(header->reserved, expected_header.reserved, sizeof(header->reserved)), + "Unexpected values in DDS header reserved field."); + check_dds_pixel_format_struct(&header->pixel_format, pixel_format, FALSE); + todo_wine_if(wine_todo && header->caps != caps) + ok_(file, line)(header->caps == caps, "Unexpected DDS header caps %#lx.\n", header->caps); + todo_wine_if(wine_todo && header->caps2 != caps2) + ok_(file, line)(header->caps2 == caps2, "Unexpected DDS header caps2 %#lx.\n", header->caps2); + ok_(file, line)(!header->caps3, "Unexpected DDS header caps3 %#lx.\n", header->caps3); + ok_(file, line)(!header->caps4, "Unexpected DDS header caps4 %#lx.\n", header->caps4); + ok_(file, line)(!header->reserved2, "Unexpected DDS header reserved2 %#lx.\n", header->reserved2); +} + +#define DDS_FILE_HEADER_SIZE (sizeof(uint32_t) + sizeof(struct dds_header)) +#define PALETTED_DDS_FILE_HEADER_SIZE (DDS_FILE_HEADER_SIZE + (sizeof(PALETTEENTRY) * 256)) +static void test_save_surface_to_dds(IDirect3DDevice9 *device) +{ + static const struct + { + D3DFORMAT format; + uint32_t width; + uint32_t height; + const PALETTEENTRY *palette; + + HRESULT expected_hr; + struct dds_pixel_format expected_pixel_format; + uint32_t expected_flags; + uint32_t expected_width; + uint32_t expected_height; + uint32_t expected_pitch; + uint32_t expected_depth; + uint32_t expected_mip_levels; + uint32_t expected_caps; + uint32_t expected_caps2; + uint32_t expected_buffer_size; + BOOL todo_hr; + BOOL todo_expected; + } dds_tests[] = { + { D3DFMT_P8, 4, 4, test_palette, D3D_OK, + { 32, DDS_PF_INDEXED, 0, 8, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_PALETTE), 0, + PALETTED_DDS_FILE_HEADER_SIZE + (4 * 4), .todo_hr = TRUE + }, + { D3DFMT_A8P8, 4, 4, test_palette, D3D_OK, + { 32, DDS_PF_INDEXED | DDS_PF_ALPHA, 0, 16, 0, 0, 0, 0xff00 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_PALETTE | DDSCAPS_ALPHA), 0, + PALETTED_DDS_FILE_HEADER_SIZE + (4 * 2 * 4), .todo_hr = TRUE + }, + /* If a palette isn't provided, d3dx converts to D3DFMT_A8R8G8B8. */ + { D3DFMT_P8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_hr = TRUE + }, + { D3DFMT_A8P8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_hr = TRUE + }, + { D3DFMT_A16B16G16R16, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_A16B16G16R16, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 8 * 4), + }, + { D3DFMT_V8U8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_BUMPDUDV, 0, 16, 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + }, + { D3DFMT_V16U16, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, + { D3DFMT_Q8W8V8U8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, + { D3DFMT_A2W10V10U10, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_BUMPDUDV | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + }, + { D3DFMT_X8L8V8U8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_BUMPLUMINANCE, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, + { D3DFMT_R5G6B5, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB, 0, 16, 0xf800, 0x07e0, 0x001f, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + }, + { D3DFMT_A1R5G5B5, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x8000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4), .todo_expected = TRUE + }, + { D3DFMT_A4R4G4B4, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x0f00, 0x00f0, 0x000f, 0xf000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4), .todo_expected = TRUE + }, + { D3DFMT_R3G3B2, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB, 0, 8, 0xe0, 0x1c, 0x03, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4) + }, + { D3DFMT_A8R3G3B2, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x00e0, 0x001c, 0x0003, 0xff00 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4), .todo_expected = TRUE + }, + { D3DFMT_X4R4G4B4, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB, 0, 16, 0xf00, 0x0f0, 0x00f, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + }, + { D3DFMT_A2B10G10R10, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + }, + { D3DFMT_A2R10G10B10, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + }, + { D3DFMT_A8R8G8B8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + }, + { D3DFMT_A8B8G8R8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + }, + { D3DFMT_X8R8G8B8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, + { D3DFMT_X8B8G8R8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB, 0, 32, 0x0000ff, 0x00ff00, 0xff0000, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, + { D3DFMT_R8G8B8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 3 * 4) + }, + { D3DFMT_G16R16, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, + { D3DFMT_A8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_ALPHA_ONLY, 0, 8, 0, 0, 0, 0xff }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, + DDS_FILE_HEADER_SIZE + (4 * 4), .todo_expected = TRUE + }, + { D3DFMT_DXT1, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (8) + }, + { D3DFMT_DXT2, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_DXT2, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (16) + }, + { D3DFMT_DXT3, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_DXT3, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (16) + }, + { D3DFMT_DXT4, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (16) + }, + { D3DFMT_DXT5, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_DXT5, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (16) + }, + { D3DFMT_A16B16G16R16, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_A16B16G16R16, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 8 * 4) + }, + { D3DFMT_Q16W16V16U16, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_Q16W16V16U16, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 8 * 4) + }, + { D3DFMT_R16F, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_R16F, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + }, + { D3DFMT_G16R16F, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_G16R16F, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, + { D3DFMT_A16B16G16R16F, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_A16B16G16R16F, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 8 * 4) + }, + { D3DFMT_R32F, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_R32F, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, + { D3DFMT_G32R32F, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_G32R32F, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 8 * 4) + }, + { D3DFMT_A32B32G32R32F, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_A32B32G32R32F, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 16 * 4) + }, + { D3DFMT_G8R8_G8B8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_G8R8_G8B8, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + }, + { D3DFMT_R8G8_B8G8, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_R8G8_B8G8, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + }, + { D3DFMT_UYVY, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_UYVY, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + }, + { D3DFMT_YUY2, 4, 4, NULL, D3D_OK, + { 32, DDS_PF_FOURCC, D3DFMT_YUY2, 0, 0, 0, 0, 0 }, + (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + }, + }; + struct + { + DWORD magic; + struct dds_header header; + BYTE *data; + } *dds; + IDirect3DSurface9 *surface; + ID3DXBuffer *buffer; + uint32_t i; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(dds_tests); ++i) + { + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, dds_tests[i].width, dds_tests[i].height, dds_tests[i].format, + D3DPOOL_SCRATCH, &surface, NULL); + if (FAILED(hr)) + { + skip("Couldn't create surface for format %#x.\n", dds_tests[i].format); + continue; + } + + winetest_push_context("Test %u", i); + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, dds_tests[i].palette, NULL); + todo_wine_if(dds_tests[i].todo_hr) ok(hr == dds_tests[i].expected_hr, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + ok(ID3DXBuffer_GetBufferSize(buffer) == dds_tests[i].expected_buffer_size, "Unexpected buffer size %lu.\n", + ID3DXBuffer_GetBufferSize(buffer)); + + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, dds_tests[i].expected_flags, dds_tests[i].expected_height, dds_tests[i].expected_width, + dds_tests[i].expected_pitch, dds_tests[i].expected_depth, dds_tests[i].expected_mip_levels, + &dds_tests[i].expected_pixel_format, dds_tests[i].expected_caps, dds_tests[i].expected_caps2, dds_tests[i].todo_expected); + ID3DXBuffer_Release(buffer); + } + + 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, + 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; + static const uint32_t tmp_pixdata_4_4[] = { 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0x00ff0040, 0x00ff0040, 0x00ff0040, 0x00ff0040, + 0x0000ff80, 0x0000ff80, 0x0000ff80, 0x0000ff80, + 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0 }; static const struct { DWORD usage; @@ -3466,8 +3826,8 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) } *dds; IDirect3DSurface9 *surface; IDirect3DTexture9 *texture; + unsigned int i, x, y; ID3DXBuffer *buffer; - unsigned int i; HRESULT hr; RECT rect;
@@ -3477,6 +3837,10 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) return; }
+ SetRect(&rect, 0, 0, 4, 4); + hr = D3DXLoadSurfaceFromMemory(surface, NULL, NULL, tmp_pixdata_4_4, D3DFMT_A8R8G8B8, 16, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + SetRectEmpty(&rect); hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_BMP, surface, NULL, &rect); /* fails with the debug version of d3d9 */ @@ -3507,6 +3871,50 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) ID3DXBuffer_Release(buffer); }
+ /* Test rectangle argument for D3DXIFF_DDS. */ + SetRect(&rect, 0, 0, 0, 2); + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 2, 0, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + ID3DXBuffer_Release(buffer); + } + + SetRect(&rect, 0, 0, 2, 0); + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 0, 2, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + ID3DXBuffer_Release(buffer); + } + + SetRect(&rect, 2, 2, 4, 4); + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 2, 2, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + for (y = 0; y < 2; ++y) + { + for (x = 0; x < 2; ++x) + { + const uint32_t expected_pixel = tmp_pixdata_4_4[((2 + y) * 4) + (x + 2)]; + const uint32_t saved_pixel = ((uint32_t *)&dds->data)[(y * 2) + x]; + + ok(expected_pixel == saved_pixel, "Unexpected pixel value %#x.\n", saved_pixel); + } + } + ID3DXBuffer_Release(buffer); + } + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, NULL); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
@@ -3545,6 +3953,8 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) IDirect3DSurface9_Release(surface); IDirect3DTexture9_Release(texture); } + + test_save_surface_to_dds(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 | 200 ++++++++++++++++++++++------------ dlls/d3dx9_36/tests/surface.c | 83 +++++++------- 2 files changed, 167 insertions(+), 116 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index f9d0fad1ad3..dea58648ca9 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -378,24 +378,31 @@ static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dds_pixel_format(cons return D3DX_PIXEL_FORMAT_COUNT; }
-static HRESULT dds_pixel_format_from_d3dformat(struct dds_pixel_format *pixel_format, D3DFORMAT d3dformat) +static HRESULT dds_pixel_format_from_d3dx_pixel_format_id(struct dds_pixel_format *pixel_format, + enum d3dx_pixel_format_id d3dx_pixel_format) { - enum d3dx_pixel_format_id d3dx_pixel_format = d3dx_pixel_format_id_from_d3dformat(d3dformat); + const struct dds_pixel_format *pf = NULL; uint32_t i;
- memset(pixel_format, 0, sizeof(*pixel_format)); - pixel_format->size = sizeof(*pixel_format); for (i = 0; i < ARRAY_SIZE(dds_pixel_formats); ++i) { if (dds_pixel_formats[i].d3dx_pixel_format == d3dx_pixel_format) { - *pixel_format = dds_pixel_formats[i].dds_pixel_format; - return D3D_OK; + pf = &dds_pixel_formats[i].dds_pixel_format; + break; } }
- WARN("Unknown pixel format %#x.\n", d3dformat); - return E_NOTIMPL; + if (!pf) + { + WARN("Unhandled format %#x.\n", d3dx_pixel_format); + return E_NOTIMPL; + } + + if (pixel_format) + *pixel_format = *pf; + + return D3D_OK; }
static void d3dx_get_next_mip_level_size(struct volume *size) @@ -454,97 +461,150 @@ static uint32_t d3dx_calculate_layer_pixels_size(enum d3dx_pixel_format_id forma return layer_size; }
-static UINT calculate_dds_file_size(D3DFORMAT format, UINT width, UINT height, UINT depth, - UINT miplevels, UINT faces) +static HRESULT d3dx_init_dds_header(struct dds_header *header, D3DRESOURCETYPE resource_type, + enum d3dx_pixel_format_id format, const struct volume *size, uint32_t mip_levels) +{ + HRESULT hr; + + memset(header, 0, sizeof(*header)); + header->signature = MAKEFOURCC('D','D','S',' '); + /* The signature is not really part of the DDS header. */ + header->size = sizeof(*header) - FIELD_OFFSET(struct dds_header, size); + hr = dds_pixel_format_from_d3dx_pixel_format_id(&header->pixel_format, format); + if (FAILED(hr)) + return hr; + + header->flags = DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT; + header->height = size->height; + header->width = size->width; + header->caps = DDS_CAPS_TEXTURE; + + return D3D_OK; +} + +static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_fmt_desc, + D3DXIMAGE_FILEFORMAT file_format, ID3DXBuffer **dst_buffer) { - const struct pixel_format_desc *fmt_desc = get_format_info(format); - UINT i, file_size = 0; + const struct pixel_format_desc *dst_fmt_desc; + uint32_t dst_row_pitch, dst_slice_pitch; + enum d3dx_pixel_format_id dst_format; + struct d3dx_pixels dst_pixels; + ID3DXBuffer *buffer = NULL; + uint8_t *pixels; + HRESULT hr;
- for (i = 0; i < miplevels; i++) + *dst_buffer = NULL; + dst_format = src_fmt_desc->format; + hr = dds_pixel_format_from_d3dx_pixel_format_id(NULL, dst_format); + if (FAILED(hr)) + return hr; + + 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) { - UINT pitch, size = 0; - if (FAILED(d3dx_calculate_pixels_size(fmt_desc->format, width, height, &pitch, &size))) - return 0; - size *= depth; - file_size += size; - width = max(1, width / 2); - height = max(1, height / 2); - depth = max(1, depth / 2); + case D3DXIFF_DDS: + { + struct dds_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); + hr = d3dx_init_dds_header(header, D3DRTYPE_TEXTURE, dst_format, &src_pixels->size, 1); + if (FAILED(hr)) + goto exit; + break; + } + + default: + assert(0); + break; + } + + if (src_pixels->size.width != 0 && src_pixels->size.height != 0) + { + const RECT dst_rect = { 0, 0, src_pixels->size.width, src_pixels->size.height }; + + set_d3dx_pixels(&dst_pixels, pixels, dst_row_pitch, dst_slice_pitch, src_pixels->palette, src_pixels->size.width, + src_pixels->size.height, src_pixels->size.depth, &dst_rect); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_fmt_desc, src_pixels, src_fmt_desc, D3DX_FILTER_NONE, 0); + if (FAILED(hr)) + goto exit; }
- file_size *= faces; - file_size += sizeof(struct dds_header); - return file_size; + *dst_buffer = buffer; +exit: + if (buffer && *dst_buffer != buffer) + ID3DXBuffer_Release(buffer); + return hr; }
static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, const RECT *src_rect) { - HRESULT hr; - UINT dst_pitch, surface_size, file_size; - D3DSURFACE_DESC src_desc; + const struct pixel_format_desc *src_fmt_desc; + D3DSURFACE_DESC src_surface_desc; + IDirect3DSurface9 *temp_surface; + struct d3dx_pixels src_pixels; D3DLOCKED_RECT locked_rect; ID3DXBuffer *buffer; - struct dds_header *header; - BYTE *pixels; - struct volume volume; - const struct pixel_format_desc *pixel_format; - IDirect3DSurface9 *temp_surface; + RECT src_rect_temp; + HRESULT hr; + + IDirect3DSurface9_GetDesc(src_surface, &src_surface_desc); + src_fmt_desc = get_format_info(src_surface_desc.Format); + if (is_unknown_format(src_fmt_desc)) + return E_NOTIMPL;
if (src_rect) { - FIXME("Saving a part of a surface to a DDS file is not implemented yet\n"); - return E_NOTIMPL; + if (src_rect->left > src_rect->right || src_rect->right > src_surface_desc.Width + || src_rect->top > src_rect->bottom || src_rect->bottom > src_surface_desc.Height + || src_rect->left < 0 || src_rect->top < 0) + { + WARN("Invalid src_rect specified.\n"); + return D3DERR_INVALIDCALL; + } + } + else + { + SetRect(&src_rect_temp, 0, 0, src_surface_desc.Width, src_surface_desc.Height); + src_rect = &src_rect_temp; }
- hr = IDirect3DSurface9_GetDesc(src_surface, &src_desc); - if (FAILED(hr)) return hr; - - pixel_format = get_format_info(src_desc.Format); - if (is_unknown_format(pixel_format)) return E_NOTIMPL; - - file_size = calculate_dds_file_size(src_desc.Format, src_desc.Width, src_desc.Height, 1, 1, 1); - if (!file_size) - return D3DERR_INVALIDCALL; - - hr = d3dx_calculate_pixels_size(pixel_format->format, src_desc.Width, src_desc.Height, &dst_pitch, &surface_size); - if (FAILED(hr)) return hr; - - hr = D3DXCreateBuffer(file_size, &buffer); - if (FAILED(hr)) return hr; + hr = lock_surface(src_surface, NULL, &locked_rect, &temp_surface, FALSE); + if (FAILED(hr)) + return hr;
- header = ID3DXBuffer_GetBufferPointer(buffer); - pixels = (BYTE *)(header + 1); + hr = d3dx_pixels_init(locked_rect.pBits, locked_rect.Pitch, 0, NULL, src_fmt_desc->format, + src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1, &src_pixels); + if (FAILED(hr)) + { + unlock_surface(src_surface, NULL, temp_surface, FALSE); + return hr; + }
- memset(header, 0, sizeof(*header)); - header->signature = MAKEFOURCC('D','D','S',' '); - /* The signature is not really part of the DDS header */ - header->size = sizeof(*header) - FIELD_OFFSET(struct dds_header, size); - header->flags = DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT; - header->height = src_desc.Height; - header->width = src_desc.Width; - header->caps = DDS_CAPS_TEXTURE; - hr = dds_pixel_format_from_d3dformat(&header->pixel_format, src_desc.Format); + hr = d3dx_save_pixels_to_memory(&src_pixels, src_fmt_desc, D3DXIFF_DDS, &buffer); if (FAILED(hr)) { - ID3DXBuffer_Release(buffer); + unlock_surface(src_surface, NULL, temp_surface, FALSE); return hr; }
- hr = lock_surface(src_surface, NULL, &locked_rect, &temp_surface, FALSE); + hr = unlock_surface(src_surface, NULL, temp_surface, FALSE); if (FAILED(hr)) { ID3DXBuffer_Release(buffer); return hr; }
- volume.width = src_desc.Width; - volume.height = src_desc.Height; - volume.depth = 1; - copy_pixels(locked_rect.pBits, locked_rect.Pitch, 0, pixels, dst_pitch, 0, - &volume, pixel_format); - - unlock_surface(src_surface, NULL, temp_surface, FALSE); - *dst_buffer = buffer; return D3D_OK; } diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index fa915715907..7cdf967d2bc 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3853,67 +3853,58 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
SetRectEmpty(&rect); hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - dds = ID3DXBuffer_GetBufferPointer(buffer); - - ok(dds->magic == MAKEFOURCC('D','D','S',' '), "Got unexpected DDS signature %#lx.\n", dds->magic); - ok(dds->header.size == sizeof(dds->header), "Got unexpected DDS size %lu.\n", dds->header.size); - ok(!dds->header.height, "Got unexpected height %lu.\n", dds->header.height); - ok(!dds->header.width, "Got unexpected width %lu.\n", dds->header.width); - ok(!dds->header.depth, "Got unexpected depth %lu.\n", dds->header.depth); - ok(!dds->header.miplevels, "Got unexpected miplevels %lu.\n", dds->header.miplevels); - ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %lu.\n", dds->header.pitch_or_linear_size); - ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); - ok(dds->header.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), - "Got unexpected flags %#lx.\n", dds->header.flags); - ID3DXBuffer_Release(buffer); - } + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + dds = ID3DXBuffer_GetBufferPointer(buffer); + + ok(dds->magic == MAKEFOURCC('D','D','S',' '), "Got unexpected DDS signature %#lx.\n", dds->magic); + ok(dds->header.size == sizeof(dds->header), "Got unexpected DDS size %lu.\n", dds->header.size); + ok(!dds->header.height, "Got unexpected height %lu.\n", dds->header.height); + ok(!dds->header.width, "Got unexpected width %lu.\n", dds->header.width); + ok(!dds->header.depth, "Got unexpected depth %lu.\n", dds->header.depth); + ok(!dds->header.miplevels, "Got unexpected miplevels %lu.\n", dds->header.miplevels); + ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %lu.\n", dds->header.pitch_or_linear_size); + todo_wine ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); + ok(dds->header.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), + "Got unexpected flags %#lx.\n", dds->header.flags); + ID3DXBuffer_Release(buffer);
/* Test rectangle argument for D3DXIFF_DDS. */ SetRect(&rect, 0, 0, 0, 2); hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - dds = ID3DXBuffer_GetBufferPointer(buffer); - check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 2, 0, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); - ID3DXBuffer_Release(buffer); - } + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 2, 0, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + ID3DXBuffer_Release(buffer);
SetRect(&rect, 0, 0, 2, 0); hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - dds = ID3DXBuffer_GetBufferPointer(buffer); - check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 0, 2, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); - ID3DXBuffer_Release(buffer); - } + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 0, 2, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + ID3DXBuffer_Release(buffer);
SetRect(&rect, 2, 2, 4, 4); hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 2, 2, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + for (y = 0; y < 2; ++y) { - dds = ID3DXBuffer_GetBufferPointer(buffer); - check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 2, 2, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); - for (y = 0; y < 2; ++y) + for (x = 0; x < 2; ++x) { - for (x = 0; x < 2; ++x) - { - const uint32_t expected_pixel = tmp_pixdata_4_4[((2 + y) * 4) + (x + 2)]; - const uint32_t saved_pixel = ((uint32_t *)&dds->data)[(y * 2) + x]; + const uint32_t expected_pixel = tmp_pixdata_4_4[((2 + y) * 4) + (x + 2)]; + const uint32_t saved_pixel = ((uint32_t *)&dds->data)[(y * 2) + x];
- ok(expected_pixel == saved_pixel, "Unexpected pixel value %#x.\n", saved_pixel); - } + ok(expected_pixel == saved_pixel, "Unexpected pixel value %#x.\n", saved_pixel); } - ID3DXBuffer_Release(buffer); } + ID3DXBuffer_Release(buffer);
hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, NULL); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 3 +++ dlls/d3dx9_36/tests/surface.c | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index dea58648ca9..548b335e9e2 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -90,6 +90,7 @@ static const GUID *wic_guid_from_d3dformat(D3DFORMAT format) #define DDS_DEPTH 0x800000
/* dds_header.caps */ +#define DDSCAPS_ALPHA 0x2 #define DDS_CAPS_COMPLEX 0x8 #define DDS_CAPS_TEXTURE 0x1000 #define DDS_CAPS_MIPMAP 0x400000 @@ -478,6 +479,8 @@ static HRESULT d3dx_init_dds_header(struct dds_header *header, D3DRESOURCETYPE r header->height = size->height; header->width = size->width; header->caps = DDS_CAPS_TEXTURE; + if (header->pixel_format.flags & DDS_PF_ALPHA || header->pixel_format.flags & DDS_PF_ALPHA_ONLY) + header->caps |= DDSCAPS_ALPHA;
return D3D_OK; } diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 7cdf967d2bc..452291f9f6f 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3589,7 +3589,7 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3DFMT_A2W10V10U10, 4, 4, NULL, D3D_OK, { 32, DDS_PF_BUMPDUDV | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) }, { D3DFMT_X8L8V8U8, 4, 4, NULL, D3D_OK, { 32, DDS_PF_BUMPLUMINANCE, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, @@ -3604,12 +3604,12 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3DFMT_A1R5G5B5, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x8000 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 2 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) }, { D3DFMT_A4R4G4B4, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x0f00, 0x00f0, 0x000f, 0xf000 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 2 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) }, { D3DFMT_R3G3B2, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB, 0, 8, 0xe0, 0x1c, 0x03, 0 }, @@ -3619,7 +3619,7 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3DFMT_A8R3G3B2, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x00e0, 0x001c, 0x0003, 0xff00 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 2 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) }, { D3DFMT_X4R4G4B4, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB, 0, 16, 0xf00, 0x0f0, 0x00f, 0 }, @@ -3629,22 +3629,22 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3DFMT_A2B10G10R10, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) }, { D3DFMT_A2R10G10B10, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) }, { D3DFMT_A8R8G8B8, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) }, { D3DFMT_A8B8G8R8, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 4 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) }, { D3DFMT_X8R8G8B8, 4, 4, NULL, D3D_OK, { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, @@ -3669,7 +3669,7 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3DFMT_A8, 4, 4, NULL, D3D_OK, { 32, DDS_PF_ALPHA_ONLY, 0, 8, 0, 0, 0, 0xff }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, - DDS_FILE_HEADER_SIZE + (4 * 4), .todo_expected = TRUE + DDS_FILE_HEADER_SIZE + (4 * 4) }, { D3DFMT_DXT1, 4, 4, NULL, D3D_OK, { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, @@ -3863,7 +3863,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) ok(!dds->header.depth, "Got unexpected depth %lu.\n", dds->header.depth); ok(!dds->header.miplevels, "Got unexpected miplevels %lu.\n", dds->header.miplevels); ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %lu.\n", dds->header.pitch_or_linear_size); - todo_wine ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); + ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); ok(dds->header.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), "Got unexpected flags %#lx.\n", dds->header.flags); ID3DXBuffer_Release(buffer); @@ -3875,7 +3875,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
dds = ID3DXBuffer_GetBufferPointer(buffer); check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 2, 0, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, FALSE); ID3DXBuffer_Release(buffer);
SetRect(&rect, 0, 0, 2, 0); @@ -3884,7 +3884,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
dds = ID3DXBuffer_GetBufferPointer(buffer); check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 0, 2, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, FALSE); ID3DXBuffer_Release(buffer);
SetRect(&rect, 2, 2, 4, 4); @@ -3893,7 +3893,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
dds = ID3DXBuffer_GetBufferPointer(buffer); check_dds_header(&dds->header, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 2, 2, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, TRUE); + &d3dfmt_a8r8g8b8_pf, (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), 0, FALSE); for (y = 0; y < 2; ++y) { for (x = 0; x < 2; ++x) @@ -3917,7 +3917,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) ok(!dds->header.depth, "Got unexpected depth %lu.\n", dds->header.depth); ok(!dds->header.miplevels, "Got unexpected miplevels %lu.\n", dds->header.miplevels); ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %lu.\n", dds->header.pitch_or_linear_size); - todo_wine ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); + ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); ok(dds->header.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), "Got unexpected flags %#lx.\n", dds->header.flags); ID3DXBuffer_Release(buffer);
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 32 ++++++++++++++++++++++++-------- dlls/d3dx9_36/tests/surface.c | 4 ++-- 2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 548b335e9e2..cf122988967 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -79,6 +79,8 @@ static const GUID *wic_guid_from_d3dformat(D3DFORMAT format) return NULL; }
+#define DDS_PALETTE_SIZE (sizeof(PALETTEENTRY) * 256) + /* dds_header.flags */ #define DDS_CAPS 0x1 #define DDS_HEIGHT 0x2 @@ -92,6 +94,7 @@ static const GUID *wic_guid_from_d3dformat(D3DFORMAT format) /* dds_header.caps */ #define DDSCAPS_ALPHA 0x2 #define DDS_CAPS_COMPLEX 0x8 +#define DDSCAPS_PALETTE 0x100 #define DDS_CAPS_TEXTURE 0x1000 #define DDS_CAPS_MIPMAP 0x400000
@@ -481,6 +484,8 @@ static HRESULT d3dx_init_dds_header(struct dds_header *header, D3DRESOURCETYPE r header->caps = DDS_CAPS_TEXTURE; if (header->pixel_format.flags & DDS_PF_ALPHA || header->pixel_format.flags & DDS_PF_ALPHA_ONLY) header->caps |= DDSCAPS_ALPHA; + if (header->pixel_format.flags & DDS_PF_INDEXED) + header->caps |= DDSCAPS_PALETTE;
return D3D_OK; } @@ -513,16 +518,21 @@ static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const case D3DXIFF_DDS: { struct dds_header *header; + uint32_t header_size;
- hr = D3DXCreateBuffer(dst_slice_pitch + sizeof(*header), &buffer); + header_size = is_index_format(dst_fmt_desc) ? sizeof(*header) + DDS_PALETTE_SIZE : sizeof(*header); + hr = D3DXCreateBuffer(dst_slice_pitch + header_size, &buffer); if (FAILED(hr)) return hr;
header = ID3DXBuffer_GetBufferPointer(buffer); - pixels = (uint8_t *)ID3DXBuffer_GetBufferPointer(buffer) + sizeof(*header); + pixels = (uint8_t *)ID3DXBuffer_GetBufferPointer(buffer) + header_size; hr = d3dx_init_dds_header(header, D3DRTYPE_TEXTURE, dst_format, &src_pixels->size, 1); if (FAILED(hr)) goto exit; + if (is_index_format(dst_fmt_desc)) + memcpy((uint8_t *)ID3DXBuffer_GetBufferPointer(buffer) + sizeof(*header), src_pixels->palette, + DDS_PALETTE_SIZE); break; }
@@ -550,7 +560,8 @@ exit: return hr; }
-static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, const RECT *src_rect) +static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, + const PALETTEENTRY *src_palette, const RECT *src_rect) { const struct pixel_format_desc *src_fmt_desc; D3DSURFACE_DESC src_surface_desc; @@ -566,6 +577,12 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSur if (is_unknown_format(src_fmt_desc)) return E_NOTIMPL;
+ if (!src_palette && is_index_format(src_fmt_desc)) + { + FIXME("Default palette unimplemented.\n"); + return E_NOTIMPL; + } + if (src_rect) { if (src_rect->left > src_rect->right || src_rect->right > src_surface_desc.Width @@ -586,7 +603,7 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSur if (FAILED(hr)) return hr;
- hr = d3dx_pixels_init(locked_rect.pBits, locked_rect.Pitch, 0, NULL, src_fmt_desc->format, + hr = d3dx_pixels_init(locked_rect.pBits, locked_rect.Pitch, 0, src_palette, src_fmt_desc->format, src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1, &src_pixels); if (FAILED(hr)) { @@ -666,7 +683,6 @@ static BOOL d3dx_get_image_file_format_from_file_signature(const void *src_data, return FALSE; }
-#define DDS_PALETTE_SIZE (sizeof(PALETTEENTRY) * 256) static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t starting_mip_level) { @@ -2959,9 +2975,9 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE if (!dst_buffer || !src_surface) return D3DERR_INVALIDCALL;
IDirect3DSurface9_GetDesc(src_surface, &src_surface_desc); - if (src_palette || is_index_format(get_format_info(src_surface_desc.Format))) + if (file_format != D3DXIFF_DDS && (src_palette || is_index_format(get_format_info(src_surface_desc.Format)))) { - FIXME("Saving surfaces with palettized pixel formats is not implemented yet.\n"); + FIXME("Saving surfaces with palettized pixel formats to non-DDS files is not implemented yet.\n"); return D3DERR_INVALIDCALL; }
@@ -2978,7 +2994,7 @@ 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_rect); + return save_dds_surface_to_memory(dst_buffer, src_surface, src_palette, src_rect); case D3DXIFF_HDR: case D3DXIFF_PFM: case D3DXIFF_TGA: diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 452291f9f6f..7e3f284fe00 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3548,12 +3548,12 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3DFMT_P8, 4, 4, test_palette, D3D_OK, { 32, DDS_PF_INDEXED, 0, 8, 0, 0, 0, 0 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_PALETTE), 0, - PALETTED_DDS_FILE_HEADER_SIZE + (4 * 4), .todo_hr = TRUE + PALETTED_DDS_FILE_HEADER_SIZE + (4 * 4) }, { D3DFMT_A8P8, 4, 4, test_palette, D3D_OK, { 32, DDS_PF_INDEXED | DDS_PF_ALPHA, 0, 16, 0, 0, 0, 0xff00 }, (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_PALETTE | DDSCAPS_ALPHA), 0, - PALETTED_DDS_FILE_HEADER_SIZE + (4 * 2 * 4), .todo_hr = TRUE + PALETTED_DDS_FILE_HEADER_SIZE + (4 * 2 * 4) }, /* If a palette isn't provided, d3dx converts to D3DFMT_A8R8G8B8. */ { D3DFMT_P8, 4, 4, NULL, D3D_OK,
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
/* dds_header.caps */ #define DDSCAPS_ALPHA 0x00000002 +#define DDSCAPS_PALETTE 0x00000100 #define DDS_CAPS_TEXTURE 0x00001000 #define DDS_CAPS_COMPLEX 0x00000008
It just came to me: can we `#include <ddraw.h>` instead? It wouldn't be proper for the implementation side, but for the tests I don't think there should be major problems with that... Not worth spending a lot of time on this, though.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
uint32_t height;
const PALETTEENTRY *palette;
HRESULT expected_hr;
struct dds_pixel_format expected_pixel_format;
uint32_t expected_flags;
uint32_t expected_width;
uint32_t expected_height;
uint32_t expected_pitch;
uint32_t expected_depth;
uint32_t expected_mip_levels;
uint32_t expected_caps;
uint32_t expected_caps2;
uint32_t expected_buffer_size;
BOOL todo_hr;
BOOL todo_expected;
An option would be to collect all of that into an `expected` structure, which would be easier to handle (e.g. to pass the data to `check_dds_header()`).
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
struct dds_pixel_format expected_pixel_format;
uint32_t expected_flags;
uint32_t expected_width;
uint32_t expected_height;
uint32_t expected_pitch;
uint32_t expected_depth;
uint32_t expected_mip_levels;
uint32_t expected_caps;
uint32_t expected_caps2;
uint32_t expected_buffer_size;
BOOL todo_hr;
BOOL todo_expected;
- } dds_tests[] = {
{ D3DFMT_P8, 4, 4, test_palette, D3D_OK,
{ 32, DDS_PF_INDEXED, 0, 8, 0, 0, 0, 0 },
(DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE | DDSCAPS_PALETTE), 0,
I think those kind of parentheses are a bit ugly, especially when they aren't used consistently.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
},
{ D3DFMT_DXT4, 4, 4, NULL, D3D_OK,
{ 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 },
(DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0,
DDS_FILE_HEADER_SIZE + (16)
},
{ D3DFMT_DXT5, 4, 4, NULL, D3D_OK,
{ 32, DDS_PF_FOURCC, D3DFMT_DXT5, 0, 0, 0, 0, 0 },
(DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0,
DDS_FILE_HEADER_SIZE + (16)
},
{ D3DFMT_A16B16G16R16, 4, 4, NULL, D3D_OK,
{ 32, DDS_PF_FOURCC, D3DFMT_A16B16G16R16, 0, 0, 0, 0, 0 },
(DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0,
DDS_FILE_HEADER_SIZE + (4 * 8 * 4)
},
Doesn't this test also appear above?
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
},
{ D3DFMT_YUY2, 4, 4, NULL, D3D_OK,
{ 32, DDS_PF_FOURCC, D3DFMT_YUY2, 0, 0, 0, 0, 0 },
(DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), 4, 4, 0, 0, 0, (DDS_CAPS_TEXTURE), 0,
DDS_FILE_HEADER_SIZE + (4 * 2 * 4)
},
- };
- struct
- {
DWORD magic;
struct dds_header header;
BYTE *data;
- } *dds;
- IDirect3DSurface9 *surface;
- ID3DXBuffer *buffer;
- uint32_t i;
Just `unsigned int` should be fine for a generic loop counter.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
- IDirect3DSurface9 *surface;
- ID3DXBuffer *buffer;
- uint32_t i;
- HRESULT hr;
- for (i = 0; i < ARRAY_SIZE(dds_tests); ++i)
- {
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, dds_tests[i].width, dds_tests[i].height, dds_tests[i].format,
D3DPOOL_SCRATCH, &surface, NULL);
if (FAILED(hr))
{
skip("Couldn't create surface for format %#x.\n", dds_tests[i].format);
continue;
}
winetest_push_context("Test %u", i);
I guess the `dds_tests[]` definition above could use a small comment every 10 entries or so.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
if (FAILED(hr))
{
skip("Couldn't create surface for format %#x.\n", dds_tests[i].format);
continue;
}
winetest_push_context("Test %u", i);
hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, dds_tests[i].palette, NULL);
todo_wine_if(dds_tests[i].todo_hr) ok(hr == dds_tests[i].expected_hr, "Unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
{
ok(ID3DXBuffer_GetBufferSize(buffer) == dds_tests[i].expected_buffer_size, "Unexpected buffer size %lu.\n",
ID3DXBuffer_GetBufferSize(buffer));
dds = ID3DXBuffer_GetBufferPointer(buffer);
check_dds_header(&dds->header, dds_tests[i].expected_flags, dds_tests[i].expected_height, dds_tests[i].expected_width,
We usually try to keep line length below 100-120 columns. It's not a super strict limit, but once you end up having to split lines you might as well aim for that kind of range.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
- const struct pixel_format_desc *fmt_desc = get_format_info(format);
- UINT i, file_size = 0;
- const struct pixel_format_desc *dst_fmt_desc;
- uint32_t dst_row_pitch, dst_slice_pitch;
- enum d3dx_pixel_format_id dst_format;
- struct d3dx_pixels dst_pixels;
- ID3DXBuffer *buffer = NULL;
- uint8_t *pixels;
- HRESULT hr;
- for (i = 0; i < miplevels; i++)
- *dst_buffer = NULL;
- dst_format = src_fmt_desc->format;
- hr = dds_pixel_format_from_d3dx_pixel_format_id(NULL, dst_format);
- if (FAILED(hr))
return hr;
Obviously it doesn't matter at the moment, but this should probably go after the `file_format` switch.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
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);
hr = d3dx_init_dds_header(header, D3DRTYPE_TEXTURE, dst_format, &src_pixels->size, 1);
if (FAILED(hr))
goto exit;
break;
}
default:
assert(0);
break;
This suggestion is probably going to be a bit much in respect to what's usual for Wine, so feel free to ignore it. I'd personally go for something like: ```suggestion:-1+0 assert(0 && "Unexpected file format"); return E_FAIL; ```
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
ok(!dds->header.depth, "Got unexpected depth %lu.\n", dds->header.depth); ok(!dds->header.miplevels, "Got unexpected miplevels %lu.\n", dds->header.miplevels); ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %lu.\n", dds->header.pitch_or_linear_size);
- todo_wine ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps);
- ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps);
Maybe we want to use `check_dds_header()` in this particular test as well? Just for consistency, I wouldn't expect any surprise here.
(I'd "update" this test when adding the others in patch 2/5, FWIW)
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/surface.c:
ok(!dds->header.depth, "Got unexpected depth %lu.\n", dds->header.depth); ok(!dds->header.miplevels, "Got unexpected miplevels %lu.\n", dds->header.miplevels); ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %lu.\n", dds->header.pitch_or_linear_size);
- todo_wine ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps);
- ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps);
Same as above.
Sorry it took me a while to finish the review. I've got a bunch of comments but nothing really important.
In addition, as a pet peeve of mine, I find a bit surprising when a patch is titled "Refactor" but then it fixes tests (something you wouldn't expect from a simple refactor). I'd rather say "Improve" or something like that.