From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/tests/surface.c | 635 ++++++++++++++++++++++++++++++++++ 1 file changed, 635 insertions(+)
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index fdc573c3e55..abd583e296a 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -26,6 +26,23 @@ #include <stdint.h> #include "d3dx9_test_images.h"
+#define ADMITTED_ERROR 0.0001f + +static inline float relative_error(float expected, float got) +{ + return expected == 0.0f ? fabs(expected - got) : fabs(1.0f - got / expected); +} + +static BOOL relative_float_match(float expected, float got, float admitted_error) +{ + if ((isnan(expected))) + return isnan(got); + if ((isinf(expected))) + return isinf(got); + + return relative_error(expected, got) < ADMITTED_ERROR; +} + #define check_release(obj, exp) _check_release(__LINE__, obj, exp) static inline void _check_release(unsigned int line, IUnknown *obj, int exp) { @@ -755,6 +772,22 @@ static inline void _check_pixel_4bpp(unsigned int line, const D3DLOCKED_RECT *lo ok_(__FILE__, line)(color == expected_color, "Got color 0x%08lx, expected 0x%08lx\n", color, expected_color); }
+#define check_pixel_float4(lockrect, x, y, fx, fy, fz, fw, todo) \ + _check_pixel_float4(__LINE__, lockrect, x, y, fx, fy, fz, fw, todo) +static inline void _check_pixel_float4(uint32_t line, const D3DLOCKED_RECT *lockrect, uint32_t x, uint32_t y, + float fx, float fy, float fz, float fw, BOOL todo) +{ + float *ptr = (float *)(((BYTE *)lockrect->pBits) + (y * lockrect->Pitch) + (x * sizeof(float) * 4)); + + todo_wine_if(todo) ok_(__FILE__, line)(relative_float_match(fx, ptr[0], ADMITTED_ERROR) + && relative_float_match(fy, ptr[1], ADMITTED_ERROR) + && relative_float_match(fz, ptr[2], ADMITTED_ERROR) + && relative_float_match(fw, ptr[3], ADMITTED_ERROR), + "Expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n", + fx, fy, fz, fw, + ptr[0], ptr[1], ptr[2], ptr[3]); +} + #define check_readback_pixel_4bpp(rb, x, y, color, todo) _check_readback_pixel_4bpp(__LINE__, rb, x, y, color, todo) static inline void _check_readback_pixel_4bpp(unsigned int line, struct surface_readback *rb, uint32_t x, uint32_t y, uint32_t expected_color, BOOL todo) @@ -763,6 +796,287 @@ static inline void _check_readback_pixel_4bpp(unsigned int line, struct surface_ todo_wine_if(todo) ok_(__FILE__, line)(color == expected_color, "Got color 0x%08x, expected 0x%08x.\n", color, expected_color); }
+static const PALETTEENTRY test_palette[256] = +{ + {0x00,0x00,0x00,0x00}, {0x00,0x00,0x80,0x01}, {0x00,0x80,0x00,0x02}, {0x00,0x80,0x80,0x03}, + {0x80,0x00,0x00,0x04}, {0x80,0x00,0x80,0x05}, {0x80,0x80,0x00,0x06}, {0xc0,0xc0,0xc0,0x07}, + {0xc0,0xdc,0xc0,0x08}, {0xf0,0xca,0xa6,0x09}, {0x00,0x20,0x40,0x0a}, {0x00,0x20,0x60,0x0b}, + {0x00,0x20,0x80,0x0c}, {0x00,0x20,0xa0,0x0d}, {0x00,0x20,0xc0,0x0e}, {0x00,0x20,0xe0,0x0f}, + + {0x00,0x40,0x00,0x10}, {0x00,0x40,0x20,0x11}, {0x00,0x40,0x40,0x12}, {0x00,0x40,0x60,0x13}, + {0x00,0x40,0x80,0x14}, {0x00,0x40,0xa0,0x15}, {0x00,0x40,0xc0,0x16}, {0x00,0x40,0xe0,0x17}, + {0x00,0x60,0x00,0x18}, {0x00,0x60,0x20,0x19}, {0x00,0x60,0x40,0x1a}, {0x00,0x60,0x60,0x1b}, + {0x00,0x60,0x80,0x1c}, {0x00,0x60,0xa0,0x1d}, {0x00,0x60,0xc0,0x1e}, {0x00,0x60,0xe0,0x1f}, + + {0x00,0x80,0x00,0x20}, {0x00,0x80,0x20,0x21}, {0x00,0x80,0x40,0x22}, {0x00,0x80,0x60,0x23}, + {0x00,0x80,0x80,0x24}, {0x00,0x80,0xa0,0x25}, {0x00,0x80,0xc0,0x26}, {0x00,0x80,0xe0,0x27}, + {0x00,0xa0,0x00,0x28}, {0x00,0xa0,0x20,0x29}, {0x00,0xa0,0x40,0x2a}, {0x00,0xa0,0x60,0x2b}, + {0x00,0xa0,0x80,0x2c}, {0x00,0xa0,0xa0,0x2d}, {0x00,0xa0,0xc0,0x2e}, {0x00,0xa0,0xe0,0x2f}, + + {0x00,0xc0,0x00,0x30}, {0x00,0xc0,0x20,0x31}, {0x00,0xc0,0x40,0x32}, {0x00,0xc0,0x60,0x33}, + {0x00,0xc0,0x80,0x34}, {0x00,0xc0,0xa0,0x35}, {0x00,0xc0,0xc0,0x36}, {0x00,0xc0,0xe0,0x37}, + {0x00,0xe0,0x00,0x38}, {0x00,0xe0,0x20,0x39}, {0x00,0xe0,0x40,0x3a}, {0x00,0xe0,0x60,0x3b}, + {0x00,0xe0,0x80,0x3c}, {0x00,0xe0,0xa0,0x3d}, {0x00,0xe0,0xc0,0x3e}, {0x00,0xe0,0xe0,0x3f}, + + {0x40,0x00,0x00,0x40}, {0x40,0x00,0x20,0x41}, {0x40,0x00,0x40,0x42}, {0x40,0x00,0x60,0x43}, + {0x40,0x00,0x80,0x44}, {0x40,0x00,0xa0,0x45}, {0x40,0x00,0xc0,0x46}, {0x40,0x00,0xe0,0x47}, + {0x40,0x20,0x00,0x48}, {0x40,0x20,0x20,0x49}, {0x40,0x20,0x40,0x4a}, {0x40,0x20,0x60,0x4b}, + {0x40,0x20,0x80,0x4c}, {0x40,0x20,0xa0,0x4d}, {0x40,0x20,0xc0,0x4e}, {0x40,0x20,0xe0,0x4f}, + + {0x40,0x40,0x00,0x50}, {0x40,0x40,0x20,0x51}, {0x40,0x40,0x40,0x52}, {0x40,0x40,0x60,0x53}, + {0x40,0x40,0x80,0x54}, {0x40,0x40,0xa0,0x55}, {0x40,0x40,0xc0,0x56}, {0x40,0x40,0xe0,0x57}, + {0x40,0x60,0x00,0x58}, {0x40,0x60,0x20,0x59}, {0x40,0x60,0x40,0x5a}, {0x40,0x60,0x60,0x5b}, + {0x40,0x60,0x80,0x5c}, {0x40,0x60,0xa0,0x5d}, {0x40,0x60,0xc0,0x5e}, {0x40,0x60,0xe0,0x5f}, + + {0x40,0x80,0x00,0x60}, {0x40,0x80,0x20,0x61}, {0x40,0x80,0x40,0x62}, {0x40,0x80,0x60,0x63}, + {0x40,0x80,0x80,0x64}, {0x40,0x80,0xa0,0x65}, {0x40,0x80,0xc0,0x66}, {0x40,0x80,0xe0,0x67}, + {0x40,0xa0,0x00,0x68}, {0x40,0xa0,0x20,0x69}, {0x40,0xa0,0x40,0x6a}, {0x40,0xa0,0x60,0x6b}, + {0x40,0xa0,0x80,0x6c}, {0x40,0xa0,0xa0,0x6d}, {0x40,0xa0,0xc0,0x6e}, {0x40,0xa0,0xe0,0x6f}, + + {0x40,0xc0,0x00,0x70}, {0x40,0xc0,0x20,0x71}, {0x40,0xc0,0x40,0x72}, {0x40,0xc0,0x60,0x73}, + {0x40,0xc0,0x80,0x74}, {0x40,0xc0,0xa0,0x75}, {0x40,0xc0,0xc0,0x76}, {0x40,0xc0,0xe0,0x77}, + {0x40,0xe0,0x00,0x78}, {0x40,0xe0,0x20,0x79}, {0x40,0xe0,0x40,0x7a}, {0x40,0xe0,0x60,0x7b}, + {0x40,0xe0,0x80,0x7c}, {0x40,0xe0,0xa0,0x7d}, {0x40,0xe0,0xc0,0x7e}, {0x40,0xe0,0xe0,0x7f}, + + {0x80,0x00,0x00,0x80}, {0x80,0x00,0x20,0x81}, {0x80,0x00,0x40,0x82}, {0x80,0x00,0x60,0x83}, + {0x80,0x00,0x80,0x84}, {0x80,0x00,0xa0,0x85}, {0x80,0x00,0xc0,0x86}, {0x80,0x00,0xe0,0x87}, + {0x80,0x20,0x00,0x88}, {0x80,0x20,0x20,0x89}, {0x80,0x20,0x40,0x8a}, {0x80,0x20,0x60,0x8b}, + {0x80,0x20,0x80,0x8c}, {0x80,0x20,0xa0,0x8d}, {0x80,0x20,0xc0,0x8e}, {0x80,0x20,0xe0,0x8f}, + + {0x80,0x40,0x00,0x90}, {0x80,0x40,0x20,0x91}, {0x80,0x40,0x40,0x92}, {0x80,0x40,0x60,0x93}, + {0x80,0x40,0x80,0x94}, {0x80,0x40,0xa0,0x95}, {0x80,0x40,0xc0,0x96}, {0x80,0x40,0xe0,0x97}, + {0x80,0x60,0x00,0x98}, {0x80,0x60,0x20,0x99}, {0x80,0x60,0x40,0x9a}, {0x80,0x60,0x60,0x9b}, + {0x80,0x60,0x80,0x9c}, {0x80,0x60,0xa0,0x9d}, {0x80,0x60,0xc0,0x9e}, {0x80,0x60,0xe0,0x9f}, + + {0x80,0x80,0x00,0xa0}, {0x80,0x80,0x20,0xa1}, {0x80,0x80,0x40,0xa2}, {0x80,0x80,0x60,0xa3}, + {0x80,0x80,0x80,0xa4}, {0x80,0x80,0xa0,0xa5}, {0x80,0x80,0xc0,0xa6}, {0x80,0x80,0xe0,0xa7}, + {0x80,0xa0,0x00,0xa8}, {0x80,0xa0,0x20,0xa9}, {0x80,0xa0,0x40,0xaa}, {0x80,0xa0,0x60,0xab}, + {0x80,0xa0,0x80,0xac}, {0x80,0xa0,0xa0,0xad}, {0x80,0xa0,0xc0,0xae}, {0x80,0xa0,0xe0,0xaf}, + + {0x80,0xc0,0x00,0xb0}, {0x80,0xc0,0x20,0xb1}, {0x80,0xc0,0x40,0xb2}, {0x80,0xc0,0x60,0xb3}, + {0x80,0xc0,0x80,0xb4}, {0x80,0xc0,0xa0,0xb5}, {0x80,0xc0,0xc0,0xb6}, {0x80,0xc0,0xe0,0xb7}, + {0x80,0xe0,0x00,0xb8}, {0x80,0xe0,0x20,0xb9}, {0x80,0xe0,0x40,0xba}, {0x80,0xe0,0x60,0xbb}, + {0x80,0xe0,0x80,0xbc}, {0x80,0xe0,0xa0,0xbd}, {0x80,0xe0,0xc0,0xbe}, {0x80,0xe0,0xe0,0xbf}, + + {0xc0,0x00,0x00,0xc0}, {0xc0,0x00,0x20,0xc1}, {0xc0,0x00,0x40,0xc2}, {0xc0,0x00,0x60,0xc3}, + {0xc0,0x00,0x80,0xc4}, {0xc0,0x00,0xa0,0xc5}, {0xc0,0x00,0xc0,0xc6}, {0xc0,0x00,0xe0,0xc7}, + {0xc0,0x20,0x00,0xc8}, {0xc0,0x20,0x20,0xc9}, {0xc0,0x20,0x40,0xca}, {0xc0,0x20,0x60,0xcb}, + {0xc0,0x20,0x80,0xcc}, {0xc0,0x20,0xa0,0xcd}, {0xc0,0x20,0xc0,0xce}, {0xc0,0x20,0xe0,0xcf}, + + {0xc0,0x40,0x00,0xd0}, {0xc0,0x40,0x20,0xd1}, {0xc0,0x40,0x40,0xd2}, {0xc0,0x40,0x60,0xd3}, + {0xc0,0x40,0x80,0xd4}, {0xc0,0x40,0xa0,0xd5}, {0xc0,0x40,0xc0,0xd6}, {0xc0,0x40,0xe0,0xd7}, + {0xc0,0x60,0x00,0xd8}, {0xc0,0x60,0x20,0xd9}, {0xc0,0x60,0x40,0xda}, {0xc0,0x60,0x60,0xdb}, + {0xc0,0x60,0x80,0xdc}, {0xc0,0x60,0xa0,0xdd}, {0xc0,0x60,0xc0,0xde}, {0xc0,0x60,0xe0,0xdf}, + + {0xc0,0x80,0x00,0xe0}, {0xc0,0x80,0x20,0xe1}, {0xc0,0x80,0x40,0xe2}, {0xc0,0x80,0x60,0xe3}, + {0xc0,0x80,0x80,0xe4}, {0xc0,0x80,0xa0,0xe5}, {0xc0,0x80,0xc0,0xe6}, {0xc0,0x80,0xe0,0xe7}, + {0xc0,0xa0,0x00,0xe8}, {0xc0,0xa0,0x20,0xe9}, {0xc0,0xa0,0x40,0xea}, {0xc0,0xa0,0x60,0xeb}, + {0xc0,0xa0,0x80,0xec}, {0xc0,0xa0,0xa0,0xed}, {0xc0,0xa0,0xc0,0xee}, {0xc0,0xa0,0xe0,0xef}, + + {0xc0,0xc0,0x00,0xf0}, {0xc0,0xc0,0x20,0xf1}, {0xc0,0xc0,0x40,0xf2}, {0xc0,0xc0,0x60,0xf3}, + {0xc0,0xc0,0x80,0xf4}, {0xc0,0xc0,0xa0,0xf5}, {0xf0,0xfb,0xff,0xf6}, {0xa4,0xa0,0xa0,0xf7}, + {0x80,0x80,0x80,0xf8}, {0x00,0x00,0xff,0xf9}, {0x00,0xff,0x00,0xfa}, {0x00,0xff,0xff,0xfb}, + {0xff,0x00,0x00,0xfc}, {0xff,0x00,0xff,0xfd}, {0xff,0xff,0x00,0xfe}, {0xff,0xff,0xff,0xff}, +}; + +static const uint16_t v16u16_2_2[] = +{ + 0x0000, 0x3000, 0x4000, 0x7fff, 0x8000, 0x8001, 0xc000, 0xffff, +}; + +static const uint8_t v16u16_2_2_expected[] = +{ + 0x00,0x80,0x00,0xb0,0x00,0xc0,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0x3f,0xff,0x7f, +}; + +static const uint8_t v16u16_2_2_expected2[] = +{ + 0x00,0x00,0x00,0x00,0x80,0x01,0xc0,0x3e,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f, + 0x00,0x01,0x00,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f, + 0x00,0x00,0x80,0xbf,0x00,0x00,0x80,0xbf,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f, + 0x00,0x01,0x00,0xbf,0x00,0x01,0x00,0xb8,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f, +}; + +static const uint8_t v8u8_2_2[] = +{ + 0x00,0x30,0x40,0x7f,0x80,0x81,0xc0,0xff, +}; + +static const uint8_t v8u8_2_2_expected[] = +{ + 0x00,0x00,0x00,0x00,0x06,0x83,0xc1,0x3e,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f, + 0x04,0x02,0x01,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f, + 0x00,0x00,0x80,0xbf,0x00,0x00,0x80,0xbf,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f, + 0x04,0x02,0x01,0xbf,0x04,0x02,0x01,0xbc,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f, +}; + +static const uint16_t a16b16g16r16_2_2[] = +{ + 0x0000,0x1000,0x2000,0x3000,0x4000,0x5000,0x6000,0x7000, + 0x8000,0x9000,0xa000,0xb000,0xc000,0xd000,0xe000,0xffff, +}; + +static const uint8_t a16b16g16r16_2_2_expected[] = +{ + 0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x3d,0x80,0x00,0x00,0x3e,0xc0,0x00,0x40,0x3e, + 0x80,0x00,0x80,0x3e,0xa0,0x00,0xa0,0x3e,0xc0,0x00,0xc0,0x3e,0xe0,0x00,0xe0,0x3e, + 0x80,0x00,0x00,0x3f,0x90,0x00,0x10,0x3f,0xa0,0x00,0x20,0x3f,0xb0,0x00,0x30,0x3f, + 0xc0,0x00,0x40,0x3f,0xd0,0x00,0x50,0x3f,0xe0,0x00,0x60,0x3f,0x00,0x00,0x80,0x3f, +}; + +static const uint16_t q16w16v16u16_2_2[] = +{ + 0x0000,0x1000,0x2000,0x3000,0x4000,0x5000,0x6000,0x7fff, + 0x8000,0x8001,0xa000,0xb000,0xc000,0xd000,0xe000,0xffff, +}; + +static const uint8_t q16w16v16u16_2_2_expected[] = +{ + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x3e,0x00,0x01,0x80,0x3e,0x80,0x01,0xc0,0x3e, + 0x00,0x01,0x00,0x3f,0x40,0x01,0x20,0x3f,0x80,0x01,0x40,0x3f,0x00,0x00,0x80,0x3f, + 0x00,0x00,0x80,0xbf,0x00,0x00,0x80,0xbf,0x80,0x01,0x40,0xbf,0x40,0x01,0x20,0xbf, + 0x00,0x01,0x00,0xbf,0x80,0x01,0xc0,0xbe,0x00,0x01,0x80,0xbe,0x00,0x01,0x00,0xb8, +}; + +static const uint8_t p8_2_2[] = +{ + 0x00,0x40,0x80,0xff, +}; + +static const uint8_t p8_2_2_expected[] = +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x00,0x80,0x80,0xff,0xff,0xff,0xff, +}; + +static const uint8_t a8p8_2_2[] = +{ + 0x00,0x10,0x40,0x20,0x80,0x30,0xff,0x40 +}; + +static const uint8_t a8p8_2_2_expected[] = +{ + 0x00,0x00,0x00,0x10,0x00,0x00,0x40,0x20,0x00,0x00,0x80,0x30,0xff,0xff,0xff,0x40, +}; + +static uint32_t get_bpp_for_d3dformat(D3DFORMAT format) +{ + switch (format) + { + case D3DFMT_A32B32G32R32F: + return 16; + + case D3DFMT_A16B16G16R16: + case D3DFMT_Q16W16V16U16: + return 8; + + case D3DFMT_A8R8G8B8: + case D3DFMT_V16U16: + case D3DFMT_G16R16: + return 4; + + case D3DFMT_V8U8: + case D3DFMT_A8P8: + return 2; + + case D3DFMT_P8: + return 1; + + default: + assert(0 && "Need to add format to get_bpp_for_d3dformat()."); + return 0; + } +} + +static void test_format_conversion(IDirect3DDevice9 *device) +{ + struct + { + D3DFORMAT src_format; + const PALETTEENTRY *src_palette; + const RECT src_rect; + const void *src_data; + + D3DFORMAT dst_format; + const void *expected_dst_data; + BOOL partial_todo; + BOOL todo; + } tests[] = { + { D3DFMT_P8, test_palette, { 0, 0, 2, 2 }, p8_2_2, D3DFMT_A8R8G8B8, p8_2_2_expected }, + { D3DFMT_A16B16G16R16, NULL, { 0, 0, 2, 2 }, a16b16g16r16_2_2, D3DFMT_A32B32G32R32F, a16b16g16r16_2_2_expected }, + { D3DFMT_V16U16, NULL, { 0, 0, 2, 2 }, v16u16_2_2, D3DFMT_G16R16, v16u16_2_2_expected, .todo = TRUE }, + { D3DFMT_V16U16, NULL, { 0, 0, 2, 2 }, v16u16_2_2, D3DFMT_A32B32G32R32F, v16u16_2_2_expected2, .todo = TRUE }, + { D3DFMT_V8U8, NULL, { 0, 0, 2, 2 }, v8u8_2_2, D3DFMT_A32B32G32R32F, v8u8_2_2_expected, .todo = TRUE }, + { D3DFMT_Q16W16V16U16, NULL, { 0, 0, 2, 2 }, q16w16v16u16_2_2, D3DFMT_A32B32G32R32F, q16w16v16u16_2_2_expected, .todo = TRUE }, + { D3DFMT_A8P8, test_palette, { 0, 0, 2, 2 }, a8p8_2_2, D3DFMT_A8R8G8B8, a8p8_2_2_expected, .todo = TRUE }, + }; + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + IDirect3DTexture9 *tex; + HRESULT hr; + + winetest_push_context("Test %u", i); + hr = IDirect3DDevice9_CreateTexture(device, tests[i].src_rect.right, tests[i].src_rect.bottom, 1, 0, + tests[i].dst_format, D3DPOOL_MANAGED, &tex, NULL); + if (SUCCEEDED(hr)) + { + const uint32_t src_pitch = get_bpp_for_d3dformat(tests[i].src_format) * tests[i].src_rect.right; + const uint32_t dst_pitch = get_bpp_for_d3dformat(tests[i].dst_format) * tests[i].src_rect.right; + IDirect3DSurface9 *surf; + + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surf); + ok(hr == D3D_OK, "Failed to get the surface, hr %#lx.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, tests[i].src_data, tests[i].src_format, + src_pitch, tests[i].src_palette, &tests[i].src_rect, D3DX_FILTER_NONE, 0); + todo_wine_if(tests[i].todo) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + const uint32_t dst_fmt_bpp = get_bpp_for_d3dformat(tests[i].dst_format); + uint32_t match_count, mismatch_count; + D3DLOCKED_RECT lock_rect; + uint32_t x, y; + + match_count = mismatch_count = 0; + IDirect3DSurface9_LockRect(surf, &lock_rect, NULL, D3DLOCK_READONLY); + for (y = 0; y < tests[i].src_rect.bottom; ++y) + { + const uint8_t *dst_expected_row = ((uint8_t *)tests[i].expected_dst_data) + (dst_pitch * y); + const uint8_t *dst_row = ((uint8_t *)lock_rect.pBits) + (lock_rect.Pitch * y); + + for (x = 0; x < tests[i].src_rect.right; ++x) + { + const uint8_t *dst_expected_pixel = dst_expected_row + (dst_fmt_bpp * x); + const uint8_t *dst_pixel = dst_row + (dst_fmt_bpp * x); + BOOL pixel_match = !memcmp(dst_pixel, dst_expected_pixel, dst_fmt_bpp); + + if (!pixel_match) + mismatch_count++; + else + match_count++; + + if (!pixel_match && tests[i].partial_todo) + continue; + todo_wine_if(tests[i].todo) ok(pixel_match, "Pixel mismatch at (%u,%u).\n", x, y); + } + } + + todo_wine_if(tests[i].partial_todo || tests[i].todo) ok(!mismatch_count, "%u mismatched pixels.\n", mismatch_count); + IDirect3DSurface9_UnlockRect(surf); + } + + check_release((IUnknown *)surf, 1); + check_release((IUnknown *)tex, 0); + } + else + { + skip("Failed to create texture for format %d, hr %#lx.\n", tests[i].dst_format, hr); + } + winetest_pop_context(); + } +} + static void test_D3DXLoadSurface(IDirect3DDevice9 *device) { HRESULT hr; @@ -779,6 +1093,13 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) static const DWORD pixdata_a8b8g8r8[] = { 0xc3394cf0, 0x235ae892, 0x09b197fd, 0x8dc32bf6 }; static const DWORD pixdata_a2r10g10b10[] = { 0x57395aff, 0x5b7668fd, 0xb0d856b5, 0xff2c61d6 }; static const uint32_t pixdata_a8r8g8b8[] = { 0x00102030, 0x40506070, 0x8090a0b0, 0xc0d0e0ff }; + static const uint32_t pixdata_a8b8g8r8_2[] = { 0x30201000, 0x70605040, 0xb0a09080, 0xffe0d0c0 }; + static const uint32_t pixdata_x8l8v8u8[] = { 0x00003000, 0x00557f40, 0x00aa8180, 0x00ffffc0 }; + static const uint32_t pixdata_a2w10v10u10[] = { 0x0ba17400, 0x5ff5d117, 0xae880600, 0xfffe8b45 }; + static const uint32_t pixdata_q8w8v8u8[] = { 0x30201000, 0x7f605040, 0xb0a08180, 0xffe0d0c0 }; + static const float pixdata_a32b32g32r32f[] = { 0.0f, 0.1f, NAN, INFINITY, 1.0f, 1.1f, 1.2f, 1.3f, + -0.1f, -0.2f, -NAN, -INFINITY, -1.0f, -1.1f, -1.2f, -1.3f }; + static const uint16_t pixdata_v8u8[] = { 0x3000, 0x7f40, 0x8180, 0xffc0 }; BYTE buffer[4 * 8 * 4]; uint32_t i;
@@ -1197,6 +1518,34 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) hr = IDirect3DSurface9_UnlockRect(surf); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
+ /* From a signed normalized format to an unsigned normalized format. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_4bpp(&lockrect, 0, 0, 0xb08090a0); + check_pixel_4bpp(&lockrect, 1, 0, 0xffc0d0e0); + check_pixel_4bpp(&lockrect, 0, 1, 0x2f00001f); + check_pixel_4bpp(&lockrect, 1, 1, 0x7e3f4f5f); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + } + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a32b32g32r32f, D3DFMT_A32B32G32R32F, 32, NULL, &rect, + D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0xff001aff); + todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0xffffffff); + todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x000000ff); + todo_wine check_pixel_4bpp(&lockrect, 1, 1, 0x00000000); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + /* Test D3DXLoadSurfaceFromMemory with indexed color image */ if (0) { @@ -1422,6 +1771,33 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) hr = IDirect3DSurface9_UnlockRect(surf); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0xb08d); + check_pixel_2bpp(&lockrect, 1, 0, 0xffce); + check_pixel_2bpp(&lockrect, 0, 1, 0x2f02); + check_pixel_2bpp(&lockrect, 1, 1, 0x7e4d); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + } + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a32b32g32r32f, D3DFMT_A32B32G32R32F, 32, NULL, &rect, + D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_2bpp(&lockrect, 0, 0, 0xff25); + todo_wine check_pixel_2bpp(&lockrect, 1, 0, 0xffff); + todo_wine check_pixel_2bpp(&lockrect, 0, 1, 0x0012); + todo_wine check_pixel_2bpp(&lockrect, 1, 1, 0x0000); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + check_release((IUnknown*)surf, 1); check_release((IUnknown*)tex, 0); } @@ -1646,6 +2022,265 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) check_release((IUnknown*)surf, 0); }
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &surf, NULL); + if (FAILED(hr)) + skip("Failed to create a D3DFMT_A32B32G32R32F surface, hr %#lx.\n", hr); + else + { + /* Direct copy. */ + SetRect(&rect, 0, 0, 2, 2); + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a32b32g32r32f, D3DFMT_A32B32G32R32F, 32, NULL, &rect, + D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_float4(&lockrect, 0, 0, pixdata_a32b32g32r32f[0], pixdata_a32b32g32r32f[1], + pixdata_a32b32g32r32f[2], pixdata_a32b32g32r32f[3], FALSE); + check_pixel_float4(&lockrect, 1, 0, pixdata_a32b32g32r32f[4], pixdata_a32b32g32r32f[5], + pixdata_a32b32g32r32f[6], pixdata_a32b32g32r32f[7], FALSE); + check_pixel_float4(&lockrect, 0, 1, pixdata_a32b32g32r32f[8], pixdata_a32b32g32r32f[9], + pixdata_a32b32g32r32f[10], pixdata_a32b32g32r32f[11], FALSE); + check_pixel_float4(&lockrect, 1, 1, pixdata_a32b32g32r32f[12], pixdata_a32b32g32r32f[13], + pixdata_a32b32g32r32f[14], pixdata_a32b32g32r32f[15], FALSE); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* Signed normalized value to full range float. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_float4(&lockrect, 0, 0, 0.0f, 0.125984f, 0.251969f, 0.377953f, TRUE); + check_pixel_float4(&lockrect, 1, 0, 0.503937f, 0.629921f, 0.755906f, 1.0f, TRUE); + check_pixel_float4(&lockrect, 0, 1, -1.0f, -1.0f, -0.755906f, -0.629921f, TRUE); + check_pixel_float4(&lockrect, 1, 1, -0.503937f, -0.377953f, -0.251969f, -0.007874f, TRUE); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* Unsigned normalized value to full range float. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8_2, D3DFMT_A8B8G8R8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_float4(&lockrect, 0, 0, 0.0f, 0.062745f, 0.125490f, 0.188235f, FALSE); + check_pixel_float4(&lockrect, 1, 0, 0.250980f, 0.313726f, 0.376471f, 0.439216f, FALSE); + check_pixel_float4(&lockrect, 0, 1, 0.501961f, 0.564706f, 0.627451f, 0.690196f, FALSE); + check_pixel_float4(&lockrect, 1, 1, 0.752941f, 0.815686f, 0.878431f, 1.0f, FALSE); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* V8U8 snorm. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_v8u8, D3DFMT_V8U8, 4, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_float4(&lockrect, 0, 0, 0.0f, 0.377953f, 1.0f, 1.0f, TRUE); + check_pixel_float4(&lockrect, 1, 0, 0.503937f, 1.0f, 1.0f, 1.0f, TRUE); + check_pixel_float4(&lockrect, 0, 1, -1.0f, -1.0f, 1.0f, 1.0f, TRUE); + check_pixel_float4(&lockrect, 1, 1, -0.503937f, -0.007874f, 1.0f, 1.0f, TRUE); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* A2W10V10U10 unorm/snorm. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2w10v10u10, D3DFMT_A2W10V10U10, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_float4(&lockrect, 0, 0, 0.0f, 0.181996f, 0.363992f, 0.0f, TRUE); + check_pixel_float4(&lockrect, 1, 0, 0.545988f, 0.727984f, 1.0f, 0.333333f, TRUE); + check_pixel_float4(&lockrect, 0, 1, -1.0f, -1.0f, -0.547945f, 0.666667f, TRUE); + check_pixel_float4(&lockrect, 1, 1, -0.365949f, -0.183953f, -0.001957f, 1.0f, TRUE); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* X8L8V8U8 unorm/snorm. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_x8l8v8u8, D3DFMT_X8L8V8U8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + /* The luma value goes into the alpha channel. */ + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_float4(&lockrect, 0, 0, 0.0f, 0.377953f, 1.0f, 0.0f, FALSE); + check_pixel_float4(&lockrect, 1, 0, 0.503937f, 1.0f, 1.0f, 0.333333f, FALSE); + check_pixel_float4(&lockrect, 0, 1, -1.0f, -1.0f, 1.0f, 0.666667f, FALSE); + check_pixel_float4(&lockrect, 1, 1, -0.503937f, -0.007874f, 1.0f, 1.0f, FALSE); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + } + + check_release((IUnknown*)surf, 0); + } + + hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_Q8W8V8U8, D3DPOOL_MANAGED, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create D3DFMT_Q8W8V8U8 texture, hr %#lx.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surf); + ok(hr == D3D_OK, "Failed to get the surface, hr %#lx.\n", hr); + + /* Snorm to snorm, direct copy. */ + SetRect(&rect, 0, 0, 2, 2); + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_4bpp(&lockrect, 0, 0, pixdata_q8w8v8u8[0]); + todo_wine check_pixel_4bpp(&lockrect, 1, 0, pixdata_q8w8v8u8[1]); + todo_wine check_pixel_4bpp(&lockrect, 0, 1, pixdata_q8w8v8u8[2]); + todo_wine check_pixel_4bpp(&lockrect, 1, 1, pixdata_q8w8v8u8[3]); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* Unorm to snorm. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, + D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0x43bbce70); + todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0xa5dc6812); + todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x8b31177d); + todo_wine check_pixel_4bpp(&lockrect, 1, 1, 0x0d43ad76); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* Full range float to snorm. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a32b32g32r32f, D3DFMT_A32B32G32R32F, 32, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0x7f7f0d00); + todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0x7f7f7f7f); + todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x827fe8f4); + todo_wine check_pixel_4bpp(&lockrect, 1, 1, 0x82828282); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* Unorm alpha and unorm luma to snorm. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8l8, D3DFMT_A8L8, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0x7f828282); + todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0x827f7f7f); + todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x7fb2b2b2); + check_pixel_4bpp(&lockrect, 1, 1, 0x00000000); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + check_release((IUnknown*)surf, 1); + check_release((IUnknown*)tex, 0); + } + + hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create D3DFMT_X8L8V8U8 texture, hr %#lx.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surf); + ok(hr == D3D_OK, "Failed to get the surface, hr %#lx.\n", hr); + + SetRect(&rect, 0, 0, 2, 2); + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8_2, D3DFMT_A8B8G8R8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + /* + * The luma channel here doesn't do RGB->Luma conversion, it just + * copies the alpha channel directly as UNORM. V8 and U8 are snorm, + * pulled from r/g respectively. The X8 (b) channel is set to 0. + */ + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0x00309282); + todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0x0070d2c2); + todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x00b01000); + todo_wine check_pixel_4bpp(&lockrect, 1, 1, 0x00ff5040); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* Q8 will get converted to unorm range, v8u8 will be copied. */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0x00b01000); + todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0x00ff5040); + todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x002f8282); + todo_wine check_pixel_4bpp(&lockrect, 1, 1, 0x007ed1c1); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + check_release((IUnknown*)surf, 1); + check_release((IUnknown*)tex, 0); + } + + hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create D3DFMT_V8U8 texture, hr %#lx.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surf); + ok(hr == D3D_OK, "Failed to get the surface, hr %#lx.\n", hr); + + /* R and G channels converted to SNORM range. */ + SetRect(&rect, 0, 0, 2, 2); + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8_2, D3DFMT_A8B8G8R8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_2bpp(&lockrect, 0, 0, 0x9282); + todo_wine check_pixel_2bpp(&lockrect, 1, 0, 0xd2c2); + todo_wine check_pixel_2bpp(&lockrect, 0, 1, 0x1000); + todo_wine check_pixel_2bpp(&lockrect, 1, 1, 0x5040); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + /* + * Pull the V8U8 channels. Even though they're the same range, they're + * not directly copied over. 0x80/0x81 are clamped to 0x82, and + * 0xd0/0xc0 end up as 0xd1/0xc1. + */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, + D3DX_FILTER_NONE, 0); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + todo_wine check_pixel_2bpp(&lockrect, 0, 0, 0x1000); + todo_wine check_pixel_2bpp(&lockrect, 1, 0, 0x5040); + todo_wine check_pixel_2bpp(&lockrect, 0, 1, 0x8282); + todo_wine check_pixel_2bpp(&lockrect, 1, 1, 0xd1c1); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); + + check_release((IUnknown*)surf, 1); + check_release((IUnknown*)tex, 0); + } + + test_format_conversion(device); + /* cleanup */ if(testdummy_ok) DeleteFileA("testdummy.bmp"); if(testbitmap_ok) DeleteFileA("testbitmap.bmp");