This is the first of 3 planned MRs reworking how `D3DXSaveSurfaceToFileInMemory()` functions, starting with DDS files.
-- v2: d3dx9: Add support for saving paletted surfaces to DDS files. d3dx9: Set the DDSCAPS_ALPHA flag when saving DDS files with a pixel format containing an alpha channel. d3dx9: Improve save_dds_surface_to_memory(). d3dx9/tests: Add more tests for saving surfaces as DDS files. d3dx9: Don't attempt to save palettized surfaces in D3DXSaveSurfaceToFileInMemory(). d3dx9/tests: Include ddraw.h in surface.c for DDS header flag definitions.
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/surface.c | 163 +++++++++++++++------------------- 1 file changed, 72 insertions(+), 91 deletions(-)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 98408d026ed..911991600d4 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -26,6 +26,15 @@ #include <stdint.h> #include "d3dx9_test_images.h"
+/* + * MAKE_DDHRESULT is first defined in d3dx9.h, with the same definition as the + * one in ddraw.h. + */ +#ifdef MAKE_DDHRESULT +#undef MAKE_DDHRESULT +#endif +#include "ddraw.h" + static BOOL compare_uint(uint32_t x, uint32_t y, uint32_t max_diff) { uint32_t diff = x > y ? x - y : y - x; @@ -140,34 +149,6 @@ static HRESULT create_file(const char *filename, const unsigned char *data, cons return D3DERR_INVALIDCALL; }
-/* dds_header.flags */ -#define DDS_CAPS 0x00000001 -#define DDS_HEIGHT 0x00000002 -#define DDS_WIDTH 0x00000004 -#define DDS_PITCH 0x00000008 -#define DDS_PIXELFORMAT 0x00001000 -#define DDS_MIPMAPCOUNT 0x00020000 -#define DDS_LINEARSIZE 0x00080000 -#define DDS_PITCH 0x00000008 -#define DDS_DEPTH 0x00800000 - -/* dds_header.caps */ -#define DDSCAPS_ALPHA 0x00000002 -#define DDS_CAPS_TEXTURE 0x00001000 -#define DDS_CAPS_COMPLEX 0x00000008 - -#define DDS_CAPS2_VOLUME 0x00200000 -#define DDS_CAPS2_CUBEMAP 0x00000200 -#define DDS_CAPS2_CUBEMAP_POSITIVEX 0x00000400 -#define DDS_CAPS2_CUBEMAP_NEGATIVEX 0x00000800 -#define DDS_CAPS2_CUBEMAP_POSITIVEY 0x00001000 -#define DDS_CAPS2_CUBEMAP_NEGATIVEY 0x00002000 -#define DDS_CAPS2_CUBEMAP_POSITIVEZ 0x00004000 -#define DDS_CAPS2_CUBEMAP_NEGATIVEZ 0x00008000 -#define DDS_CAPS2_CUBEMAP_ALL_FACES ( DDS_CAPS2_CUBEMAP_POSITIVEX | DDS_CAPS2_CUBEMAP_NEGATIVEX \ - | DDS_CAPS2_CUBEMAP_POSITIVEY | DDS_CAPS2_CUBEMAP_NEGATIVEY \ - | DDS_CAPS2_CUBEMAP_POSITIVEZ | DDS_CAPS2_CUBEMAP_NEGATIVEZ ) - /* dds_pixel_format.flags */ #define DDS_PF_ALPHA 0x00000001 #define DDS_PF_ALPHA_ONLY 0x00000002 @@ -214,7 +195,7 @@ static void fill_dds_header(struct dds_header *header) memset(header, 0, sizeof(*header));
header->size = sizeof(*header); - header->flags = DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT; + header->flags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; header->height = 4; header->width = 4; header->pixel_format.size = sizeof(header->pixel_format); @@ -226,7 +207,7 @@ static void fill_dds_header(struct dds_header *header) header->pixel_format.gmask = 0x00ff00; header->pixel_format.bmask = 0x0000ff; header->pixel_format.amask = 0; - header->caps = DDS_CAPS_TEXTURE; + header->caps = DDSCAPS_TEXTURE; }
#define check_dds_pixel_format(flags, fourcc, bpp, rmask, gmask, bmask, amask, format) \ @@ -332,37 +313,37 @@ static void test_dds_header_handling(void) /* pitch is ignored */ { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, 0, 4, 4, 0, 0, 63 /* pixel data size */, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 0 /* pitch */, 0, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSD_PITCH, 4, 4, 0 /* pitch */, 0, 64, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 1 /* pitch */, 0, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSD_PITCH, 4, 4, 1 /* pitch */, 0, 64, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 2 /* pitch */, 0, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSD_PITCH, 4, 4, 2 /* pitch */, 0, 64, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 3 /* pitch */, 0, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSD_PITCH, 4, 4, 3 /* pitch */, 0, 64, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 4 /* pitch */, 0, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSD_PITCH, 4, 4, 4 /* pitch */, 0, 64, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 16 /* pitch */, 0, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSD_PITCH, 4, 4, 16 /* pitch */, 0, 64, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 1024 /* pitch */, 0, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSD_PITCH, 4, 4, 1024 /* pitch */, 0, 64, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, -1 /* pitch */, 0, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDSD_PITCH, 4, 4, -1 /* pitch */, 0, 64, { D3D_OK, 1 } }, /* linear size is ignored */ { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 4, 4, 0, 0, 7 /* pixel data size */, { D3DXERR_INVALIDDATA, 1 } }, /* 10. */ - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 0 /* linear size */, 0, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_LINEARSIZE, 4, 4, 0 /* linear size */, 0, 8, { D3D_OK, 1 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 1 /* linear size */, 0, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_LINEARSIZE, 4, 4, 1 /* linear size */, 0, 8, { D3D_OK, 1 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 2 /* linear size */, 0, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_LINEARSIZE, 4, 4, 2 /* linear size */, 0, 8, { D3D_OK, 1 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 9 /* linear size */, 0, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_LINEARSIZE, 4, 4, 9 /* linear size */, 0, 8, { D3D_OK, 1 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 16 /* linear size */, 0, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_LINEARSIZE, 4, 4, 16 /* linear size */, 0, 8, { D3D_OK, 1 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, -1 /* linear size */, 0, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_LINEARSIZE, 4, 4, -1 /* linear size */, 0, 8, { D3D_OK, 1 } }, /* integer overflows */ { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x80000000, 0x80000000 /* 0x80000000 * 0x80000000 * 4 = 0 */, 0, 0, @@ -376,46 +357,46 @@ static void test_dds_header_handling(void) /* 20. File size is validated. */ { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 64, 0, 0, 49151, { D3DXERR_INVALIDDATA, 0 } }, { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 64, 0, 0, 49152, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 65279, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 65280, { D3D_OK, 4 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 9, 65540, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 9, 65541, { D3D_OK, 9 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 64, 0, 4, 65279, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 64, 0, 4, 65280, { D3D_OK, 4 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 64, 0, 9, 65540, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 64, 0, 9, 65541, { D3D_OK, 9 } }, { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196607, { D3DXERR_INVALIDDATA, 0 } }, { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196608, { D3D_OK, 1 } }, { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196609, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 1, 196607, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 1, 196607, { D3DXERR_INVALIDDATA, 0 } }, /* 30. */ - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 1, 196608, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 196607, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 196608, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 400000, { D3D_OK, 1 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 262142, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 262143, { D3D_OK, 9 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 10, 262145, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 10, 262146, { D3D_OK, 10 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 262175, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 262176, { D3D_OK, 20 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 1, 196608, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 0, 196607, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 0, 196608, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 0, 400000, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 9, 262142, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 9, 262143, { D3D_OK, 9 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 10, 262145, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 10, 262146, { D3D_OK, 10 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 20, 262175, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 20, 262176, { D3D_OK, 20 } }, /* 40. */ { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 32767, { D3DXERR_INVALIDDATA, 0 } }, { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 32768, { D3D_OK, 1 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 32767, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 32768, { D3D_OK, 1 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 43703, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 43704, { D3D_OK, 9 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 43791, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 43792, { D3D_OK, 20 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 0, 32767, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 0, 32768, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 9, 43703, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 9, 43704, { D3D_OK, 9 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 20, 43791, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 20, 43792, { D3D_OK, 20 } }, { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 65535, { D3DXERR_INVALIDDATA, 0 } }, { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 65536, { D3D_OK, 1 } }, /* 50. */ - { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 65535, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 65536, { D3D_OK, 1 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 87407, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 87408, { D3D_OK, 9 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 87583, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 87584, { D3D_OK, 20 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 21759, { D3DXERR_INVALIDDATA, 0 } }, - { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 21760, { D3D_OK, 4 } }, - /* DDS_MIPMAPCOUNT is ignored */ + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 0, 65535, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 0, 65536, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 9, 87407, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 9, 87408, { D3D_OK, 9 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 20, 87583, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 256, 0, 20, 87584, { D3D_OK, 20 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 64, 0, 4, 21759, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDSD_MIPMAPCOUNT, 256, 64, 0, 4, 21760, { D3D_OK, 4 } }, + /* DDSD_MIPMAPCOUNT is ignored */ { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 262146, { D3D_OK, 1 } }, { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 2, 262146, { D3D_OK, 2 } }, /* 60. */ @@ -462,34 +443,34 @@ static void test_dds_header_handling(void) BOOL todo_info; } info_tests[] = { /* Depth value set to 4, but no caps bits are set. Depth is ignored. */ - { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 4, (4 * 4), 3, 0, 0, + { (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT), 4, 4, 4, (4 * 4), 3, 0, 0, { D3D_OK, 4, 4, 1, 3, D3DRTYPE_TEXTURE, }, 292 }, /* The volume texture caps2 field is ignored. */ - { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 4, (4 * 4), 3, - (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), DDS_CAPS2_VOLUME, + { (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT), 4, 4, 4, (4 * 4), 3, + (DDSCAPS_TEXTURE | DDSCAPS_COMPLEX), DDSCAPS2_VOLUME, { D3D_OK, 4, 4, 1, 3, D3DRTYPE_TEXTURE, }, 292 }, /* - * The DDS_DEPTH flag is the only thing checked to determine if a DDS + * The DDSD_DEPTH flag is the only thing checked to determine if a DDS * file represents a volume texture. */ - { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT | DDS_DEPTH), 4, 4, 4, (4 * 4), 3, + { (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_DEPTH), 4, 4, 4, (4 * 4), 3, 0, 0, { D3D_OK, 4, 4, 4, 3, D3DRTYPE_VOLUMETEXTURE, }, 292 }, /* Even if the depth field is set to 0, it's still a volume texture. */ - { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT | DDS_DEPTH), 4, 4, 0, (4 * 4), 3, + { (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_DEPTH), 4, 4, 0, (4 * 4), 3, 0, 0, { D3D_OK, 4, 4, 1, 3, D3DRTYPE_VOLUMETEXTURE, }, 292 }, - /* The DDS_DEPTH flag overrides cubemap caps. */ - { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT | DDS_DEPTH), 4, 4, 4, (4 * 4), 3, - (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), (DDS_CAPS2_CUBEMAP | DDS_CAPS2_CUBEMAP_ALL_FACES), + /* The DDSD_DEPTH flag overrides cubemap caps. */ + { (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_DEPTH), 4, 4, 4, (4 * 4), 3, + (DDSCAPS_TEXTURE | DDSCAPS_COMPLEX), (DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES), { D3D_OK, 4, 4, 4, 3, D3DRTYPE_VOLUMETEXTURE, }, (292 * 6) }, /* Cubemap where width field does not equal height. */ - { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 5, 1, (4 * 4), 1, - (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), (DDS_CAPS2_CUBEMAP | DDS_CAPS2_CUBEMAP_ALL_FACES), + { (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT), 4, 5, 1, (4 * 4), 1, + (DDSCAPS_TEXTURE | DDSCAPS_COMPLEX), (DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES), { D3D_OK, 4, 5, 1, 1, D3DRTYPE_CUBETEXTURE, }, (80 * 6) }, /* Partial cubemaps are not supported. */ - { (DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT), 4, 4, 1, (4 * 4), 1, - (DDS_CAPS_TEXTURE | DDS_CAPS_COMPLEX), (DDS_CAPS2_CUBEMAP | DDS_CAPS2_CUBEMAP_POSITIVEX), + { (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT), 4, 4, 1, (4 * 4), 1, + (DDSCAPS_TEXTURE | DDSCAPS_COMPLEX), (DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX), { D3DXERR_INVALIDDATA, }, (64 * 6) }, };
@@ -3501,8 +3482,8 @@ 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); - 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), + ok(dds->header.caps == (DDSCAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); + ok(dds->header.flags == (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT), "Got unexpected flags %#lx.\n", dds->header.flags); ID3DXBuffer_Release(buffer); } @@ -3518,8 +3499,8 @@ 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.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), + todo_wine ok(dds->header.caps == (DDSCAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); + ok(dds->header.flags == (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_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 | 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 | 482 ++++++++++++++++++++++++++++++++-- 1 file changed, 461 insertions(+), 21 deletions(-)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 911991600d4..57297c49d7b 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3425,8 +3425,415 @@ 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) +{ + struct expected + { + HRESULT hr; + struct dds_pixel_format pixel_format; + uint32_t flags; + uint32_t width; + uint32_t height; + uint32_t pitch; + uint32_t depth; + uint32_t mip_levels; + uint32_t caps; + uint32_t caps2; + uint32_t buffer_size; + }; + static const struct + { + D3DFORMAT format; + uint32_t width; + uint32_t height; + const PALETTEENTRY *palette; + struct expected expected_vals; + 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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, + DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + }, .todo_hr = TRUE + }, + { D3DFMT_V8U8, 4, 4, NULL, + { D3D_OK, { 32, DDS_PF_BUMPDUDV, 0, 16, 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_TEXTURE, 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + } + }, + /* 10. */ + { D3DFMT_A1R5G5B5, 4, 4, NULL, + { D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x8000 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_TEXTURE, 0, + DDS_FILE_HEADER_SIZE + (4 * 4 * 4) + } + }, + /* 20. */ + { D3DFMT_X8B8G8R8, 4, 4, NULL, + { D3D_OK, { 32, DDS_PF_RGB, 0, 32, 0x0000ff, 0x00ff00, 0xff0000, 0 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_TEXTURE, 0, + DDS_FILE_HEADER_SIZE + (4 * 8 * 4) + } + }, + /* 30. */ + { D3DFMT_Q16W16V16U16, 4, 4, NULL, + { D3D_OK, { 32, DDS_PF_FOURCC, D3DFMT_Q16W16V16U16, 0, 0, 0, 0, 0 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_TEXTURE, 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + } + }, + /* 40. */ + { D3DFMT_YUY2, 4, 4, NULL, + { D3D_OK, { 32, DDS_PF_FOURCC, D3DFMT_YUY2, 0, 0, 0, 0, 0 }, + DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_TEXTURE, 0, + DDS_FILE_HEADER_SIZE + (4 * 2 * 4) + } + }, + }; + struct + { + DWORD magic; + struct dds_header header; + BYTE *data; + } *dds; + IDirect3DSurface9 *surface; + ID3DXBuffer *buffer; + unsigned int i; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(dds_tests); ++i) + { + const struct expected *expected = &dds_tests[i].expected_vals; + + 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 == expected->hr, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + ok(ID3DXBuffer_GetBufferSize(buffer) == expected->buffer_size, "Unexpected buffer size %lu.\n", + ID3DXBuffer_GetBufferSize(buffer)); + + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, expected->flags, expected->height, expected->width, expected->pitch, + expected->depth, expected->mip_levels, &expected->pixel_format, expected->caps, 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; @@ -3447,8 +3854,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;
@@ -3458,6 +3865,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 */ @@ -3474,17 +3885,52 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) if (SUCCEEDED(hr)) { dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0, 0, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, FALSE); + 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, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 2, 0, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_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, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0, 2, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); + ID3DXBuffer_Release(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 == (DDSCAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); - ok(dds->header.flags == (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT), - "Got unexpected flags %#lx.\n", dds->header.flags); + 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, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 2, 2, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_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); }
@@ -3492,16 +3938,8 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) 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 == 4, "Got unexpected height %lu.\n", dds->header.height); - ok(dds->header.width == 4, "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 == (DDSCAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#lx.\n", dds->header.caps); - ok(dds->header.flags == (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT), - "Got unexpected flags %#lx.\n", dds->header.flags); + check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); ID3DXBuffer_Release(buffer);
IDirect3DSurface9_Release(surface); @@ -3526,6 +3964,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 | 199 ++++++++++++++++++++++------------ dlls/d3dx9_36/tests/surface.c | 66 +++++------ 2 files changed, 158 insertions(+), 107 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index f9d0fad1ad3..2ea1cc2b440 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,149 @@ 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; + enum d3dx_pixel_format_id dst_format = src_fmt_desc->format; + const struct pixel_format_desc *dst_fmt_desc; + uint32_t dst_row_pitch, dst_slice_pitch; + struct d3dx_pixels dst_pixels; + ID3DXBuffer *buffer = NULL; + uint8_t *pixels; + HRESULT hr;
- for (i = 0; i < miplevels; i++) + *dst_buffer = NULL; + 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 = 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; + + 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 && "Unexpected file format."); + return E_FAIL; }
- file_size *= faces; - file_size += sizeof(struct dds_header); - return file_size; + 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; + } + + *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 57297c49d7b..b4ffafa0423 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3881,58 +3881,50 @@ 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); - check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0, 0, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, FALSE); - ID3DXBuffer_Release(buffer); - } + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + dds = ID3DXBuffer_GetBufferPointer(buffer); + check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0, 0, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); + 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, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 2, 0, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_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, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 2, 0, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_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, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0, 2, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_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, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0, 2, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_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, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 2, 2, 0, 0, 0, + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); + for (y = 0; y < 2; ++y) { - dds = ID3DXBuffer_GetBufferPointer(buffer); - check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 2, 2, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_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 2ea1cc2b440..1aca50a3059 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 b4ffafa0423..198cb8bc841 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3578,7 +3578,7 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3D_OK, { 32, DDS_PF_BUMPDUDV | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, @@ -3597,13 +3597,13 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x8000 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, @@ -3615,7 +3615,7 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x00e0, 0x001c, 0x0003, 0xff00 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, @@ -3627,25 +3627,25 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3D_OK, { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, @@ -3676,7 +3676,7 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3D_OK, { 32, DDS_PF_ALPHA_ONLY, 0, 8, 0, 0, 0, 0xff }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, @@ -3885,7 +3885,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
dds = ID3DXBuffer_GetBufferPointer(buffer); check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0, 0, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, FALSE); ID3DXBuffer_Release(buffer);
/* Test rectangle argument for D3DXIFF_DDS. */ @@ -3895,7 +3895,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
dds = ID3DXBuffer_GetBufferPointer(buffer); check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 2, 0, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, FALSE); ID3DXBuffer_Release(buffer);
SetRect(&rect, 0, 0, 2, 0); @@ -3904,7 +3904,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
dds = ID3DXBuffer_GetBufferPointer(buffer); check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0, 2, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, FALSE); ID3DXBuffer_Release(buffer);
SetRect(&rect, 2, 2, 4, 4); @@ -3913,7 +3913,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
dds = ID3DXBuffer_GetBufferPointer(buffer); check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 2, 2, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, FALSE); for (y = 0; y < 2; ++y) { for (x = 0; x < 2; ++x) @@ -3931,7 +3931,7 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
dds = ID3DXBuffer_GetBufferPointer(buffer); check_dds_header(&dds->header, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, - &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, TRUE); + &d3dfmt_a8r8g8b8_pf, DDSCAPS_TEXTURE | DDSCAPS_ALPHA, 0, FALSE); ID3DXBuffer_Release(buffer);
IDirect3DSurface9_Release(surface);
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 1aca50a3059..61b0283796d 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; } @@ -502,6 +507,7 @@ 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 = dds_pixel_format_from_d3dx_pixel_format_id(NULL, dst_format); if (FAILED(hr)) @@ -513,15 +519,19 @@ static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const if (FAILED(hr)) return hr;
- 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; }
@@ -549,7 +559,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; @@ -565,6 +576,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 @@ -585,7 +602,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)) { @@ -665,7 +682,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) { @@ -2958,9 +2974,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; }
@@ -2977,7 +2993,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 198cb8bc841..80343934cea 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3534,14 +3534,14 @@ static void test_save_surface_to_dds(IDirect3DDevice9 *device) { D3D_OK, { 32, DDS_PF_INDEXED, 0, 8, 0, 0, 0, 0 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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 }, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 4, 4, 0, 0, 0, DDSCAPS_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,
On Mon Nov 11 13:43:51 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/6776/diffs?diff_id=142416&start_sha=41e22e994d3b793cc751e42f08a86cf7d8b67871#d49071753fdf2ab21d518dbd8c720b48c7c732fc_158_152)
Added a new patch for this, seems pretty straight forward aside from needing to undefine `MAKE_DDHRESULT` prior to including the `ddraw.h` header, due to `d3dx9.h` defining `MAKE_DDHRESULT` as well.
On Mon Nov 11 13:43:51 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/6776/diffs?diff_id=142416&start_sha=41e22e994d3b793cc751e42f08a86cf7d8b67871#d49071753fdf2ab21d518dbd8c720b48c7c732fc_3550_3531)
I've removed all parentheses around DDS header flags in the current revision, hopefully this is better. :)
On Mon Nov 11 13:48:00 2024 +0000, Matteo Bruni wrote:
Doesn't this test also appear above?
Good catch, I started out with just a subset of format tests, and then automated the creation of the rest. The original `D3DFMT_A16B16G16R16` test was a leftover of the old tests, should be fixed now.
On Mon Nov 11 13:43:51 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/6776/diffs?diff_id=142416&start_sha=41e22e994d3b793cc751e42f08a86cf7d8b67871#d49071753fdf2ab21d518dbd8c720b48c7c732fc_3768_3794)
I've been trying to fix these in my newer patches as I find them, sorry about missing this one :)
On Mon Nov 11 13:48:36 2024 +0000, Matteo Bruni wrote:
I guess the `dds_tests[]` definition above could use a small comment every 10 entries or so.
Done.
On Mon Nov 11 13:43:52 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/6776/diffs?diff_id=142416&start_sha=41e22e994d3b793cc751e42f08a86cf7d8b67871#8fffeae09861a99974e55842964630933974cdc8_508_505)
Good point, changed in the current revision.
On Mon Nov 11 13:43:52 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/6776/diffs?diff_id=142416&start_sha=41e22e994d3b793cc751e42f08a86cf7d8b67871#8fffeae09861a99974e55842964630933974cdc8_541_539)
Fixed in the current revision.
On Sat Nov 9 01:43:08 2024 +0000, Matteo Bruni wrote:
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()`).
I _think_ I've changed this to be more inline with what you've suggested, but I'll let you mark this as resolved to be sure.
If you meant to suggest having `check_dds_header()` take an `expected` structure as an argument, that gets kind of ugly if we're using that same function for tests outside of `test_save_surface_to_dds()`.
On Mon Nov 11 13:53:54 2024 +0000, Matteo Bruni wrote:
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.
Not a problem. :)
I see what you mean with "refactor", I've changed a commit message to use "improve" and changed the title of this MR as well.
On Mon Nov 11 13:52:36 2024 +0000, Connor McAdams wrote:
I _think_ I've changed this to be more inline with what you've suggested, but I'll let you mark this as resolved to be sure. If you meant to suggest having `check_dds_header()` take an `expected` structure as an argument, that gets kind of ugly if we're using that same function for tests outside of `test_save_surface_to_dds()`.
Yeah, I was thinking about potentially passing the structure to `check_dds_header()`. This is certainly fine but I'm wondering what makes it ugly for other tests. Is it hard to make them table-based like `test_save_surface_to_dds()` (i.e. looping on test cases in a `tests[]` array of structures)?
On Mon Nov 11 15:37:29 2024 +0000, Matteo Bruni wrote:
Yeah, I was thinking about potentially passing the structure to `check_dds_header()`. This is certainly fine but I'm wondering what makes it ugly for other tests. Is it hard to make them table-based like `test_save_surface_to_dds()` (i.e. looping on test cases in a `tests[]` array of structures)?
Largely just that it'd be extra work to make the older, existing tests that we're using this new function for table based and I'm lazy :D I can modify them to use a table if you think it'd be worth it.
On Mon Nov 11 15:37:29 2024 +0000, Connor McAdams wrote:
Largely just that it'd be extra work to make the older, existing tests that we're using this new function for table based and I'm lazy :D I can modify them to use a table if you think it'd be worth it.
Nah, this is fine :smile:
This merge request was approved by Matteo Bruni.