1 /*
2  * Tests for the D3DX9 surface functions
3  *
4  * Copyright 2009 Tony Wasserka
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define COBJMACROS
22 #include <assert.h>
23 #include "wine/test.h"
24 #include "d3dx9tex.h"
25 #include "resources.h"
26 
27 #define check_release(obj, exp) _check_release(__LINE__, obj, exp)
28 static inline void _check_release(unsigned int line, IUnknown *obj, int exp)
29 {
30     int ref = IUnknown_Release(obj);
31     ok_(__FILE__, line)(ref == exp, "Invalid refcount. Expected %d, got %d\n", exp, ref);
32 }
33 
34 /* 1x1 bmp (1 bpp) */
35 static const unsigned char bmp_1bpp[] = {
36 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
37 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
38 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
39 0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00,
40 0x00,0x00
41 };
42 
43 /* 1x1 bmp (2 bpp) */
44 static const unsigned char bmp_2bpp[] = {
45 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
46 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,
47 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
48 0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00,
49 0x00,0x00
50 };
51 
52 /* 1x1 bmp (4 bpp) */
53 static const unsigned char bmp_4bpp[] = {
54 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
55 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00,
56 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
57 0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00,
58 0x00,0x00
59 };
60 
61 /* 1x1 bmp (8 bpp) */
62 static const unsigned char bmp_8bpp[] = {
63 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
64 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x00,
65 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
66 0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00,
67 0x00,0x00
68 };
69 
70 /* 2x2 bmp (32 bpp XRGB) */
71 static const unsigned char bmp_32bpp_xrgb[] = {
72 0x42,0x4d,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
73 0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x20,0x00,0x00,0x00,
74 0x00,0x00,0x10,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x00,0x00,
75 0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0xb0,0xc0,0x00,0xa1,0xb1,0xc1,0x00,0xa2,0xb2,
76 0xc2,0x00,0xa3,0xb3,0xc3,0x00
77 };
78 
79 /* 2x2 bmp (32 bpp ARGB) */
80 static const unsigned char bmp_32bpp_argb[] = {
81 0x42,0x4d,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
82 0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x20,0x00,0x00,0x00,
83 0x00,0x00,0x10,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x00,0x00,
84 0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0xb0,0xc0,0x00,0xa1,0xb1,0xc1,0x00,0xa2,0xb2,
85 0xc2,0x00,0xa3,0xb3,0xc3,0x01
86 };
87 
88 static const unsigned char png_grayscale[] =
89 {
90     0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49,
91     0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
92     0x00, 0x00, 0x00, 0x3a, 0x7e, 0x9b, 0x55, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44,
93     0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0x0f, 0x00, 0x01, 0x01, 0x01, 0x00, 0x1b,
94     0xb6, 0xee, 0x56, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
95     0x60, 0x82
96 };
97 
98 /* 2x2 A8R8G8B8 pixel data */
99 static const unsigned char pixdata[] = {
100 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
101 };
102 
103 /* invalid image file */
104 static const unsigned char noimage[4] = {
105 0x11,0x22,0x33,0x44
106 };
107 
108 /* 2x2 24-bit dds, 2 mipmaps */
109 static const unsigned char dds_24bit[] = {
110 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x0a,0x00,0x02,0x00,0x00,0x00,
111 0x02,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
112 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
113 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
114 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
115 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00,
116 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00,
117 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
118 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
119 };
120 
121 /* 2x2 16-bit dds, no mipmaps */
122 static const unsigned char dds_16bit[] = {
123 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x02,0x00,0x00,0x00,
124 0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
125 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
127 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
128 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,
129 0xe0,0x03,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,
130 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
131 0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0x7f
132 };
133 
134 /* 4x4 cube map dds */
135 static const unsigned char dds_cube_map[] = {
136 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x04,0x00,0x00,0x00,
137 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
138 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
139 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
141 0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00,0x00,
143 0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50,
145 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50,
146 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50,
147 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50,
148 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50,
149 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50
150 };
151 
152 /* 4x4x2 volume map dds, 2 mipmaps */
153 static const unsigned char dds_volume_map[] = {
154 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x8a,0x00,0x04,0x00,0x00,0x00,
155 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
156 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
157 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
158 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
159 0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
160 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00,
161 0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
162 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50,
163 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50,
164 0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x2f,0x7e,0xcf,0x79,0x01,0x54,0x5c,0x5c,
165 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x84,0xef,0x7b,0xaa,0xab,0xab,0xab
166 };
167 
168 static HRESULT create_file(const char *filename, const unsigned char *data, const unsigned int size)
169 {
170     DWORD received;
171     HANDLE hfile;
172 
173     hfile = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
174     if(hfile == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError());
175 
176     if(WriteFile(hfile, data, size, &received, NULL))
177     {
178         CloseHandle(hfile);
179         return D3D_OK;
180     }
181 
182     CloseHandle(hfile);
183     return D3DERR_INVALIDCALL;
184 }
185 
186 /* dds_header.flags */
187 #define DDS_CAPS 0x00000001
188 #define DDS_HEIGHT 0x00000002
189 #define DDS_WIDTH 0x00000004
190 #define DDS_PITCH 0x00000008
191 #define DDS_PIXELFORMAT 0x00001000
192 #define DDS_MIPMAPCOUNT 0x00020000
193 #define DDS_LINEARSIZE 0x00080000
194 
195 /* dds_header.caps */
196 #define DDSCAPS_ALPHA    0x00000002
197 #define DDS_CAPS_TEXTURE 0x00001000
198 
199 /* dds_pixel_format.flags */
200 #define DDS_PF_ALPHA 0x00000001
201 #define DDS_PF_ALPHA_ONLY 0x00000002
202 #define DDS_PF_FOURCC 0x00000004
203 #define DDS_PF_RGB 0x00000040
204 #define DDS_PF_LUMINANCE 0x00020000
205 #define DDS_PF_BUMPDUDV 0x00080000
206 
207 struct dds_pixel_format
208 {
209     DWORD size;
210     DWORD flags;
211     DWORD fourcc;
212     DWORD bpp;
213     DWORD rmask;
214     DWORD gmask;
215     DWORD bmask;
216     DWORD amask;
217 };
218 
219 struct dds_header
220 {
221     DWORD size;
222     DWORD flags;
223     DWORD height;
224     DWORD width;
225     DWORD pitch_or_linear_size;
226     DWORD depth;
227     DWORD miplevels;
228     DWORD reserved[11];
229     struct dds_pixel_format pixel_format;
230     DWORD caps;
231     DWORD caps2;
232     DWORD caps3;
233     DWORD caps4;
234     DWORD reserved2;
235 };
236 
237 /* fills dds_header with reasonable default values */
238 static void fill_dds_header(struct dds_header *header)
239 {
240     memset(header, 0, sizeof(*header));
241 
242     header->size = sizeof(*header);
243     header->flags = DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT;
244     header->height = 4;
245     header->width = 4;
246     header->pixel_format.size = sizeof(header->pixel_format);
247     /* X8R8G8B8 */
248     header->pixel_format.flags = DDS_PF_RGB;
249     header->pixel_format.fourcc = 0;
250     header->pixel_format.bpp = 32;
251     header->pixel_format.rmask = 0xff0000;
252     header->pixel_format.gmask = 0x00ff00;
253     header->pixel_format.bmask = 0x0000ff;
254     header->pixel_format.amask = 0;
255     header->caps = DDS_CAPS_TEXTURE;
256 }
257 
258 #define check_dds_pixel_format(flags, fourcc, bpp, rmask, gmask, bmask, amask, format) \
259         check_dds_pixel_format_(__LINE__, flags, fourcc, bpp, rmask, gmask, bmask, amask, format)
260 static void check_dds_pixel_format_(unsigned int line,
261                                     DWORD flags, DWORD fourcc, DWORD bpp,
262                                     DWORD rmask, DWORD gmask, DWORD bmask, DWORD amask,
263                                     D3DFORMAT expected_format)
264 {
265     HRESULT hr;
266     D3DXIMAGE_INFO info;
267     struct
268     {
269         DWORD magic;
270         struct dds_header header;
271         BYTE data[256];
272     } dds;
273 
274     dds.magic = MAKEFOURCC('D','D','S',' ');
275     fill_dds_header(&dds.header);
276     dds.header.pixel_format.flags = flags;
277     dds.header.pixel_format.fourcc = fourcc;
278     dds.header.pixel_format.bpp = bpp;
279     dds.header.pixel_format.rmask = rmask;
280     dds.header.pixel_format.gmask = gmask;
281     dds.header.pixel_format.bmask = bmask;
282     dds.header.pixel_format.amask = amask;
283     memset(dds.data, 0, sizeof(dds.data));
284 
285     hr = D3DXGetImageInfoFromFileInMemory(&dds, sizeof(dds), &info);
286     ok_(__FILE__, line)(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x for pixel format %#x, expected %#x\n",
287             hr, expected_format, D3D_OK);
288     if (SUCCEEDED(hr))
289     {
290         ok_(__FILE__, line)(info.Format == expected_format, "D3DXGetImageInfoFromFileInMemory returned format %#x, expected %#x\n",
291                 info.Format, expected_format);
292     }
293 }
294 
295 static void test_dds_header_handling(void)
296 {
297     int i;
298     HRESULT hr;
299     D3DXIMAGE_INFO info;
300     struct
301     {
302         DWORD magic;
303         struct dds_header header;
304         BYTE data[4096 * 1024];
305     } *dds;
306 
307     struct
308     {
309         struct dds_pixel_format pixel_format;
310         DWORD flags;
311         DWORD width;
312         DWORD height;
313         DWORD pitch;
314         DWORD miplevels;
315         DWORD pixel_data_size;
316         struct
317         {
318             HRESULT hr;
319             UINT miplevels;
320         }
321         expected;
322     } tests[] = {
323         /* pitch is ignored */
324         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, 0, 4, 4, 0, 0,
325           63 /* pixel data size */, { D3DXERR_INVALIDDATA, 0 } },
326         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 0 /* pitch */, 0,
327           64, { D3D_OK, 1 } },
328         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 1 /* pitch */, 0,
329           64, { D3D_OK, 1 } },
330         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 2 /* pitch */, 0,
331           64, { D3D_OK, 1 } },
332         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 3 /* pitch */, 0,
333           64, { D3D_OK, 1 } },
334         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 4 /* pitch */, 0,
335           64, { D3D_OK, 1 } },
336         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 16 /* pitch */, 0,
337           64, { D3D_OK, 1 } },
338         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 1024 /* pitch */, 0,
339           64, { D3D_OK, 1 } },
340         { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, -1 /* pitch */, 0,
341           64, { D3D_OK, 1 } },
342         /* linear size is ignored */
343         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 4, 4, 0, 0,
344           7 /* pixel data size */, { D3DXERR_INVALIDDATA, 1 } },
345         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 0 /* linear size */, 0,
346           8, { D3D_OK, 1 } },
347         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 1 /* linear size */, 0,
348           8, { D3D_OK, 1 } },
349         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 2 /* linear size */, 0,
350           8, { D3D_OK, 1 } },
351         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 9 /* linear size */, 0,
352           8, { D3D_OK, 1 } },
353         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 16 /* linear size */, 0,
354           8, { D3D_OK, 1 } },
355         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, -1 /* linear size */, 0,
356           8, { D3D_OK, 1 } },
357         /* integer overflows */
358         { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x80000000, 0x80000000 /* 0x80000000 * 0x80000000 * 4 = 0 */, 0, 0,
359           64, { D3D_OK, 1 } },
360         { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x8000100, 0x800100 /* 0x8000100 * 0x800100 * 4 = 262144 */, 0, 0,
361           64, { D3DXERR_INVALIDDATA, 0 } },
362         { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x80000001, 0x80000001 /* 0x80000001 * 0x80000001 * 4 = 4 */, 0, 0,
363           4, { D3D_OK, 1 } },
364         { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x80000001, 0x80000001 /* 0x80000001 * 0x80000001 * 4 = 4 */, 0, 0,
365           3 /* pixel data size */, { D3DXERR_INVALIDDATA, 0 } },
366         /* file size is validated */
367         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 64, 0, 0, 49151, { D3DXERR_INVALIDDATA, 0 } },
368         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 64, 0, 0, 49152, { D3D_OK, 1 } },
369         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 65279, { D3DXERR_INVALIDDATA, 0 } },
370         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 65280, { D3D_OK, 4 } },
371         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 9, 65540, { D3DXERR_INVALIDDATA, 0 } },
372         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 9, 65541, { D3D_OK, 9 } },
373         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196607, { D3DXERR_INVALIDDATA, 0 } },
374         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196608, { D3D_OK, 1 } },
375         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196609, { D3D_OK, 1 } },
376         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 1, 196607, { D3DXERR_INVALIDDATA, 0 } },
377         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 1, 196608, { D3D_OK, 1 } },
378         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 196607, { D3DXERR_INVALIDDATA, 0 } },
379         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 196608, { D3D_OK, 1 } },
380         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 400000, { D3D_OK, 1 } },
381         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 262142, { D3DXERR_INVALIDDATA, 0 } },
382         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 262143, { D3D_OK, 9 } },
383         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 10, 262145, { D3DXERR_INVALIDDATA, 0 } },
384         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 10, 262146, { D3D_OK, 10 } },
385         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 262175, { D3DXERR_INVALIDDATA, 0 } },
386         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 262176, { D3D_OK, 20 } },
387         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 32767, { D3DXERR_INVALIDDATA, 0 } },
388         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 32768, { D3D_OK, 1 } },
389         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 32767, { D3DXERR_INVALIDDATA, 0 } },
390         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 32768, { D3D_OK, 1 } },
391         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 43703, { D3DXERR_INVALIDDATA, 0 } },
392         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 43704, { D3D_OK, 9 } },
393         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 43791, { D3DXERR_INVALIDDATA, 0 } },
394         { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 43792, { D3D_OK, 20 } },
395         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 65535, { D3DXERR_INVALIDDATA, 0 } },
396         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 65536, { D3D_OK, 1 } },
397         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 65535, { D3DXERR_INVALIDDATA, 0 } },
398         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 65536, { D3D_OK, 1 } },
399         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 87407, { D3DXERR_INVALIDDATA, 0 } },
400         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 87408, { D3D_OK, 9 } },
401         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 87583, { D3DXERR_INVALIDDATA, 0 } },
402         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 87584, { D3D_OK, 20 } },
403         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 21759, { D3DXERR_INVALIDDATA, 0 } },
404         { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 21760, { D3D_OK, 4 } },
405         /* DDS_MIPMAPCOUNT is ignored */
406         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 262146, { D3D_OK, 1 } },
407         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 2, 262146, { D3D_OK, 2 } },
408         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 9, 262146, { D3D_OK, 9 } },
409         { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 10, 262146, { D3D_OK, 10 } },
410     };
411 
412     dds = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dds));
413     if (!dds)
414     {
415         skip("Failed to allocate memory.\n");
416         return;
417     }
418 
419     for (i = 0; i < ARRAY_SIZE(tests); i++)
420     {
421         DWORD file_size = sizeof(dds->magic) + sizeof(dds->header) + tests[i].pixel_data_size;
422         assert(file_size <= sizeof(*dds));
423 
424         dds->magic = MAKEFOURCC('D','D','S',' ');
425         fill_dds_header(&dds->header);
426         dds->header.flags |= tests[i].flags;
427         dds->header.width = tests[i].width;
428         dds->header.height = tests[i].height;
429         dds->header.pitch_or_linear_size = tests[i].pitch;
430         dds->header.miplevels = tests[i].miplevels;
431         dds->header.pixel_format = tests[i].pixel_format;
432 
433         hr = D3DXGetImageInfoFromFileInMemory(dds, file_size, &info);
434         ok(hr == tests[i].expected.hr, "%d: D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n",
435                 i, hr, tests[i].expected.hr);
436         if (SUCCEEDED(hr))
437         {
438             ok(info.MipLevels == tests[i].expected.miplevels, "%d: Got MipLevels %u, expected %u\n",
439                     i, info.MipLevels, tests[i].expected.miplevels);
440         }
441     }
442 
443     HeapFree(GetProcessHeap(), 0, dds);
444 }
445 
446 static void test_D3DXGetImageInfo(void)
447 {
448     HRESULT hr;
449     D3DXIMAGE_INFO info;
450     BOOL testdummy_ok, testbitmap_ok;
451 
452     hr = create_file("testdummy.bmp", noimage, sizeof(noimage));  /* invalid image */
453     testdummy_ok = SUCCEEDED(hr);
454 
455     hr = create_file("testbitmap.bmp", bmp_1bpp, sizeof(bmp_1bpp));  /* valid image */
456     testbitmap_ok = SUCCEEDED(hr);
457 
458     /* D3DXGetImageInfoFromFile */
459     if(testbitmap_ok) {
460         hr = D3DXGetImageInfoFromFileA("testbitmap.bmp", &info);
461         ok(hr == D3D_OK, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3D_OK);
462 
463         hr = D3DXGetImageInfoFromFileA("testbitmap.bmp", NULL); /* valid image, second parameter is NULL */
464         ok(hr == D3D_OK, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3D_OK);
465     } else skip("Couldn't create \"testbitmap.bmp\"\n");
466 
467     if(testdummy_ok) {
468         hr = D3DXGetImageInfoFromFileA("testdummy.bmp", NULL); /* invalid image, second parameter is NULL */
469         ok(hr == D3D_OK, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3D_OK);
470 
471         hr = D3DXGetImageInfoFromFileA("testdummy.bmp", &info);
472         ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
473     } else skip("Couldn't create \"testdummy.bmp\"\n");
474 
475     hr = D3DXGetImageInfoFromFileA("filedoesnotexist.bmp", &info);
476     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
477 
478     hr = D3DXGetImageInfoFromFileA("filedoesnotexist.bmp", NULL);
479     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
480 
481     hr = D3DXGetImageInfoFromFileA("", &info);
482     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
483 
484     hr = D3DXGetImageInfoFromFileA(NULL, &info);
485     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
486 
487     hr = D3DXGetImageInfoFromFileA(NULL, NULL);
488     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
489 
490 
491     /* D3DXGetImageInfoFromResource */
492     hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDB_BITMAP_1x1), &info); /* RT_BITMAP */
493     ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK);
494 
495     hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDB_BITMAP_1x1), NULL);
496     ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK);
497 
498     hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), &info); /* RT_RCDATA */
499     ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK);
500 
501     hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDS_STRING), &info);
502     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
503 
504     hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDS_STRING), NULL);
505     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
506 
507     hr = D3DXGetImageInfoFromResourceA(NULL, "resourcedoesnotexist", &info);
508     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
509 
510     hr = D3DXGetImageInfoFromResourceA(NULL, "resourcedoesnotexist", NULL);
511     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
512 
513     hr = D3DXGetImageInfoFromResourceA(NULL, NULL, NULL);
514     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
515 
516 
517     /* D3DXGetImageInfoFromFileInMemory */
518     hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp), &info);
519     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
520 
521     hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp)+5, &info); /* too large size */
522     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
523 
524     hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp), NULL);
525     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
526 
527     hr = D3DXGetImageInfoFromFileInMemory(noimage, sizeof(noimage), NULL);
528     ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK);
529 
530     hr = D3DXGetImageInfoFromFileInMemory(noimage, sizeof(noimage), &info);
531     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
532 
533     todo_wine {
534         hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp)-1, &info);
535         ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
536     }
537 
538     hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp+1, sizeof(bmp_1bpp)-1, &info);
539     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
540 
541     hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, 0, &info);
542     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
543 
544     hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, 0, NULL);
545     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
546 
547     hr = D3DXGetImageInfoFromFileInMemory(noimage, 0, &info);
548     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
549 
550     hr = D3DXGetImageInfoFromFileInMemory(noimage, 0, NULL);
551     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
552 
553     hr = D3DXGetImageInfoFromFileInMemory(NULL, 0, &info);
554     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
555 
556     hr = D3DXGetImageInfoFromFileInMemory(NULL, 4, NULL);
557     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
558 
559     hr = D3DXGetImageInfoFromFileInMemory(NULL, 4, &info);
560     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
561 
562     hr = D3DXGetImageInfoFromFileInMemory(NULL, 0, NULL);
563     ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
564 
565     /* test BMP support */
566     hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp), &info);
567     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
568     ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
569     ok(info.Format == D3DFMT_P8, "Got format %u, expected %u\n", info.Format, D3DFMT_P8);
570     hr = D3DXGetImageInfoFromFileInMemory(bmp_2bpp, sizeof(bmp_2bpp), &info);
571     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
572     hr = D3DXGetImageInfoFromFileInMemory(bmp_4bpp, sizeof(bmp_4bpp), &info);
573     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
574     ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
575     ok(info.Format == D3DFMT_P8, "Got format %u, expected %u\n", info.Format, D3DFMT_P8);
576     hr = D3DXGetImageInfoFromFileInMemory(bmp_8bpp, sizeof(bmp_8bpp), &info);
577     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
578     ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
579     ok(info.Format == D3DFMT_P8, "Got format %u, expected %u\n", info.Format, D3DFMT_P8);
580     hr = D3DXGetImageInfoFromFileInMemory(bmp_32bpp_xrgb, sizeof(bmp_32bpp_xrgb), &info);
581     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
582     ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
583     ok(info.Format == D3DFMT_X8R8G8B8, "Got format %u, expected %u\n", info.Format, D3DFMT_X8R8G8B8);
584     hr = D3DXGetImageInfoFromFileInMemory(bmp_32bpp_argb, sizeof(bmp_32bpp_argb), &info);
585     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
586     ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
587     ok(info.Format == D3DFMT_A8R8G8B8, "Got format %u, expected %u\n", info.Format, D3DFMT_A8R8G8B8);
588 
589     /* Grayscale PNG */
590     hr = D3DXGetImageInfoFromFileInMemory(png_grayscale, sizeof(png_grayscale), &info);
591     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
592     ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
593     ok(info.Format == D3DFMT_L8, "Got format %u, expected %u\n", info.Format, D3DFMT_L8);
594 
595     /* test DDS support */
596     hr = D3DXGetImageInfoFromFileInMemory(dds_24bit, sizeof(dds_24bit), &info);
597     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
598     if (hr == D3D_OK) {
599         ok(info.Width == 2, "Got width %u, expected 2\n", info.Width);
600         ok(info.Height == 2, "Got height %u, expected 2\n", info.Height);
601         ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
602         ok(info.MipLevels == 2, "Got miplevels %u, expected 2\n", info.MipLevels);
603         ok(info.Format == D3DFMT_R8G8B8, "Got format %#x, expected %#x\n", info.Format, D3DFMT_R8G8B8);
604         ok(info.ResourceType == D3DRTYPE_TEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_TEXTURE);
605         ok(info.ImageFileFormat == D3DXIFF_DDS, "Got image file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS);
606     } else skip("Couldn't get image info from 24-bit DDS file in memory\n");
607 
608     hr = D3DXGetImageInfoFromFileInMemory(dds_16bit, sizeof(dds_16bit), &info);
609     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
610     if (hr == D3D_OK) {
611         ok(info.Width == 2, "Got width %u, expected 2\n", info.Width);
612         ok(info.Height == 2, "Got height %u, expected 2\n", info.Height);
613         ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
614         ok(info.MipLevels == 1, "Got miplevels %u, expected 1\n", info.MipLevels);
615         ok(info.Format == D3DFMT_X1R5G5B5, "Got format %#x, expected %#x\n", info.Format, D3DFMT_X1R5G5B5);
616         ok(info.ResourceType == D3DRTYPE_TEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_TEXTURE);
617         ok(info.ImageFileFormat == D3DXIFF_DDS, "Got image file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS);
618     } else skip("Couldn't get image info from 16-bit DDS file in memory\n");
619 
620     hr = D3DXGetImageInfoFromFileInMemory(dds_cube_map, sizeof(dds_cube_map), &info);
621     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
622     if (hr == D3D_OK) {
623         ok(info.Width == 4, "Got width %u, expected 4\n", info.Width);
624         ok(info.Height == 4, "Got height %u, expected 4\n", info.Height);
625         ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth);
626         ok(info.MipLevels == 1, "Got miplevels %u, expected 1\n", info.MipLevels);
627         ok(info.Format == D3DFMT_DXT5, "Got format %#x, expected %#x\n", info.Format, D3DFMT_DXT5);
628         ok(info.ResourceType == D3DRTYPE_CUBETEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_CUBETEXTURE);
629         ok(info.ImageFileFormat == D3DXIFF_DDS, "Got image file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS);
630     } else skip("Couldn't get image info from cube map in memory\n");
631 
632     hr = D3DXGetImageInfoFromFileInMemory(dds_volume_map, sizeof(dds_volume_map), &info);
633     ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
634     if (hr == D3D_OK) {
635         ok(info.Width == 4, "Got width %u, expected 4\n", info.Width);
636         ok(info.Height == 4, "Got height %u, expected 4\n", info.Height);
637         ok(info.Depth == 2, "Got depth %u, expected 2\n", info.Depth);
638         ok(info.MipLevels == 3, "Got miplevels %u, expected 3\n", info.MipLevels);
639         ok(info.Format == D3DFMT_DXT3, "Got format %#x, expected %#x\n", info.Format, D3DFMT_DXT3);
640         ok(info.ResourceType == D3DRTYPE_VOLUMETEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_VOLUMETEXTURE);
641         ok(info.ImageFileFormat == D3DXIFF_DDS, "Got image file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS);
642     } else skip("Couldn't get image info from volume map in memory\n");
643 
644     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0, D3DFMT_DXT1);
645     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT2, 0, 0, 0, 0, 0, D3DFMT_DXT2);
646     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT3, 0, 0, 0, 0, 0, D3DFMT_DXT3);
647     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0, D3DFMT_DXT4);
648     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT5, 0, 0, 0, 0, 0, D3DFMT_DXT5);
649     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_R8G8_B8G8, 0, 0, 0, 0, 0, D3DFMT_R8G8_B8G8);
650     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_G8R8_G8B8, 0, 0, 0, 0, 0, D3DFMT_G8R8_G8B8);
651     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_UYVY, 0, 0, 0, 0, 0, D3DFMT_UYVY);
652     check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_YUY2, 0, 0, 0, 0, 0, D3DFMT_YUY2);
653     check_dds_pixel_format(DDS_PF_RGB, 0, 16, 0xf800, 0x07e0, 0x001f, 0, D3DFMT_R5G6B5);
654     check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x8000, D3DFMT_A1R5G5B5);
655     check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x0f00, 0x00f0, 0x000f, 0xf000, D3DFMT_A4R4G4B4);
656     check_dds_pixel_format(DDS_PF_RGB, 0, 8, 0xe0, 0x1c, 0x03, 0, D3DFMT_R3G3B2);
657     check_dds_pixel_format(DDS_PF_ALPHA_ONLY, 0, 8, 0, 0, 0, 0xff, D3DFMT_A8);
658     check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x00e0, 0x001c, 0x0003, 0xff00, D3DFMT_A8R3G3B2);
659     check_dds_pixel_format(DDS_PF_RGB, 0, 16, 0xf00, 0x0f0, 0x00f, 0, D3DFMT_X4R4G4B4);
660     check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000, D3DFMT_A2B10G10R10);
661     check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000, D3DFMT_A2R10G10B10);
662     check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, D3DFMT_A8R8G8B8);
663     check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, D3DFMT_A8B8G8R8);
664     check_dds_pixel_format(DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0, D3DFMT_X8R8G8B8);
665     check_dds_pixel_format(DDS_PF_RGB, 0, 32, 0x0000ff, 0x00ff00, 0xff0000, 0, D3DFMT_X8B8G8R8);
666     check_dds_pixel_format(DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0, D3DFMT_R8G8B8);
667     check_dds_pixel_format(DDS_PF_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0, 0, D3DFMT_G16R16);
668     check_dds_pixel_format(DDS_PF_LUMINANCE, 0, 8, 0xff, 0, 0, 0, D3DFMT_L8);
669     check_dds_pixel_format(DDS_PF_LUMINANCE, 0, 16, 0xffff, 0, 0, 0, D3DFMT_L16);
670     check_dds_pixel_format(DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 16, 0x00ff, 0, 0, 0xff00, D3DFMT_A8L8);
671     check_dds_pixel_format(DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 8, 0x0f, 0, 0, 0xf0, D3DFMT_A4L4);
672     check_dds_pixel_format(DDS_PF_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0, 0, D3DFMT_V8U8);
673     check_dds_pixel_format(DDS_PF_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0, D3DFMT_V16U16);
674 
675     test_dds_header_handling();
676 
677     hr = D3DXGetImageInfoFromFileInMemory(dds_16bit, sizeof(dds_16bit) - 1, &info);
678     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
679 
680     hr = D3DXGetImageInfoFromFileInMemory(dds_24bit, sizeof(dds_24bit) - 1, &info);
681     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
682 
683     hr = D3DXGetImageInfoFromFileInMemory(dds_cube_map, sizeof(dds_cube_map) - 1, &info);
684     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
685 
686     hr = D3DXGetImageInfoFromFileInMemory(dds_volume_map, sizeof(dds_volume_map) - 1, &info);
687     ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
688 
689 
690     /* cleanup */
691     if(testdummy_ok) DeleteFileA("testdummy.bmp");
692     if(testbitmap_ok) DeleteFileA("testbitmap.bmp");
693 }
694 
695 #define check_pixel_2bpp(lockrect, x, y, color) _check_pixel_2bpp(__LINE__, lockrect, x, y, color)
696 static inline void _check_pixel_2bpp(unsigned int line, const D3DLOCKED_RECT *lockrect, int x, int y, WORD expected_color)
697 {
698     WORD color = ((WORD*)lockrect->pBits)[x + y * lockrect->Pitch / 2];
699     ok_(__FILE__, line)(color == expected_color, "Got color 0x%04x, expected 0x%04x\n", color, expected_color);
700 }
701 
702 #define check_pixel_4bpp(lockrect, x, y, color) _check_pixel_4bpp(__LINE__, lockrect, x, y, color)
703 static inline void _check_pixel_4bpp(unsigned int line, const D3DLOCKED_RECT *lockrect, int x, int y, DWORD expected_color)
704 {
705    DWORD color = ((DWORD*)lockrect->pBits)[x + y * lockrect->Pitch / 4];
706    ok_(__FILE__, line)(color == expected_color, "Got color 0x%08x, expected 0x%08x\n", color, expected_color);
707 }
708 
709 static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
710 {
711     HRESULT hr;
712     BOOL testdummy_ok, testbitmap_ok;
713     IDirect3DTexture9 *tex;
714     IDirect3DSurface9 *surf, *newsurf;
715     RECT rect, destrect;
716     D3DLOCKED_RECT lockrect;
717     const WORD pixdata_a8r3g3b2[] = { 0x57df, 0x98fc, 0xacdd, 0xc891 };
718     const WORD pixdata_a1r5g5b5[] = { 0x46b5, 0x99c8, 0x06a2, 0x9431 };
719     const WORD pixdata_r5g6b5[] = { 0x9ef6, 0x658d, 0x0aee, 0x42ee };
720     const WORD pixdata_a8l8[] = { 0xff00, 0x00ff, 0xff30, 0x7f7f };
721     const DWORD pixdata_g16r16[] = { 0x07d23fbe, 0xdc7f44a4, 0xe4d8976b, 0x9a84fe89 };
722     const DWORD pixdata_a8b8g8r8[] = { 0xc3394cf0, 0x235ae892, 0x09b197fd, 0x8dc32bf6 };
723     const DWORD pixdata_a2r10g10b10[] = { 0x57395aff, 0x5b7668fd, 0xb0d856b5, 0xff2c61d6 };
724 
725     hr = create_file("testdummy.bmp", noimage, sizeof(noimage));  /* invalid image */
726     testdummy_ok = SUCCEEDED(hr);
727 
728     hr = create_file("testbitmap.bmp", bmp_1bpp, sizeof(bmp_1bpp));  /* valid image */
729     testbitmap_ok = SUCCEEDED(hr);
730 
731     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf, NULL);
732     if(FAILED(hr)) {
733         skip("Failed to create a surface (%#x)\n", hr);
734         if(testdummy_ok) DeleteFileA("testdummy.bmp");
735         if(testbitmap_ok) DeleteFileA("testbitmap.bmp");
736         return;
737     }
738 
739     /* D3DXLoadSurfaceFromFile */
740     if(testbitmap_ok) {
741         hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "testbitmap.bmp", NULL, D3DX_DEFAULT, 0, NULL);
742         ok(hr == D3D_OK, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3D_OK);
743 
744         hr = D3DXLoadSurfaceFromFileA(NULL, NULL, NULL, "testbitmap.bmp", NULL, D3DX_DEFAULT, 0, NULL);
745         ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
746     } else skip("Couldn't create \"testbitmap.bmp\"\n");
747 
748     if(testdummy_ok) {
749         hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "testdummy.bmp", NULL, D3DX_DEFAULT, 0, NULL);
750         ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
751     } else skip("Couldn't create \"testdummy.bmp\"\n");
752 
753     hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, NULL, NULL, D3DX_DEFAULT, 0, NULL);
754     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
755 
756     hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "", NULL, D3DX_DEFAULT, 0, NULL);
757     ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
758 
759 
760     /* D3DXLoadSurfaceFromResource */
761     hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL,
762             MAKEINTRESOURCEA(IDB_BITMAP_1x1), NULL, D3DX_DEFAULT, 0, NULL);
763     ok(hr == D3D_OK, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3D_OK);
764 
765     hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL,
766             MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), NULL, D3DX_DEFAULT, 0, NULL);
767     ok(hr == D3D_OK, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3D_OK);
768 
769     hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, NULL, NULL, D3DX_DEFAULT, 0, NULL);
770     ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
771 
772     hr = D3DXLoadSurfaceFromResourceA(NULL, NULL, NULL, NULL,
773             MAKEINTRESOURCEA(IDB_BITMAP_1x1), NULL, D3DX_DEFAULT, 0, NULL);
774     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
775 
776     hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL,
777             MAKEINTRESOURCEA(IDS_STRING), NULL, D3DX_DEFAULT, 0, NULL);
778     ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
779 
780 
781     /* D3DXLoadSurfaceFromFileInMemory */
782     hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp_1bpp, sizeof(bmp_1bpp), NULL, D3DX_DEFAULT, 0, NULL);
783     ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
784 
785     hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, noimage, sizeof(noimage), NULL, D3DX_DEFAULT, 0, NULL);
786     ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
787 
788     hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp_1bpp, 0, NULL, D3DX_DEFAULT, 0, NULL);
789     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
790 
791     hr = D3DXLoadSurfaceFromFileInMemory(NULL, NULL, NULL, bmp_1bpp, sizeof(bmp_1bpp), NULL, D3DX_DEFAULT, 0, NULL);
792     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
793 
794     hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, NULL, 8, NULL, D3DX_DEFAULT, 0, NULL);
795     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
796 
797     hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, NULL, 0, NULL, D3DX_DEFAULT, 0, NULL);
798     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
799 
800     hr = D3DXLoadSurfaceFromFileInMemory(NULL, NULL, NULL, NULL, 0, NULL, D3DX_DEFAULT, 0, NULL);
801     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
802 
803 
804     /* D3DXLoadSurfaceFromMemory */
805     SetRect(&rect, 0, 0, 2, 2);
806 
807     hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0);
808     ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
809 
810     hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, 0, NULL, &rect, D3DX_FILTER_NONE, 0);
811     ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
812 
813     hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, NULL, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_DEFAULT, 0);
814     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
815 
816     hr = D3DXLoadSurfaceFromMemory(NULL, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_DEFAULT, 0);
817     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
818 
819     hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, NULL, D3DX_DEFAULT, 0);
820     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
821 
822     hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_UNKNOWN, sizeof(pixdata), NULL, &rect, D3DX_DEFAULT, 0);
823     ok(hr == E_FAIL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, E_FAIL);
824 
825     SetRect(&destrect, -1, -1, 1, 1); /* destination rect is partially outside texture boundaries */
826     hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0);
827     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
828 
829     SetRect(&destrect, 255, 255, 257, 257); /* destination rect is partially outside texture boundaries */
830     hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0);
831     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
832 
833     SetRect(&destrect, 1, 1, 0, 0); /* left > right, top > bottom */
834     hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0);
835     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
836 
837     SetRect(&destrect, 1, 2, 1, 2); /* left = right, top = bottom */
838     hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0);
839     /* fails when debug version of d3d9 is used */
840     ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
841 
842     SetRect(&destrect, 257, 257, 257, 257); /* left = right, top = bottom, but invalid values */
843     hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0);
844     ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
845 
846 
847     /* D3DXLoadSurfaceFromSurface */
848     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &newsurf, NULL);
849     if(SUCCEEDED(hr)) {
850         hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0);
851         ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3D_OK);
852 
853         hr = D3DXLoadSurfaceFromSurface(NULL, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0);
854         ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
855 
856         hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, NULL, NULL, NULL, D3DX_DEFAULT, 0);
857         ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
858 
859         check_release((IUnknown*)newsurf, 0);
860     } else skip("Failed to create a second surface\n");
861 
862     hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL);
863     if (SUCCEEDED(hr))
864     {
865         IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
866 
867         hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0);
868         ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3D_OK);
869 
870         IDirect3DSurface9_Release(newsurf);
871         IDirect3DTexture9_Release(tex);
872     } else skip("Failed to create texture\n");
873 
874     /* non-lockable render target */
875     hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &newsurf, NULL);
876     ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
877     hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
878     ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
879     IDirect3DSurface9_Release(newsurf);
880 
881     /* non-lockable multisampled render target */
882     hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &newsurf, NULL);
883     if (SUCCEEDED(hr))
884     {
885        hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
886        ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
887 
888        IDirect3DSurface9_Release(newsurf);
889     }
890     else
891     {
892         skip("Failed to create multisampled render target.\n");
893     }
894 
895     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &newsurf);
896     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget returned %#x, expected %#x.\n", hr, D3D_OK);
897 
898     hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
899     ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK);
900     hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
901     ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK);
902     hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0xff000000);
903     ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK);
904     hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_TRIANGLE | D3DX_FILTER_MIRROR, 0);
905     ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK);
906     hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_LINEAR, 0);
907     ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK);
908 
909     IDirect3DSurface9_Release(newsurf);
910 
911     check_release((IUnknown*)surf, 0);
912 
913 
914     /* test color conversion */
915     /* A8R8G8B8 */
916     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf, NULL);
917     if(FAILED(hr)) skip("Failed to create a surface (%#x)\n", hr);
918     else {
919         PALETTEENTRY palette;
920 
921         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2, D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
922         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
923         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
924         check_pixel_4bpp(&lockrect, 0, 0, 0x57dbffff);
925         check_pixel_4bpp(&lockrect, 1, 0, 0x98ffff00);
926         check_pixel_4bpp(&lockrect, 0, 1, 0xacdbff55);
927         check_pixel_4bpp(&lockrect, 1, 1, 0xc8929255);
928         IDirect3DSurface9_UnlockRect(surf);
929 
930         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5, D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
931         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
932         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
933         check_pixel_4bpp(&lockrect, 0, 0, 0x008cadad);
934         check_pixel_4bpp(&lockrect, 1, 0, 0xff317342);
935         check_pixel_4bpp(&lockrect, 0, 1, 0x0008ad10);
936         check_pixel_4bpp(&lockrect, 1, 1, 0xff29088c);
937         IDirect3DSurface9_UnlockRect(surf);
938 
939         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5, D3DFMT_R5G6B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
940         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
941         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
942         check_pixel_4bpp(&lockrect, 0, 0, 0xff9cdfb5);
943         check_pixel_4bpp(&lockrect, 1, 0, 0xff63b26b);
944         check_pixel_4bpp(&lockrect, 0, 1, 0xff085d73);
945         check_pixel_4bpp(&lockrect, 1, 1, 0xff425d73);
946         IDirect3DSurface9_UnlockRect(surf);
947 
948         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16, D3DFMT_G16R16, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
949         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
950         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
951         todo_wine {
952             check_pixel_4bpp(&lockrect, 0, 0, 0xff3f08ff);
953         }
954         check_pixel_4bpp(&lockrect, 1, 0, 0xff44dcff);
955         check_pixel_4bpp(&lockrect, 0, 1, 0xff97e4ff);
956         check_pixel_4bpp(&lockrect, 1, 1, 0xfffe9aff);
957         IDirect3DSurface9_UnlockRect(surf);
958 
959         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
960         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
961         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
962         check_pixel_4bpp(&lockrect, 0, 0, 0xc3f04c39);
963         check_pixel_4bpp(&lockrect, 1, 0, 0x2392e85a);
964         check_pixel_4bpp(&lockrect, 0, 1, 0x09fd97b1);
965         check_pixel_4bpp(&lockrect, 1, 1, 0x8df62bc3);
966         IDirect3DSurface9_UnlockRect(surf);
967 
968         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10, D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
969         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
970         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
971         check_pixel_4bpp(&lockrect, 0, 0, 0x555c95bf);
972         check_pixel_4bpp(&lockrect, 1, 0, 0x556d663f);
973         check_pixel_4bpp(&lockrect, 0, 1, 0xaac385ad);
974         todo_wine {
975             check_pixel_4bpp(&lockrect, 1, 1, 0xfffcc575);
976         }
977         IDirect3DSurface9_UnlockRect(surf);
978 
979         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8l8,
980                 D3DFMT_A8L8, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
981         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
982         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
983         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
984         check_pixel_4bpp(&lockrect, 0, 0, 0xff000000);
985         check_pixel_4bpp(&lockrect, 1, 0, 0x00ffffff);
986         check_pixel_4bpp(&lockrect, 0, 1, 0xff303030);
987         check_pixel_4bpp(&lockrect, 1, 1, 0x7f7f7f7f);
988         hr = IDirect3DSurface9_UnlockRect(surf);
989         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
990 
991         /* Test D3DXLoadSurfaceFromMemory with indexed color image */
992         if (0)
993         {
994         /* Crashes on Nvidia Win10. */
995         palette.peRed   = bmp_1bpp[56];
996         palette.peGreen = bmp_1bpp[55];
997         palette.peBlue  = bmp_1bpp[54];
998         palette.peFlags = bmp_1bpp[57]; /* peFlags is the alpha component in DX8 and higher */
999         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, &bmp_1bpp[62],
1000                 D3DFMT_P8, 1, (const PALETTEENTRY *)&palette, &rect, D3DX_FILTER_NONE, 0);
1001         ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
1002         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1003         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x\n", hr);
1004         ok(*(DWORD*)lockrect.pBits == 0x80f3f2f1, "Pixel color mismatch: got %#x, expected 0x80f3f2f1\n", *(DWORD*)lockrect.pBits);
1005         hr = IDirect3DSurface9_UnlockRect(surf);
1006         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x\n", hr);
1007         }
1008 
1009         /* Test D3DXLoadSurfaceFromFileInMemory with indexed color image (alpha is not taken into account for bmp file) */
1010         hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp_1bpp, sizeof(bmp_1bpp), NULL, D3DX_FILTER_NONE, 0, NULL);
1011         ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
1012         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1013         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x\n", hr);
1014         ok(*(DWORD*)lockrect.pBits == 0xfff3f2f1, "Pixel color mismatch: got %#x, expected 0xfff3f2f1\n", *(DWORD*)lockrect.pBits);
1015         hr = IDirect3DSurface9_UnlockRect(surf);
1016         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x\n", hr);
1017 
1018         check_release((IUnknown*)surf, 0);
1019     }
1020 
1021     /* A1R5G5B5 */
1022     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_A1R5G5B5, D3DPOOL_DEFAULT, &surf, NULL);
1023     if(FAILED(hr)) skip("Failed to create a surface (%#x)\n", hr);
1024     else {
1025         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2, D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
1026         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
1027         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1028         check_pixel_2bpp(&lockrect, 0, 0, 0x6fff);
1029         check_pixel_2bpp(&lockrect, 1, 0, 0xffe0);
1030         check_pixel_2bpp(&lockrect, 0, 1, 0xefea);
1031         check_pixel_2bpp(&lockrect, 1, 1, 0xca4a);
1032         IDirect3DSurface9_UnlockRect(surf);
1033 
1034         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5, D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
1035         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
1036         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1037         check_pixel_2bpp(&lockrect, 0, 0, 0x46b5);
1038         check_pixel_2bpp(&lockrect, 1, 0, 0x99c8);
1039         check_pixel_2bpp(&lockrect, 0, 1, 0x06a2);
1040         check_pixel_2bpp(&lockrect, 1, 1, 0x9431);
1041         IDirect3DSurface9_UnlockRect(surf);
1042 
1043         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5, D3DFMT_R5G6B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
1044         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
1045         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1046         check_pixel_2bpp(&lockrect, 0, 0, 0xcf76);
1047         check_pixel_2bpp(&lockrect, 1, 0, 0xb2cd);
1048         check_pixel_2bpp(&lockrect, 0, 1, 0x856e);
1049         check_pixel_2bpp(&lockrect, 1, 1, 0xa16e);
1050         IDirect3DSurface9_UnlockRect(surf);
1051 
1052         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16, D3DFMT_G16R16, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
1053         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
1054         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1055         todo_wine {
1056             check_pixel_2bpp(&lockrect, 0, 0, 0xa03f);
1057         }
1058         check_pixel_2bpp(&lockrect, 1, 0, 0xa37f);
1059         check_pixel_2bpp(&lockrect, 0, 1, 0xcb9f);
1060         check_pixel_2bpp(&lockrect, 1, 1, 0xfe7f);
1061         IDirect3DSurface9_UnlockRect(surf);
1062 
1063         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
1064         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
1065         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1066         todo_wine {
1067             check_pixel_2bpp(&lockrect, 0, 0, 0xf527);
1068             check_pixel_2bpp(&lockrect, 1, 0, 0x4b8b);
1069         }
1070         check_pixel_2bpp(&lockrect, 0, 1, 0x7e56);
1071         check_pixel_2bpp(&lockrect, 1, 1, 0xf8b8);
1072         IDirect3DSurface9_UnlockRect(surf);
1073 
1074         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10, D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
1075         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
1076         IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1077         check_pixel_2bpp(&lockrect, 0, 0, 0x2e57);
1078         todo_wine {
1079             check_pixel_2bpp(&lockrect, 1, 0, 0x3588);
1080         }
1081         check_pixel_2bpp(&lockrect, 0, 1, 0xe215);
1082         check_pixel_2bpp(&lockrect, 1, 1, 0xff0e);
1083         IDirect3DSurface9_UnlockRect(surf);
1084 
1085         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8l8,
1086                 D3DFMT_A8L8, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
1087         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
1088         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1089         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
1090         check_pixel_2bpp(&lockrect, 0, 0, 0x8000);
1091         check_pixel_2bpp(&lockrect, 1, 0, 0x7fff);
1092         check_pixel_2bpp(&lockrect, 0, 1, 0x98c6);
1093         check_pixel_2bpp(&lockrect, 1, 1, 0x3def);
1094         hr = IDirect3DSurface9_UnlockRect(surf);
1095         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
1096 
1097         check_release((IUnknown*)surf, 0);
1098     }
1099 
1100     /* A8L8 */
1101     hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8L8, D3DPOOL_MANAGED, &tex, NULL);
1102     if (FAILED(hr))
1103         skip("Failed to create A8L8 texture, hr %#x.\n", hr);
1104     else
1105     {
1106         hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surf);
1107         ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
1108 
1109         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2,
1110                 D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
1111         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
1112         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1113         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
1114         check_pixel_2bpp(&lockrect, 0, 0, 0x57f7);
1115         check_pixel_2bpp(&lockrect, 1, 0, 0x98ed);
1116         check_pixel_2bpp(&lockrect, 0, 1, 0xaceb);
1117         check_pixel_2bpp(&lockrect, 1, 1, 0xc88d);
1118         hr = IDirect3DSurface9_UnlockRect(surf);
1119         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
1120 
1121         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5,
1122                 D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
1123         ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
1124         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1125         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
1126         check_pixel_2bpp(&lockrect, 0, 0, 0x00a6);
1127         check_pixel_2bpp(&lockrect, 1, 0, 0xff62);
1128         check_pixel_2bpp(&lockrect, 0, 1, 0x007f);
1129         check_pixel_2bpp(&lockrect, 1, 1, 0xff19);
1130         hr = IDirect3DSurface9_UnlockRect(surf);
1131         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
1132 
1133         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5,
1134                 D3DFMT_R5G6B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
1135         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
1136         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1137         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
1138         check_pixel_2bpp(&lockrect, 0, 0, 0xffce);
1139         check_pixel_2bpp(&lockrect, 1, 0, 0xff9c);
1140         check_pixel_2bpp(&lockrect, 0, 1, 0xff4d);
1141         check_pixel_2bpp(&lockrect, 1, 1, 0xff59);
1142         hr = IDirect3DSurface9_UnlockRect(surf);
1143         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
1144 
1145         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16,
1146                 D3DFMT_G16R16, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
1147         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
1148         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1149         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
1150         check_pixel_2bpp(&lockrect, 0, 0, 0xff25);
1151         check_pixel_2bpp(&lockrect, 1, 0, 0xffbe);
1152         check_pixel_2bpp(&lockrect, 0, 1, 0xffd6);
1153         check_pixel_2bpp(&lockrect, 1, 1, 0xffb6);
1154         hr = IDirect3DSurface9_UnlockRect(surf);
1155         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
1156 
1157         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8,
1158                 D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
1159         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
1160         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1161         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
1162         check_pixel_2bpp(&lockrect, 0, 0, 0xc36d);
1163         check_pixel_2bpp(&lockrect, 1, 0, 0x23cb);
1164         check_pixel_2bpp(&lockrect, 0, 1, 0x09af);
1165         check_pixel_2bpp(&lockrect, 1, 1, 0x8d61);
1166         hr = IDirect3DSurface9_UnlockRect(surf);
1167         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
1168 
1169         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10,
1170                 D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0);
1171         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
1172         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1173         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
1174         check_pixel_2bpp(&lockrect, 0, 0, 0x558c);
1175         check_pixel_2bpp(&lockrect, 1, 0, 0x5565);
1176         check_pixel_2bpp(&lockrect, 0, 1, 0xaa95);
1177         check_pixel_2bpp(&lockrect, 1, 1, 0xffcb);
1178         hr = IDirect3DSurface9_UnlockRect(surf);
1179         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
1180 
1181         hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8l8,
1182                 D3DFMT_A8L8, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
1183         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
1184         hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
1185         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
1186         check_pixel_2bpp(&lockrect, 0, 0, 0xff00);
1187         check_pixel_2bpp(&lockrect, 1, 0, 0x00ff);
1188         check_pixel_2bpp(&lockrect, 0, 1, 0xff30);
1189         check_pixel_2bpp(&lockrect, 1, 1, 0x7f7f);
1190         hr = IDirect3DSurface9_UnlockRect(surf);
1191         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
1192 
1193         check_release((IUnknown*)surf, 1);
1194         check_release((IUnknown*)tex, 0);
1195     }
1196 
1197     /* DXT1, DXT2, DXT3, DXT4, DXT5 */
1198     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL);
1199     if (FAILED(hr))
1200         skip("Failed to create R8G8B8 surface, hr %#x.\n", hr);
1201     else
1202     {
1203         hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, dds_24bit, sizeof(dds_24bit), NULL, D3DX_FILTER_NONE, 0, NULL);
1204         ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr);
1205 
1206         hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT2, D3DPOOL_SYSTEMMEM, &tex, NULL);
1207         if (FAILED(hr))
1208             skip("Failed to create DXT2 texture, hr %#x.\n", hr);
1209         else
1210         {
1211             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
1212             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
1213             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
1214             todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT2 format.\n");
1215             check_release((IUnknown*)newsurf, 1);
1216             check_release((IUnknown*)tex, 0);
1217         }
1218 
1219         hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT3, D3DPOOL_SYSTEMMEM, &tex, NULL);
1220         if (FAILED(hr))
1221             skip("Failed to create DXT3 texture, hr %#x.\n", hr);
1222         else
1223         {
1224             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
1225             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
1226             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
1227             ok(SUCCEEDED(hr), "Failed to convert pixels to DXT3 format.\n");
1228             check_release((IUnknown*)newsurf, 1);
1229             check_release((IUnknown*)tex, 0);
1230         }
1231 
1232         hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT4, D3DPOOL_SYSTEMMEM, &tex, NULL);
1233         if (FAILED(hr))
1234             skip("Failed to create DXT4 texture, hr %#x.\n", hr);
1235         else
1236         {
1237             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
1238             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
1239             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
1240             todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT4 format.\n");
1241             check_release((IUnknown*)newsurf, 1);
1242             check_release((IUnknown*)tex, 0);
1243         }
1244 
1245         hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT5, D3DPOOL_SYSTEMMEM, &tex, NULL);
1246         if (FAILED(hr))
1247             skip("Failed to create DXT5 texture, hr %#x.\n", hr);
1248         else
1249         {
1250             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
1251             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
1252             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
1253             ok(SUCCEEDED(hr), "Failed to convert pixels to DXT5 format.\n");
1254             check_release((IUnknown*)newsurf, 1);
1255             check_release((IUnknown*)tex, 0);
1256         }
1257 
1258         hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT1, D3DPOOL_SYSTEMMEM, &tex, NULL);
1259         if (FAILED(hr))
1260             skip("Failed to create DXT1 texture, hr %#x.\n", hr);
1261         else
1262         {
1263             hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf);
1264             ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr);
1265             hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0);
1266             ok(SUCCEEDED(hr), "Failed to convert pixels to DXT1 format.\n");
1267 
1268             hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
1269             ok(SUCCEEDED(hr), "Failed to convert pixels from DXT1 format.\n");
1270 
1271             check_release((IUnknown*)newsurf, 1);
1272             check_release((IUnknown*)tex, 0);
1273         }
1274 
1275         check_release((IUnknown*)surf, 0);
1276     }
1277 
1278     /* cleanup */
1279     if(testdummy_ok) DeleteFileA("testdummy.bmp");
1280     if(testbitmap_ok) DeleteFileA("testbitmap.bmp");
1281 }
1282 
1283 static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
1284 {
1285     static const struct
1286     {
1287         DWORD usage;
1288         D3DPOOL pool;
1289     }
1290     test_access_types[] =
1291     {
1292         {0,  D3DPOOL_MANAGED},
1293         {0,  D3DPOOL_DEFAULT},
1294         {D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT},
1295     };
1296 
1297     struct
1298     {
1299          DWORD magic;
1300          struct dds_header header;
1301          BYTE *data;
1302     } *dds;
1303     IDirect3DSurface9 *surface;
1304     IDirect3DTexture9 *texture;
1305     ID3DXBuffer *buffer;
1306     unsigned int i;
1307     HRESULT hr;
1308     RECT rect;
1309 
1310     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
1311     if (FAILED(hr)) {
1312        skip("Couldn't create surface\n");
1313        return;
1314     }
1315 
1316     SetRectEmpty(&rect);
1317     hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_BMP, surface, NULL, &rect);
1318     /* fails with the debug version of d3d9 */
1319     ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "D3DXSaveSurfaceToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
1320     if (SUCCEEDED(hr)) {
1321         DWORD size = ID3DXBuffer_GetBufferSize(buffer);
1322         ok(size > 0, "ID3DXBuffer_GetBufferSize returned %u, expected > 0\n", size);
1323         ID3DXBuffer_Release(buffer);
1324     }
1325 
1326     SetRectEmpty(&rect);
1327     hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect);
1328     todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1329     if (SUCCEEDED(hr))
1330     {
1331         dds = ID3DXBuffer_GetBufferPointer(buffer);
1332 
1333         ok(dds->magic == MAKEFOURCC('D','D','S',' '), "Got unexpected DDS signature %#x.\n", dds->magic);
1334         ok(dds->header.size == sizeof(dds->header), "Got unexpected DDS size %u.\n", dds->header.size);
1335         ok(!dds->header.height, "Got unexpected height %u.\n", dds->header.height);
1336         ok(!dds->header.width, "Got unexpected width %u.\n", dds->header.width);
1337         ok(!dds->header.depth, "Got unexpected depth %u.\n", dds->header.depth);
1338         ok(!dds->header.miplevels, "Got unexpected miplevels %u.\n", dds->header.miplevels);
1339         ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %u.\n", dds->header.pitch_or_linear_size);
1340         ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#x.\n", dds->header.caps);
1341         ok(dds->header.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT),
1342                 "Got unexpected flags %#x.\n", dds->header.flags);
1343         ID3DXBuffer_Release(buffer);
1344     }
1345 
1346     hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, NULL);
1347     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1348 
1349     dds = ID3DXBuffer_GetBufferPointer(buffer);
1350     ok(dds->magic == MAKEFOURCC('D','D','S',' '), "Got unexpected DDS signature %#x.\n", dds->magic);
1351     ok(dds->header.size == sizeof(dds->header), "Got unexpected DDS size %u.\n", dds->header.size);
1352     ok(dds->header.height == 4, "Got unexpected height %u.\n", dds->header.height);
1353     ok(dds->header.width == 4, "Got unexpected width %u.\n", dds->header.width);
1354     ok(!dds->header.depth, "Got unexpected depth %u.\n", dds->header.depth);
1355     ok(!dds->header.miplevels, "Got unexpected miplevels %u.\n", dds->header.miplevels);
1356     ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %u.\n", dds->header.pitch_or_linear_size);
1357     todo_wine ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#x.\n", dds->header.caps);
1358     ok(dds->header.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT),
1359             "Got unexpected flags %#x.\n", dds->header.flags);
1360     ID3DXBuffer_Release(buffer);
1361 
1362     IDirect3DSurface9_Release(surface);
1363 
1364     for (i = 0; i < ARRAY_SIZE(test_access_types); ++i)
1365     {
1366         hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 0, test_access_types[i].usage,
1367                 D3DFMT_A8R8G8B8, test_access_types[i].pool, &texture, NULL);
1368         ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i);
1369 
1370         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
1371         ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i);
1372 
1373         hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, NULL);
1374         ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i);
1375         ID3DXBuffer_Release(buffer);
1376 
1377         hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_BMP, surface, NULL, NULL);
1378         ok(hr == D3D_OK, "Unexpected hr %#x, i %u.\n", hr, i);
1379         ID3DXBuffer_Release(buffer);
1380 
1381         IDirect3DSurface9_Release(surface);
1382         IDirect3DTexture9_Release(texture);
1383     }
1384 }
1385 
1386 static void test_D3DXSaveSurfaceToFile(IDirect3DDevice9 *device)
1387 {
1388     HRESULT hr;
1389     IDirect3DSurface9 *surface;
1390     RECT rect;
1391     D3DLOCKED_RECT lock_rect;
1392     D3DXIMAGE_INFO image_info;
1393     const BYTE pixels[] = { 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
1394                             0x00, 0x00, 0xff, 0x00, 0x00, 0xff };
1395     DWORD pitch = sizeof(pixels) / 2;
1396 
1397     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
1398     if (FAILED(hr)) {
1399        skip("Couldn't create surface\n");
1400        return;
1401     }
1402 
1403     SetRect(&rect, 0, 0, 2, 2);
1404     hr = D3DXLoadSurfaceFromMemory(surface, NULL, NULL, pixels, D3DFMT_R8G8B8, pitch, NULL, &rect, D3DX_FILTER_NONE, 0);
1405     if (SUCCEEDED(hr)) {
1406         hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, NULL);
1407         ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK);
1408 
1409         hr = D3DXLoadSurfaceFromFileA(surface, NULL, NULL, "saved_surface.bmp", NULL, D3DX_FILTER_NONE, 0, &image_info);
1410         ok(hr == D3D_OK, "Couldn't load saved surface %#x\n", hr);
1411         if (FAILED(hr)) goto next_tests;
1412 
1413         ok(image_info.Width == 2, "Wrong width %u\n", image_info.Width);
1414         ok(image_info.Height == 2, "Wrong height %u\n", image_info.Height);
1415         ok(image_info.Format == D3DFMT_R8G8B8, "Wrong format %#x\n", image_info.Format);
1416         ok(image_info.ImageFileFormat == D3DXIFF_BMP, "Wrong file format %u\n", image_info.ImageFileFormat);
1417 
1418         hr = IDirect3DSurface9_LockRect(surface, &lock_rect, NULL, D3DLOCK_READONLY);
1419         ok(hr == D3D_OK, "Couldn't lock surface %#x\n", hr);
1420         if (FAILED(hr)) goto next_tests;
1421 
1422         ok(!memcmp(lock_rect.pBits, pixels, pitch), "Pixel data mismatch in first row\n");
1423         ok(!memcmp((BYTE *)lock_rect.pBits + lock_rect.Pitch, pixels + pitch, pitch), "Pixel data mismatch in second row\n");
1424 
1425         IDirect3DSurface9_UnlockRect(surface);
1426     } else skip("Couldn't fill surface\n");
1427 
1428 next_tests:
1429     hr = D3DXSaveSurfaceToFileA(NULL, D3DXIFF_BMP, surface, NULL, NULL);
1430     ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1431 
1432     /* PPM and TGA are supported, even though MSDN claims they aren't */
1433     todo_wine {
1434     hr = D3DXSaveSurfaceToFileA("saved_surface.ppm", D3DXIFF_PPM, surface, NULL, NULL);
1435     ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK);
1436     hr = D3DXSaveSurfaceToFileA("saved_surface.tga", D3DXIFF_TGA, surface, NULL, NULL);
1437     ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK);
1438     }
1439 
1440     hr = D3DXSaveSurfaceToFileA("saved_surface.dds", D3DXIFF_DDS, surface, NULL, NULL);
1441     ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK);
1442     if (SUCCEEDED(hr)) {
1443         hr = D3DXLoadSurfaceFromFileA(surface, NULL, NULL, "saved_surface.dds", NULL, D3DX_FILTER_NONE, 0, &image_info);
1444         ok(hr == D3D_OK, "Couldn't load saved surface %#x\n", hr);
1445 
1446         if (SUCCEEDED(hr)) {
1447             ok(image_info.Width == 2, "Wrong width %u\n", image_info.Width);
1448             ok(image_info.Format == D3DFMT_R8G8B8, "Wrong format %#x\n", image_info.Format);
1449             ok(image_info.ImageFileFormat == D3DXIFF_DDS, "Wrong file format %u\n", image_info.ImageFileFormat);
1450 
1451             hr = IDirect3DSurface9_LockRect(surface, &lock_rect, NULL, D3DLOCK_READONLY);
1452             ok(hr == D3D_OK, "Couldn't lock surface %#x\n", hr);
1453             if (SUCCEEDED(hr)) {
1454                 ok(!memcmp(lock_rect.pBits, pixels, pitch), "Pixel data mismatch in first row\n");
1455                 ok(!memcmp((BYTE *)lock_rect.pBits + lock_rect.Pitch, pixels + pitch, pitch), "Pixel data mismatch in second row\n");
1456                 IDirect3DSurface9_UnlockRect(surface);
1457             }
1458         }
1459     } else skip("Couldn't save surface\n");
1460 
1461     hr = D3DXSaveSurfaceToFileA("saved_surface", D3DXIFF_PFM + 1, surface, NULL, NULL);
1462     ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1463 
1464     SetRect(&rect, 0, 0, 4, 4);
1465     hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect);
1466     ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1467     SetRect(&rect, 2, 0, 1, 4);
1468     hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect);
1469     ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1470     SetRect(&rect, 0, 2, 4, 1);
1471     hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect);
1472     ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1473     SetRect(&rect, -1, -1, 2, 2);
1474     hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect);
1475     ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1476     SetRectEmpty(&rect);
1477     hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect);
1478     /* fails when debug version of d3d9 is used */
1479     ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK);
1480 
1481     DeleteFileA("saved_surface.bmp");
1482     DeleteFileA("saved_surface.ppm");
1483     DeleteFileA("saved_surface.tga");
1484     DeleteFileA("saved_surface.dds");
1485 
1486     IDirect3DSurface9_Release(surface);
1487 }
1488 
1489 START_TEST(surface)
1490 {
1491     HWND wnd;
1492     IDirect3D9 *d3d;
1493     IDirect3DDevice9 *device;
1494     D3DPRESENT_PARAMETERS d3dpp;
1495     HRESULT hr;
1496 
1497     if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
1498             640, 480, NULL, NULL, NULL, NULL)))
1499     {
1500         skip("Couldn't create application window\n");
1501         return;
1502     }
1503     d3d = Direct3DCreate9(D3D_SDK_VERSION);
1504     if (!d3d) {
1505         skip("Couldn't create IDirect3D9 object\n");
1506         DestroyWindow(wnd);
1507         return;
1508     }
1509 
1510     ZeroMemory(&d3dpp, sizeof(d3dpp));
1511     d3dpp.Windowed   = TRUE;
1512     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1513     hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
1514     if(FAILED(hr)) {
1515         skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1516         IDirect3D9_Release(d3d);
1517         DestroyWindow(wnd);
1518         return;
1519     }
1520 
1521     test_D3DXGetImageInfo();
1522     test_D3DXLoadSurface(device);
1523     test_D3DXSaveSurfaceToFileInMemory(device);
1524     test_D3DXSaveSurfaceToFile(device);
1525 
1526     check_release((IUnknown*)device, 0);
1527     check_release((IUnknown*)d3d, 0);
1528     DestroyWindow(wnd);
1529 }
1530