Release 1.4.1.
[wine] / dlls / ddraw / tests / dsurface.c
1 /*
2  * Unit tests for (a few) ddraw surface functions
3  *
4  * Copyright (C) 2005 Antoine Chavasse (a.chavasse@gmail.com)
5  * Copyright (C) 2005 Christian Costa
6  * Copyright 2005 Ivan Leo Puoti
7  * Copyright (C) 2007-2009, 2011 Stefan Dösinger for CodeWeavers
8  * Copyright (C) 2008 Alexander Dorofeyev
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #define COBJMACROS
25
26 #include "wine/test.h"
27 #include "wine/exception.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "unknwn.h"
31
32 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *, void **, REFIID, IUnknown *);
33
34 static LPDIRECTDRAW lpDD = NULL;
35 static DDCAPS ddcaps;
36
37 static BOOL CreateDirectDraw(void)
38 {
39     HRESULT rc;
40
41     rc = DirectDrawCreate(NULL, &lpDD, NULL);
42     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
43     if (!lpDD) {
44         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
45         return FALSE;
46     }
47
48     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
49     ok(rc==DD_OK,"SetCooperativeLevel returned: %x\n",rc);
50
51     return TRUE;
52 }
53
54
55 static void ReleaseDirectDraw(void)
56 {
57     if( lpDD != NULL )
58     {
59         IDirectDraw_Release(lpDD);
60         lpDD = NULL;
61     }
62 }
63
64 static void MipMapCreationTest(void)
65 {
66     LPDIRECTDRAWSURFACE lpDDSMipMapTest;
67     DDSURFACEDESC ddsd;
68     HRESULT rc;
69
70     /* First mipmap creation test: create a surface with DDSCAPS_COMPLEX,
71        DDSCAPS_MIPMAP, and DDSD_MIPMAPCOUNT. This create the number of
72         requested mipmap levels. */
73     ddsd.dwSize = sizeof(ddsd);
74     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
75     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
76     U2(ddsd).dwMipMapCount = 3;
77     ddsd.dwWidth = 128;
78     ddsd.dwHeight = 32;
79     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
80     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
81     if (FAILED(rc))
82     {
83         skip("failed to create surface\n");
84         return;
85     }
86
87     /* Check the number of created mipmaps */
88     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
89     ddsd.dwSize = sizeof(ddsd);
90     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
91     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
92     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
93         "GetSurfaceDesc returned no mipmapcount.\n");
94     ok(U2(ddsd).dwMipMapCount == 3, "Incorrect mipmap count: %d.\n",
95         U2(ddsd).dwMipMapCount);
96
97     /* Destroy the surface. */
98     IDirectDrawSurface_Release(lpDDSMipMapTest);
99
100
101     /* Second mipmap creation test: create a surface without a mipmap
102        count, with DDSCAPS_MIPMAP and without DDSCAPS_COMPLEX.
103        This creates a single mipmap level. */
104     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
105     ddsd.dwSize = sizeof(ddsd);
106     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
107     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
108     ddsd.dwWidth = 128;
109     ddsd.dwHeight = 32;
110     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
111     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
112     if (FAILED(rc))
113     {
114         skip("failed to create surface\n");
115         return;
116     }
117     /* Check the number of created mipmaps */
118     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
119     ddsd.dwSize = sizeof(ddsd);
120     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
121     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
122     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
123         "GetSurfaceDesc returned no mipmapcount.\n");
124     ok(U2(ddsd).dwMipMapCount == 1, "Incorrect mipmap count: %d.\n",
125         U2(ddsd).dwMipMapCount);
126
127     /* Destroy the surface. */
128     IDirectDrawSurface_Release(lpDDSMipMapTest);
129
130
131     /* Third mipmap creation test: create a surface with DDSCAPS_MIPMAP,
132         DDSCAPS_COMPLEX and without DDSD_MIPMAPCOUNT.
133        It's an undocumented features where a chain of mipmaps, starting from
134        he specified size and down to the smallest size, is automatically
135        created.
136        Anarchy Online needs this feature to work. */
137     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
138     ddsd.dwSize = sizeof(ddsd);
139     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
140     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
141     ddsd.dwWidth = 128;
142     ddsd.dwHeight = 32;
143     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
144     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
145     if (FAILED(rc))
146     {
147         skip("failed to create surface\n");
148         return;
149     }
150
151     /* Check the number of created mipmaps */
152     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
153     ddsd.dwSize = sizeof(ddsd);
154     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
155     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
156     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
157         "GetSurfaceDesc returned no mipmapcount.\n");
158     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %d.\n",
159         U2(ddsd).dwMipMapCount);
160
161     /* Destroy the surface. */
162     IDirectDrawSurface_Release(lpDDSMipMapTest);
163
164
165     /* Fourth mipmap creation test: same as above with a different texture
166        size.
167        The purpose is to verify that the number of generated mipmaps is
168        dependent on the smallest dimension. */
169     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
170     ddsd.dwSize = sizeof(ddsd);
171     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
172     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
173     ddsd.dwWidth = 32;
174     ddsd.dwHeight = 64;
175     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
176     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
177     if (FAILED(rc))
178     {
179         skip("failed to create surface\n");
180         return;
181     }
182
183     /* Check the number of created mipmaps */
184     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
185     ddsd.dwSize = sizeof(ddsd);
186     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
187     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
188     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
189         "GetSurfaceDesc returned no mipmapcount.\n");
190     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %d.\n",
191         U2(ddsd).dwMipMapCount);
192
193     /* Destroy the surface. */
194     IDirectDrawSurface_Release(lpDDSMipMapTest);
195
196
197     /* Fifth mipmap creation test: try to create a surface with
198        DDSCAPS_COMPLEX, DDSCAPS_MIPMAP, DDSD_MIPMAPCOUNT,
199        where dwMipMapCount = 0. This should fail. */
200
201     ddsd.dwSize = sizeof(ddsd);
202     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
203     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
204     U2(ddsd).dwMipMapCount = 0;
205     ddsd.dwWidth = 128;
206     ddsd.dwHeight = 32;
207     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
208     ok(rc==DDERR_INVALIDPARAMS,"CreateSurface returned: %x\n",rc);
209
210     /* Destroy the surface. */
211     if( rc == DD_OK )
212         IDirectDrawSurface_Release(lpDDSMipMapTest);
213
214 }
215
216 static void SrcColorKey32BlitTest(void)
217 {
218     LPDIRECTDRAWSURFACE lpSrc;
219     LPDIRECTDRAWSURFACE lpDst;
220     DDSURFACEDESC ddsd, ddsd2, ddsd3;
221     DDCOLORKEY DDColorKey;
222     LPDWORD lpData;
223     HRESULT rc;
224     DDBLTFX fx;
225
226     ddsd2.dwSize = sizeof(ddsd2);
227     ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat);
228
229     ddsd.dwSize = sizeof(ddsd);
230     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
231     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
232     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
233     ddsd.dwWidth = 800;
234     ddsd.dwHeight = 600;
235     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
236     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
237     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
238     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
239     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
240     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
241     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
242     if (FAILED(rc))
243     {
244         skip("failed to create surface\n");
245         return;
246     }
247
248     ddsd.dwFlags |= DDSD_CKSRCBLT;
249     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0xFF00FF;
250     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0xFF00FF;
251     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
252     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
253     if (FAILED(rc))
254     {
255         skip("failed to create surface\n");
256         return;
257     }
258
259     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
260     ok(rc==DD_OK,"Lock returned: %x\n",rc);
261     lpData = ddsd2.lpSurface;
262     lpData[0] = 0xCCCCCCCC;
263     lpData[1] = 0xCCCCCCCC;
264     lpData[2] = 0xCCCCCCCC;
265     lpData[3] = 0xCCCCCCCC;
266
267     memset(&ddsd3, 0, sizeof(ddsd3));
268     ddsd3.dwSize = sizeof(ddsd3);
269     ddsd3.ddpfPixelFormat.dwSize = sizeof(ddsd3.ddpfPixelFormat);
270     rc = IDirectDrawSurface_GetSurfaceDesc(lpDst, &ddsd3);
271     ok(rc == DD_OK, "IDirectDrawSurface_GetSurfaceDesc between a lock/unlock pair returned %08x\n", rc);
272     ok(ddsd3.lpSurface == ddsd3.lpSurface, "lpSurface from GetSurfaceDesc(%p) differs from the one returned by Lock(%p)\n", ddsd3.lpSurface, ddsd2.lpSurface);
273
274     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
275     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
276
277     memset(&ddsd3, 0, sizeof(ddsd3));
278     ddsd3.dwSize = sizeof(ddsd3);
279     ddsd3.ddpfPixelFormat.dwSize = sizeof(ddsd3.ddpfPixelFormat);
280     rc = IDirectDrawSurface_GetSurfaceDesc(lpDst, &ddsd3);
281     ok(rc == DD_OK, "IDirectDrawSurface_GetSurfaceDesc between a lock/unlock pair returned %08x\n", rc);
282     ok(ddsd3.lpSurface == NULL, "lpSurface from GetSurfaceDesc(%p) is not NULL after unlock\n", ddsd3.lpSurface);
283
284     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
285     ok(rc==DD_OK,"Lock returned: %x\n",rc);
286     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
287     lpData = ddsd2.lpSurface;
288     lpData[0] = 0x77010203;
289     lpData[1] = 0x00010203;
290     lpData[2] = 0x77FF00FF;
291     lpData[3] = 0x00FF00FF;
292     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
293     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
294
295     IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, NULL);
296
297     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
298     ok(rc==DD_OK,"Lock returned: %x\n",rc);
299     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
300     lpData = ddsd2.lpSurface;
301     /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
302      * color keying, but copy it to the destination surface. Others apply it for color keying, but
303      * do not copy it into the destination surface.
304      */
305     if(lpData[0]==0x00010203) {
306         trace("X channel was not copied into the destination surface\n");
307         ok((lpData[0]==0x00010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0x00FF00FF)&&(lpData[3]==0xCCCCCCCC),
308            "Destination data after blitting is not correct\n");
309     } else {
310         ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC),
311            "Destination data after blitting is not correct\n");
312     }
313     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
314     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
315
316     /* Below we repeat the same test as above but now using BltFast instead of Blt. Before
317      * we can carry out the test we need to restore the color of the destination surface.
318      */
319     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
320     ok(rc==DD_OK,"Lock returned: %x\n",rc);
321     lpData = ddsd2.lpSurface;
322     lpData[0] = 0xCCCCCCCC;
323     lpData[1] = 0xCCCCCCCC;
324     lpData[2] = 0xCCCCCCCC;
325     lpData[3] = 0xCCCCCCCC;
326     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
327     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
328
329     IDirectDrawSurface_BltFast(lpDst, 0, 0, lpSrc, NULL, DDBLTFAST_SRCCOLORKEY);
330
331     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
332     ok(rc==DD_OK,"Lock returned: %x\n",rc);
333     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
334     lpData = ddsd2.lpSurface;
335     /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
336      * color keying, but copy it to the destination surface. Others apply it for color keying, but
337      * do not copy it into the destination surface.
338      */
339     if(lpData[0]==0x00010203) {
340         trace("X channel was not copied into the destination surface\n");
341         ok((lpData[0]==0x00010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0x00FF00FF)&&(lpData[3]==0xCCCCCCCC),
342            "Destination data after blitting is not correct\n");
343     } else {
344         ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC),
345            "Destination data after blitting is not correct\n");
346     }
347     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
348     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
349
350     /* Also test SetColorKey */
351     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
352     ok(DDColorKey.dwColorSpaceLowValue == 0xFF00FF && DDColorKey.dwColorSpaceHighValue == 0xFF00FF,
353        "GetColorKey does not return the colorkey used at surface creation\n");
354
355     DDColorKey.dwColorSpaceLowValue = 0x00FF00;
356     DDColorKey.dwColorSpaceHighValue = 0x00FF00;
357     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
358
359     DDColorKey.dwColorSpaceLowValue = 0;
360     DDColorKey.dwColorSpaceHighValue = 0;
361     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
362     ok(DDColorKey.dwColorSpaceLowValue == 0x00FF00 && DDColorKey.dwColorSpaceHighValue == 0x00FF00,
363        "GetColorKey does not return the colorkey set with SetColorKey\n");
364
365     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
366     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
367     IDirectDrawSurface_GetSurfaceDesc(lpSrc, &ddsd);
368     ok(ddsd.ddckCKSrcBlt.dwColorSpaceLowValue == 0x00FF00 && ddsd.ddckCKSrcBlt.dwColorSpaceHighValue == 0x00FF00,
369        "GetSurfaceDesc does not return the colorkey set with SetColorKey\n");
370
371     /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
372     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
373     DDColorKey.dwColorSpaceHighValue = 0x000000;
374     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
375
376     DDColorKey.dwColorSpaceLowValue = 0;
377     DDColorKey.dwColorSpaceHighValue = 0;
378     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
379     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
380        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
381
382     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
383     DDColorKey.dwColorSpaceHighValue = 0x000001;
384     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
385
386     DDColorKey.dwColorSpaceLowValue = 0;
387     DDColorKey.dwColorSpaceHighValue = 0;
388     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
389     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
390        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
391
392     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
393     DDColorKey.dwColorSpaceHighValue = 0x0000FE;
394     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
395
396     DDColorKey.dwColorSpaceLowValue = 0;
397     DDColorKey.dwColorSpaceHighValue = 0;
398     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
399     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
400        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
401
402     IDirectDrawSurface_Release(lpSrc);
403     IDirectDrawSurface_Release(lpDst);
404
405     /* start with a new set of surfaces to test the color keying parameters to blit */
406     memset(&ddsd, 0, sizeof(ddsd));
407     ddsd.dwSize = sizeof(ddsd);
408     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
409     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT;
410     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
411     ddsd.dwWidth = 800;
412     ddsd.dwHeight = 600;
413     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
414     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
415     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
416     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
417     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
418     ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0xFF0000;
419     ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0xFF0000;
420     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00FF00;
421     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00FF00;
422     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
423     ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc);
424     if(FAILED(rc))
425     {
426         skip("Failed to create surface\n");
427         return;
428     }
429
430     /* start with a new set of surfaces to test the color keying parameters to blit */
431     memset(&ddsd, 0, sizeof(ddsd));
432     ddsd.dwSize = sizeof(ddsd);
433     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
434     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT;
435     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
436     ddsd.dwWidth = 800;
437     ddsd.dwHeight = 600;
438     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
439     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
440     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
441     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
442     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
443     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x0000FF;
444     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x0000FF;
445     ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0x000000;
446     ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0x000000;
447     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
448     ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc);
449     if(FAILED(rc))
450     {
451         skip("Failed to create surface\n");
452         IDirectDrawSurface_Release(lpDst);
453         return;
454     }
455
456     memset(&fx, 0, sizeof(fx));
457     fx.dwSize = sizeof(fx);
458     fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x110000;
459     fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x110000;
460     fx.ddckDestColorkey.dwColorSpaceHighValue = 0x001100;
461     fx.ddckDestColorkey.dwColorSpaceLowValue = 0x001100;
462
463     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
464     ok(rc==DD_OK,"Lock returned: %x\n",rc);
465     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
466     lpData = ddsd2.lpSurface;
467     lpData[0] = 0x000000FF; /* Applies to src blt key in src surface */
468     lpData[1] = 0x00000000; /* Applies to dst blt key in src surface */
469     lpData[2] = 0x00FF0000; /* Dst color key in dst surface */
470     lpData[3] = 0x0000FF00; /* Src color key in dst surface */
471     lpData[4] = 0x00001100; /* Src color key in ddbltfx */
472     lpData[5] = 0x00110000; /* Dst color key in ddbltfx */
473     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
474     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
475
476     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
477     ok(rc==DD_OK,"Lock returned: %x\n",rc);
478     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
479     lpData = ddsd2.lpSurface;
480     lpData[0] = 0x55555555;
481     lpData[1] = 0x55555555;
482     lpData[2] = 0x55555555;
483     lpData[3] = 0x55555555;
484     lpData[4] = 0x55555555;
485     lpData[5] = 0x55555555;
486     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
487     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
488
489     /* Test a blit without keying */
490     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, 0, &fx);
491     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
492
493     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
494     ok(rc==DD_OK,"Lock returned: %x\n",rc);
495     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
496     lpData = ddsd2.lpSurface;
497     /* Should have copied src data unmodified to dst */
498     ok(lpData[0] == 0x000000FF &&
499        lpData[1] == 0x00000000 &&
500        lpData[2] == 0x00FF0000 &&
501        lpData[3] == 0x0000FF00 &&
502        lpData[4] == 0x00001100 &&
503        lpData[5] == 0x00110000, "Surface data after unkeyed blit does not match\n");
504
505     lpData[0] = 0x55555555;
506     lpData[1] = 0x55555555;
507     lpData[2] = 0x55555555;
508     lpData[3] = 0x55555555;
509     lpData[4] = 0x55555555;
510     lpData[5] = 0x55555555;
511     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
512     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
513
514     /* Src key */
515     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx);
516     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
517
518     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
519     ok(rc==DD_OK,"Lock returned: %x\n",rc);
520     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
521     lpData = ddsd2.lpSurface;
522
523     ok(lpData[0] == 0x55555555 && /* Here the src key applied */
524        lpData[1] == 0x00000000 &&
525        lpData[2] == 0x00FF0000 &&
526        lpData[3] == 0x0000FF00 &&
527        lpData[4] == 0x00001100 &&
528        lpData[5] == 0x00110000, "Surface data after srckey blit does not match\n");
529
530     lpData[0] = 0x55555555;
531     lpData[1] = 0x55555555;
532     lpData[2] = 0x55555555;
533     lpData[3] = 0x55555555;
534     lpData[4] = 0x55555555;
535     lpData[5] = 0x55555555;
536     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
537     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
538
539     /* Src override */
540     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
541     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
542
543     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
544     ok(rc==DD_OK,"Lock returned: %x\n",rc);
545     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
546     lpData = ddsd2.lpSurface;
547
548     ok(lpData[0] == 0x000000FF &&
549        lpData[1] == 0x00000000 &&
550        lpData[2] == 0x00FF0000 &&
551        lpData[3] == 0x0000FF00 &&
552        lpData[4] == 0x00001100 &&
553        lpData[5] == 0x55555555, /* Override key applies here */
554        "Surface data after src override key blit does not match\n");
555
556     lpData[0] = 0x55555555;
557     lpData[1] = 0x55555555;
558     lpData[2] = 0x55555555;
559     lpData[3] = 0x55555555;
560     lpData[4] = 0x55555555;
561     lpData[5] = 0x55555555;
562     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
563     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
564
565     /* Src override AND src key. That is not supposed to work */
566     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
567     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
568
569     /* Verify that the destination is unchanged */
570     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
571     ok(rc==DD_OK,"Lock returned: %x\n",rc);
572     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
573     lpData = ddsd2.lpSurface;
574
575     ok(lpData[0] == 0x55555555 &&
576        lpData[1] == 0x55555555 &&
577        lpData[2] == 0x55555555 &&
578        lpData[3] == 0x55555555 &&
579        lpData[4] == 0x55555555 &&
580        lpData[5] == 0x55555555, /* Override key applies here */
581        "Surface data after src key blit with override does not match\n");
582
583     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
584     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
585     lpData[2] = 0x00001100; /* Dest key in override */
586     lpData[3] = 0x00001100; /* Dest key in override */
587     lpData[4] = 0x00000000; /* Dest key in src surface */
588     lpData[5] = 0x00000000; /* Dest key in src surface */
589     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
590     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
591
592     /* Dest key blit */
593     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx);
594     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
595
596     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
597     ok(rc==DD_OK,"Lock returned: %x\n",rc);
598     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
599     lpData = ddsd2.lpSurface;
600
601     /* DirectDraw uses the dest blit key from the SOURCE surface ! */
602     ok(lpData[0] == 0x00ff0000 &&
603        lpData[1] == 0x00ff0000 &&
604        lpData[2] == 0x00001100 &&
605        lpData[3] == 0x00001100 &&
606        lpData[4] == 0x00001100 && /* Key applies here */
607        lpData[5] == 0x00110000,   /* Key applies here */
608        "Surface data after dest key blit does not match\n");
609
610     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
611     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
612     lpData[2] = 0x00001100; /* Dest key in override */
613     lpData[3] = 0x00001100; /* Dest key in override */
614     lpData[4] = 0x00000000; /* Dest key in src surface */
615     lpData[5] = 0x00000000; /* Dest key in src surface */
616     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
617     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
618
619     /* Dest override key blit */
620     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
621     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
622
623     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
624     ok(rc==DD_OK,"Lock returned: %x\n",rc);
625     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
626     lpData = ddsd2.lpSurface;
627
628     ok(lpData[0] == 0x00FF0000 &&
629        lpData[1] == 0x00FF0000 &&
630        lpData[2] == 0x00FF0000 && /* Key applies here */
631        lpData[3] == 0x0000FF00 && /* Key applies here */
632        lpData[4] == 0x00000000 &&
633        lpData[5] == 0x00000000,
634        "Surface data after dest key override blit does not match\n");
635
636     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
637     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
638     lpData[2] = 0x00001100; /* Dest key in override */
639     lpData[3] = 0x00001100; /* Dest key in override */
640     lpData[4] = 0x00000000; /* Dest key in src surface */
641     lpData[5] = 0x00000000; /* Dest key in src surface */
642     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
643     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
644
645     /* Dest override key blit. Supposed to fail too */
646     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
647     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
648
649     /* Check for unchanged data */
650     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
651     ok(rc==DD_OK,"Lock returned: %x\n",rc);
652     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
653     lpData = ddsd2.lpSurface;
654
655     ok(lpData[0] == 0x00FF0000 &&
656        lpData[1] == 0x00FF0000 &&
657        lpData[2] == 0x00001100 && /* Key applies here */
658        lpData[3] == 0x00001100 && /* Key applies here */
659        lpData[4] == 0x00000000 &&
660        lpData[5] == 0x00000000,
661        "Surface data with dest key and dest override does not match\n");
662
663     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
664     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
665     lpData[2] = 0x00001100; /* Dest key in override */
666     lpData[3] = 0x00001100; /* Dest key in override */
667     lpData[4] = 0x00000000; /* Dest key in src surface */
668     lpData[5] = 0x00000000; /* Dest key in src surface */
669     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
670     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
671
672     /* Modify the source data a bit to give some more conclusive results */
673     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
674     ok(rc==DD_OK,"Lock returned: %x\n",rc);
675     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
676     lpData = ddsd2.lpSurface;
677     lpData[5] = 0x000000FF; /* Applies to src blt key in src surface */
678     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
679     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
680
681     /* Source and destination key */
682     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
683     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
684
685     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
686     ok(rc==DD_OK,"Lock returned: %x\n",rc);
687     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
688     lpData = ddsd2.lpSurface;
689
690     ok(lpData[0] == 0x00FF0000 && /* Masked by Destination key */
691        lpData[1] == 0x00FF0000 && /* Masked by Destination key */
692        lpData[2] == 0x00001100 && /* Masked by Destination key */
693        lpData[3] == 0x00001100 && /* Masked by Destination key */
694        lpData[4] == 0x00001100 && /* Allowed by destination key, not masked by source key */
695        lpData[5] == 0x00000000,   /* Allowed by dst key, but masked by source key */
696        "Surface data with src key and dest key blit does not match\n");
697
698     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
699     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
700     lpData[2] = 0x00001100; /* Dest key in override */
701     lpData[3] = 0x00001100; /* Dest key in override */
702     lpData[4] = 0x00000000; /* Dest key in src surface */
703     lpData[5] = 0x00000000; /* Dest key in src surface */
704     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
705     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
706
707     /* Override keys without ddbltfx parameter fail */
708     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
709     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
710     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
711     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
712
713     /* Try blitting without keys in the source surface*/
714     rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, NULL);
715     ok(rc == DD_OK, "SetColorKey returned %x\n", rc);
716     rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_DESTBLT, NULL);
717     ok(rc == DD_OK, "SetColorKey returned %x\n", rc);
718
719     /* That fails now. Do not bother to check that the data is unmodified */
720     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx);
721     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
722
723     /* Dest key blit still works. Which key is used this time??? */
724     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx);
725     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
726
727     /* With correctly passed override keys no key in the surface is needed.
728      * Again, the result was checked before, no need to do that again
729      */
730     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
731     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
732     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
733     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
734
735     IDirectDrawSurface_Release(lpSrc);
736     IDirectDrawSurface_Release(lpDst);
737 }
738
739 static void QueryInterface(void)
740 {
741     LPDIRECTDRAWSURFACE dsurface;
742     DDSURFACEDESC surface;
743     LPVOID object;
744     HRESULT ret;
745
746     /* Create a surface */
747     ZeroMemory(&surface, sizeof(surface));
748     surface.dwSize = sizeof(surface);
749     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
750     surface.dwHeight = 10;
751     surface.dwWidth = 10;
752     ret = IDirectDraw_CreateSurface(lpDD, &surface, &dsurface, NULL);
753     if(ret != DD_OK)
754     {
755         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
756         return;
757     }
758
759     /* Call IUnknown::QueryInterface */
760     ret = IDirectDrawSurface_QueryInterface(dsurface, 0, &object);
761     ok(ret == DDERR_INVALIDPARAMS, "IDirectDrawSurface::QueryInterface returned %x\n", ret);
762
763     IDirectDrawSurface_Release(dsurface);
764 }
765
766 /* The following tests test which interface is returned by IDirectDrawSurfaceX::GetDDInterface.
767  * It uses refcounts to test that and compares the interface addresses. Partially fits here, and
768  * partially in the refcount test
769  */
770
771 static ULONG getref(IUnknown *iface)
772 {
773     IUnknown_AddRef(iface);
774     return IUnknown_Release(iface);
775 }
776
777 static void GetDDInterface_1(void)
778 {
779     LPDIRECTDRAWSURFACE dsurface;
780     LPDIRECTDRAWSURFACE2 dsurface2;
781     DDSURFACEDESC surface;
782     HRESULT ret;
783     IDirectDraw2 *dd2;
784     IDirectDraw4 *dd4;
785     IDirectDraw7 *dd7;
786     ULONG ref1, ref2, ref4, ref7;
787     void *dd;
788
789     /* Create a surface */
790     ZeroMemory(&surface, sizeof(surface));
791     surface.dwSize = sizeof(surface);
792     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
793     surface.dwHeight = 10;
794     surface.dwWidth = 10;
795     ret = IDirectDraw_CreateSurface(lpDD, &surface, &dsurface, NULL);
796     if(ret != DD_OK)
797     {
798         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
799         return;
800     }
801     ret = IDirectDrawSurface_QueryInterface(dsurface, &IID_IDirectDrawSurface2, (void **) &dsurface2);
802     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
803     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
804     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
805     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
806     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
807     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
808     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
809
810     ref1 = getref((IUnknown *) lpDD);
811     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
812     ref2 = getref((IUnknown *) dd2);
813     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
814     ref4 = getref((IUnknown *) dd4);
815     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
816     ref7 = getref((IUnknown *) dd7);
817     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
818
819
820     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
821     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
822     ok(getref((IUnknown *) lpDD) == ref1 + 1, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
823     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
824     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
825     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
826
827     ok(dd == lpDD, "Returned interface pointer is not equal to the creation interface\n");
828     IUnknown_Release((IUnknown *) dd);
829
830     /* try a NULL pointer */
831     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, NULL);
832     ok(ret == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
833
834     IDirectDraw_Release(dd2);
835     IDirectDraw_Release(dd4);
836     IDirectDraw_Release(dd7);
837     IDirectDrawSurface2_Release(dsurface2);
838     IDirectDrawSurface_Release(dsurface);
839 }
840
841 static void GetDDInterface_2(void)
842 {
843     LPDIRECTDRAWSURFACE dsurface;
844     LPDIRECTDRAWSURFACE2 dsurface2;
845     DDSURFACEDESC surface;
846     HRESULT ret;
847     IDirectDraw2 *dd2;
848     IDirectDraw4 *dd4;
849     IDirectDraw7 *dd7;
850     ULONG ref1, ref2, ref4, ref7;
851     void *dd;
852
853     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
854     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
855     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
856     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
857     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
858     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
859
860     /* Create a surface */
861     ZeroMemory(&surface, sizeof(surface));
862     surface.dwSize = sizeof(surface);
863     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
864     surface.dwHeight = 10;
865     surface.dwWidth = 10;
866     ret = IDirectDraw2_CreateSurface(dd2, &surface, &dsurface, NULL);
867     if(ret != DD_OK)
868     {
869         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
870         return;
871     }
872     ret = IDirectDrawSurface_QueryInterface(dsurface, &IID_IDirectDrawSurface2, (void **) &dsurface2);
873     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
874
875     ref1 = getref((IUnknown *) lpDD);
876     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
877     ref2 = getref((IUnknown *) dd2);
878     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
879     ref4 = getref((IUnknown *) dd4);
880     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
881     ref7 = getref((IUnknown *) dd7);
882     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
883
884
885     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
886     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
887     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
888     ok(getref((IUnknown *) dd2) == ref2 + 1, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
889     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
890     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
891
892     ok(dd == dd2, "Returned interface pointer is not equal to the creation interface\n");
893     IUnknown_Release((IUnknown *) dd);
894
895     IDirectDraw_Release(dd2);
896     IDirectDraw_Release(dd4);
897     IDirectDraw_Release(dd7);
898     IDirectDrawSurface2_Release(dsurface2);
899     IDirectDrawSurface_Release(dsurface);
900 }
901
902 static void GetDDInterface_4(void)
903 {
904     LPDIRECTDRAWSURFACE2 dsurface2;
905     LPDIRECTDRAWSURFACE4 dsurface4;
906     DDSURFACEDESC2 surface;
907     HRESULT ret;
908     IDirectDraw2 *dd2;
909     IDirectDraw4 *dd4;
910     IDirectDraw7 *dd7;
911     ULONG ref1, ref2, ref4, ref7;
912     void *dd;
913
914     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
915     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
916     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
917     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
918     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
919     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
920
921     /* Create a surface */
922     ZeroMemory(&surface, sizeof(surface));
923     surface.dwSize = sizeof(surface);
924     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
925     surface.dwHeight = 10;
926     surface.dwWidth = 10;
927     ret = IDirectDraw4_CreateSurface(dd4, &surface, &dsurface4, NULL);
928     if(ret != DD_OK)
929     {
930         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
931         return;
932     }
933     ret = IDirectDrawSurface4_QueryInterface(dsurface4, &IID_IDirectDrawSurface2, (void **) &dsurface2);
934     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
935
936     ref1 = getref((IUnknown *) lpDD);
937     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
938     ref2 = getref((IUnknown *) dd2);
939     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
940     ref4 = getref((IUnknown *) dd4);
941     ok(ref4 == 2, "IDirectDraw4 refcount is %d\n", ref4);
942     ref7 = getref((IUnknown *) dd7);
943     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
944
945     ret = IDirectDrawSurface4_GetDDInterface(dsurface4, &dd);
946     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
947     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
948     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
949     ok(getref((IUnknown *) dd4) == ref4 + 1, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
950     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
951
952     ok(dd == dd4, "Returned interface pointer is not equal to the creation interface\n");
953     IUnknown_Release((IUnknown *) dd);
954
955     /* Now test what happens if we QI the surface for some other version - It should still return the creation interface */
956     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
957     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
958     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
959     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
960     ok(getref((IUnknown *) dd4) == ref4 + 1, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
961     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
962
963     ok(dd == dd4, "Returned interface pointer is not equal to the creation interface\n");
964     IUnknown_Release((IUnknown *) dd);
965
966     IDirectDraw_Release(dd2);
967     IDirectDraw_Release(dd4);
968     IDirectDraw_Release(dd7);
969     IDirectDrawSurface4_Release(dsurface4);
970     IDirectDrawSurface2_Release(dsurface2);
971 }
972
973 static void GetDDInterface_7(void)
974 {
975     LPDIRECTDRAWSURFACE4 dsurface4;
976     LPDIRECTDRAWSURFACE7 dsurface7;
977     DDSURFACEDESC2 surface;
978     HRESULT ret;
979     IDirectDraw2 *dd2;
980     IDirectDraw4 *dd4;
981     IDirectDraw7 *dd7;
982     ULONG ref1, ref2, ref4, ref7;
983     void *dd;
984
985     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
986     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
987     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
988     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
989     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
990     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
991
992     /* Create a surface */
993     ZeroMemory(&surface, sizeof(surface));
994     surface.dwSize = sizeof(surface);
995     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
996     surface.dwHeight = 10;
997     surface.dwWidth = 10;
998     ret = IDirectDraw7_CreateSurface(dd7, &surface, &dsurface7, NULL);
999     if(ret != DD_OK)
1000     {
1001         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
1002         return;
1003     }
1004     ret = IDirectDrawSurface7_QueryInterface(dsurface7, &IID_IDirectDrawSurface4, (void **) &dsurface4);
1005     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
1006
1007     ref1 = getref((IUnknown *) lpDD);
1008     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
1009     ref2 = getref((IUnknown *) dd2);
1010     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
1011     ref4 = getref((IUnknown *) dd4);
1012     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
1013     ref7 = getref((IUnknown *) dd7);
1014     ok(ref7 == 2, "IDirectDraw7 refcount is %d\n", ref7);
1015
1016     ret = IDirectDrawSurface7_GetDDInterface(dsurface7, &dd);
1017     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
1018     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
1019     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
1020     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
1021     ok(getref((IUnknown *) dd7) == ref7 + 1, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
1022
1023     ok(dd == dd7, "Returned interface pointer is not equal to the creation interface\n");
1024     IUnknown_Release((IUnknown *) dd);
1025
1026     /* Now test what happens if we QI the surface for some other version - It should still return the creation interface */
1027     ret = IDirectDrawSurface4_GetDDInterface(dsurface4, &dd);
1028     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
1029     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
1030     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
1031     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
1032     ok(getref((IUnknown *) dd7) == ref7 + 1, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
1033
1034     ok(dd == dd7, "Returned interface pointer is not equal to the creation interface\n");
1035     IUnknown_Release((IUnknown *) dd);
1036
1037     IDirectDraw_Release(dd2);
1038     IDirectDraw_Release(dd4);
1039     IDirectDraw_Release(dd7);
1040     IDirectDrawSurface4_Release(dsurface4);
1041     IDirectDrawSurface7_Release(dsurface7);
1042 }
1043
1044 static ULONG getRefcount(IUnknown *iface)
1045 {
1046     IUnknown_AddRef(iface);
1047     return IUnknown_Release(iface);
1048 }
1049
1050 static void IFaceRefCount(void)
1051 {
1052     LPDIRECTDRAWSURFACE surf;
1053     DDSURFACEDESC surface;
1054     HRESULT ret;
1055     IDirectDrawSurface2 *surf2;
1056     IDirectDrawSurface2 *surf2a;
1057     IDirectDrawSurface3 *surf3;
1058     IDirectDrawSurface4 *surf4;
1059     IDirectDrawSurface7 *surf7a;
1060     IDirectDrawSurface7 *surf7b;
1061     IDirect3DTexture* tex;
1062     IDirect3DTexture2* tex2;
1063     IDirectDrawGammaControl* gamma;
1064     ULONG ref;
1065
1066     /* Create a surface */
1067     ZeroMemory(&surface, sizeof(surface));
1068     surface.dwSize = sizeof(surface);
1069     surface.dwFlags = DDSD_CAPS;
1070     surface.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1071     ret = IDirectDraw_CreateSurface(lpDD, &surface, &surf, NULL);
1072
1073     if (ret != DD_OK)
1074     {
1075         ok(FALSE, "Could not create surface, skipping test\n");
1076         return;
1077     }
1078
1079     ref = getRefcount((IUnknown *) surf);
1080     ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* Check the ref count is one */
1081
1082     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2);
1083     ref = getRefcount((IUnknown *) surf);
1084     ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* Check the ref count is one */
1085     ref = getRefcount((IUnknown *) surf2);
1086     ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* This should also be one */
1087
1088     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2a);
1089     ref = getRefcount((IUnknown *) surf2);
1090     ok(ref == 2, "Refcount is %u, expected 2\n", ref);   /* Surf2's refcount should be 2 now, but surf should be 1 */
1091     ref = getRefcount((IUnknown *) surf);
1092     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1093
1094     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface3, (void **) &surf3);
1095     ref = getRefcount((IUnknown *) surf3);
1096     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1097
1098     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface4, (void **) &surf4);
1099     ref = getRefcount((IUnknown *) surf4);
1100     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1101
1102     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface7, (void **) &surf7a);
1103     ref = getRefcount((IUnknown *) surf7a);
1104     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1105
1106     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface7, (void **) &surf7b);
1107     ref = getRefcount((IUnknown *) surf7b);
1108     ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1109
1110     /* IDirect3DTexture interface (unlike the others) alters the original IDirectDrawSurface ref count */
1111     ret = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DTexture, (void **) &tex);
1112     if (SUCCEEDED(ret))
1113     {
1114         ref = getRefcount((IUnknown *) tex);
1115         ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1116         ref = getRefcount((IUnknown *) surf);
1117         ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1118
1119         IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DTexture2, (void **) &tex2);
1120         ref = getRefcount((IUnknown *) tex);
1121         ok(ref == 3, "Refcount is %u, expected 3\n", ref);
1122         ref = getRefcount((IUnknown *) tex2);
1123         ok(ref == 3, "Refcount is %u, expected 3\n", ref);
1124         ref = getRefcount((IUnknown *) surf);
1125         ok(ref == 3, "Refcount is %u, expected 3\n", ref);
1126
1127         IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawGammaControl, (void **) &gamma);
1128         ref = getRefcount((IUnknown *) gamma);
1129         ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1130
1131         ref = IDirect3DTexture2_Release(tex2); /* Release the texture */
1132         ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1133         ref = getRefcount((IUnknown *) surf);
1134         ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1135
1136         ref = IDirect3DTexture_Release(tex); /* Release the texture */
1137         ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1138         ref = getRefcount((IUnknown *) surf);
1139         ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1140
1141         ref = IDirectDrawGammaControl_Release(gamma); /* Release the gamma control */
1142         ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1143     }
1144
1145     ref = IDirectDrawSurface2_Release(surf2); /* Release one of the 2 surf2 interfaces */
1146     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1147
1148     ref = IDirectDrawSurface2_Release(surf2a); /* Release the other */
1149     ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1150
1151     ref = IDirectDrawSurface3_Release(surf3);
1152     ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1153
1154     ref = IDirectDrawSurface4_Release(surf4);
1155     ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1156
1157     ref = IDirectDrawSurface7_Release(surf7a);
1158     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1159
1160     ref = IDirectDrawSurface7_Release(surf7b);
1161     ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1162
1163     ref = IDirectDrawSurface_Release(surf);
1164     ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1165 }
1166
1167 #define MAXEXPECTED 8  /* Can match up to 8 expected surfaces */
1168 struct enumstruct
1169 {
1170     IDirectDrawSurface *expected[MAXEXPECTED];
1171     UINT count;
1172 };
1173
1174 static HRESULT WINAPI enumCB(IDirectDrawSurface *surf, DDSURFACEDESC *desc, void *ctx)
1175 {
1176     int i;
1177     BOOL found = FALSE;
1178
1179     for(i = 0; i < MAXEXPECTED; i++)
1180     {
1181         if(((struct enumstruct *)ctx)->expected[i] == surf) found = TRUE;
1182     }
1183
1184     ok(found, "Unexpected surface %p enumerated\n", surf);
1185     ((struct enumstruct *)ctx)->count++;
1186     IDirectDrawSurface_Release(surf);
1187     return DDENUMRET_OK;
1188 }
1189
1190 static void EnumTest(void)
1191 {
1192     HRESULT rc;
1193     DDSURFACEDESC ddsd;
1194     IDirectDrawSurface *surface;
1195     struct enumstruct ctx;
1196
1197     ddsd.dwSize = sizeof(ddsd);
1198     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1199     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1200     U2(ddsd).dwMipMapCount = 3;
1201     ddsd.dwWidth = 32;
1202     ddsd.dwHeight = 32;
1203     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
1204     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
1205
1206     memset(&ctx, 0, sizeof(ctx));
1207     ctx.expected[0] = surface;
1208     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[0], &ddsd.ddsCaps, &ctx.expected[1]);
1209     ok(rc == DD_OK, "GetAttachedSurface returned %08x\n", rc);
1210     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[1], &ddsd.ddsCaps, &ctx.expected[2]);
1211     ok(rc == DD_OK, "GetAttachedSurface returned %08x\n", rc);
1212     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[2], &ddsd.ddsCaps, &ctx.expected[3]);
1213     ok(rc == DDERR_NOTFOUND, "GetAttachedSurface returned %08x\n", rc);
1214     ok(!ctx.expected[3], "expected NULL pointer\n");
1215     ctx.count = 0;
1216
1217     rc = IDirectDraw_EnumSurfaces(lpDD, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, &ddsd, &ctx, enumCB);
1218     ok(rc == DD_OK, "IDirectDraw_EnumSurfaces returned %08x\n", rc);
1219     ok(ctx.count == 3, "%d surfaces enumerated, expected 3\n", ctx.count);
1220
1221     ctx.count = 0;
1222     rc = IDirectDraw_EnumSurfaces(lpDD, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, &ctx, enumCB);
1223     ok(rc == DD_OK, "IDirectDraw_EnumSurfaces returned %08x\n", rc);
1224     ok(ctx.count == 3, "%d surfaces enumerated, expected 3\n", ctx.count);
1225
1226     IDirectDrawSurface_Release(ctx.expected[2]);
1227     IDirectDrawSurface_Release(ctx.expected[1]);
1228     IDirectDrawSurface_Release(surface);
1229 }
1230
1231 static HRESULT WINAPI SurfaceCounter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1232 {
1233     UINT *num = context;
1234     (*num)++;
1235     IDirectDrawSurface_Release(surface);
1236     return DDENUMRET_OK;
1237 }
1238
1239 static void AttachmentTest7(void)
1240 {
1241     HRESULT hr;
1242     IDirectDraw7 *dd7;
1243     IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
1244     IDirectDrawSurface *surface1v1, *surface2v1;
1245     DDSURFACEDESC2 ddsd, ddsd2;
1246     DWORD ref;
1247     UINT num;
1248     DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, 0}, caps2 = {DDSCAPS_BACKBUFFER,0,0,0};
1249     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1250
1251     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
1252     ok(hr == DD_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
1253
1254     memset(&ddsd, 0, sizeof(ddsd));
1255     ddsd.dwSize = sizeof(ddsd);
1256     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1257     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1258     U2(ddsd).dwMipMapCount = 3; /* Will create 128x128, 64x64, 32x32 */
1259     ddsd.dwWidth = 128;
1260     ddsd.dwHeight = 128;
1261     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1262     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1263
1264     /* ROOT */
1265     num = 0;
1266     IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &num, SurfaceCounter);
1267     ok(num == 1, "Mipmap root has %d surfaces attached, expected 1\n", num);
1268     /* DONE ROOT */
1269
1270     /* LEVEL 1 */
1271     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
1272     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1273     num = 0;
1274     IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &num, SurfaceCounter);
1275     ok(num == 1, "First mip level has %d surfaces attached, expected 1\n", num);
1276     /* DONE LEVEL 1 */
1277
1278     /* LEVEL 2 */
1279     hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
1280     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1281     IDirectDrawSurface7_Release(surface2);
1282     num = 0;
1283     IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &num, SurfaceCounter);
1284     ok(num == 0, "Second mip level has %d surfaces attached, expected 1\n", num);
1285     /* Done level 2 */
1286     /* Mip level 3 is still needed */
1287     hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
1288     ok(hr == DDERR_NOTFOUND, "GetAttachedSurface returned %08x\n", hr);
1289     ok(!surface4, "expected NULL pointer\n");
1290
1291     /* Try to attach a 16x16 miplevel - Should not work as far I can see */
1292     memset(&ddsd, 0, sizeof(ddsd));
1293     ddsd.dwSize = sizeof(ddsd);
1294     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1295     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1296     ddsd.dwWidth = 16;
1297     ddsd.dwHeight = 16;
1298     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1299     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1300
1301     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1302     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 128x128 texture root returned %08x\n", hr);
1303     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1304     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 texture returned %08x\n", hr);
1305     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
1306     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 32x32 texture mip level returned %08x\n", hr);
1307     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1308     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 surface returned %08x\n", hr);
1309
1310     IDirectDrawSurface7_Release(surface2);
1311
1312     memset(&ddsd, 0, sizeof(ddsd));
1313     ddsd.dwSize = sizeof(ddsd);
1314     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1315     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
1316     ddsd.dwWidth = 16;
1317     ddsd.dwHeight = 16;
1318     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1319     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1320
1321     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1322     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1323     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1324     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1325     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
1326     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1327     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1328     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 offscreen plain surface returned %08x\n", hr);
1329
1330     IDirectDrawSurface7_Release(surface3);
1331     IDirectDrawSurface7_Release(surface2);
1332     IDirectDrawSurface7_Release(surface1);
1333
1334     hr = IDirectDraw7_SetCooperativeLevel(dd7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1335     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1336
1337     memset(&ddsd, 0, sizeof(ddsd));
1338     ddsd.dwSize = sizeof(ddsd);
1339     ddsd.dwFlags = DDSD_BACKBUFFERCOUNT | DDSD_CAPS;
1340     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1341     ddsd.dwBackBufferCount = 2;
1342     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1343     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1344
1345     /* backbuffer surfaces must not have dwBackBufferCount set */
1346     ddsd2.dwSize = sizeof(ddsd2);
1347     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps2, &surface2);
1348     ok(hr==DD_OK,"GetAttachedSurface returned: %x\n", hr);
1349     hr = IDirectDrawSurface7_GetSurfaceDesc(surface2, &ddsd2);
1350     ok(hr==DD_OK,"GetSurfaceDesc returned: %x\n", hr);
1351     ok(ddsd2.dwBackBufferCount==0,"backbuffer surface has dwBackBufferCount==%u\n", ddsd2.dwBackBufferCount);
1352
1353     num = 0;
1354     IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &num, SurfaceCounter);
1355     ok(num == 1, "Primary surface has %d surfaces attached, expected 1\n", num);
1356     IDirectDrawSurface7_Release(surface1);
1357
1358     /* Those are some invalid descriptions, no need to test attachments with them */
1359     memset(&ddsd, 0, sizeof(ddsd));
1360     ddsd.dwSize = sizeof(ddsd);
1361     ddsd.dwFlags = DDSD_CAPS;
1362     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER;
1363     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1364     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1365     memset(&ddsd, 0, sizeof(ddsd));
1366     ddsd.dwSize = sizeof(ddsd);
1367     ddsd.dwFlags = DDSD_CAPS;
1368     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER;
1369     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1370     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1371
1372     /* Try a single primary and two offscreen plain surfaces */
1373     memset(&ddsd, 0, sizeof(ddsd));
1374     ddsd.dwSize = sizeof(ddsd);
1375     ddsd.dwFlags = DDSD_CAPS;
1376     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1377     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1378     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1379
1380     memset(&ddsd, 0, sizeof(ddsd));
1381     ddsd.dwSize = sizeof(ddsd);
1382     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1383     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1384     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1385     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1386     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1387     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1388
1389     memset(&ddsd, 0, sizeof(ddsd));
1390     ddsd.dwSize = sizeof(ddsd);
1391     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1392     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1393     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1394     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1395     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface3, NULL);
1396     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1397
1398     /* This one has a different size */
1399     memset(&ddsd, 0, sizeof(ddsd));
1400     ddsd.dwSize = sizeof(ddsd);
1401     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1402     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1403     ddsd.dwWidth = 128;
1404     ddsd.dwHeight = 128;
1405     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface4, NULL);
1406     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1407
1408     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1409     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer returned %08x\n", hr);
1410     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1411     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface returned %08x\n", hr);
1412     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1413     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to another offscreen plain surface returned %08x\n", hr);
1414     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
1415     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer of different size returned %08x\n", hr);
1416     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
1417     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface of different size returned %08x\n", hr);
1418
1419     IDirectDrawSurface7_Release(surface4);
1420     IDirectDrawSurface7_Release(surface3);
1421     IDirectDrawSurface7_Release(surface2);
1422     IDirectDrawSurface7_Release(surface1);
1423
1424     /* Test DeleteAttachedSurface and automatic detachment of attached surfaces on release */
1425     memset(&ddsd, 0, sizeof(ddsd));
1426     ddsd.dwSize = sizeof(ddsd);
1427     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1428     ddsd.dwWidth = 64;
1429     ddsd.dwHeight = 64;
1430     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1431     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1432     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
1433     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1434     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1435     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1436     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1437
1438     memset(&ddsd2, 0, sizeof(ddsd2));
1439     ddsd2.dwSize = sizeof(ddsd2);
1440     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1441     ddsd2.dwWidth = ddsd.dwWidth;
1442     ddsd2.dwHeight = ddsd.dwHeight;
1443     ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1444     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
1445     U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
1446     U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
1447     U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
1448
1449     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1450     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1451     if (SUCCEEDED(hr))
1452     {
1453         hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surface2, NULL);
1454         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1455         if (SUCCEEDED(hr))
1456         {
1457             hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
1458             ok(hr == DD_OK, "IDirectDrawSurface7_QueryInterface returned %08x\n", hr);
1459             hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
1460             ok(hr == DD_OK, "IDirectDrawSurface7_QueryInterface returned %08x\n", hr);
1461
1462             /* DeleteAttachedSurface when attaching via IDirectDrawSurface7 */
1463             hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1464             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1465             if (SUCCEEDED(hr))
1466             {
1467                 ref = getRefcount((IUnknown *)surface2);
1468                 ok(ref == 2, "Got refcount %d, expected 2\n", ref);
1469                 ref = getRefcount((IUnknown *)surface2v1);
1470                 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1471
1472                 /* Try reattach */
1473                 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1474                 ok(hr == DDERR_SURFACEALREADYATTACHED, "AddAttachedSurface returned %08x\n", hr);
1475
1476                 /* Attachment / detachment on another interface */
1477                 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
1478                 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "AddAttachedSurface returned %08x\n", hr);
1479                 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
1480                 ok(hr == DDERR_SURFACENOTATTACHED, "DeleteAttachedSurface returned %08x\n", hr);
1481
1482                 /* Attaching while already attached to other surface */
1483                 hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface3, NULL);
1484                 ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1485                 if (SUCCEEDED(hr))
1486                 {
1487                     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
1488                     todo_wine ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1489                     if (SUCCEEDED(hr))
1490                     {
1491                         hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
1492                         ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1493                     }
1494                     IDirectDrawSurface7_Release(surface3);
1495                 }
1496
1497                 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
1498                 ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1499                 ref = getRefcount((IUnknown *)surface2);
1500                 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1501                 ref = getRefcount((IUnknown *)surface2v1);
1502                 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1503             }
1504
1505             /* DeleteAttachedSurface when attaching via IDirectDrawSurface */
1506             hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
1507             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1508             if (SUCCEEDED(hr))
1509             {
1510                 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
1511                 ok(hr == DDERR_SURFACENOTATTACHED, "DeleteAttachedSurface returned %08x\n", hr);
1512                 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
1513                 ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1514             }
1515             ref = IDirectDrawSurface7_Release(surface2);
1516             ok(!ref, "Got refcount %d, expected 0\n", ref);
1517             ref = IDirectDrawSurface7_Release(surface1);
1518             ok(!ref, "Got refcount %d, expected 0\n", ref);
1519
1520             /* Automatic detachment on release */
1521             hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
1522             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1523             ref = getRefcount((IUnknown *)surface2v1);
1524             ok(ref == 2, "Got refcount %d, expected 2\n", ref);
1525             ref = IDirectDrawSurface_Release(surface1v1);
1526             ok(!ref, "Got refcount %d, expected 0\n", ref);
1527             ref = getRefcount((IUnknown *)surface2v1);
1528             ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1529             ref = IDirectDrawSurface_Release(surface2v1);
1530             ok(!ref, "Got refcount %d, expected 0\n", ref);
1531         }
1532         else
1533             IDirectDrawSurface7_Release(surface1);
1534     }
1535
1536     hr =IDirectDraw7_SetCooperativeLevel(dd7, NULL, DDSCL_NORMAL);
1537     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1538     IDirectDraw7_Release(dd7);
1539 }
1540
1541 static void AttachmentTest(void)
1542 {
1543     HRESULT hr;
1544     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
1545     DDSURFACEDESC ddsd, ddsd2;
1546     DWORD ref;
1547     DDSCAPS caps = {DDSCAPS_TEXTURE};
1548     BOOL refrast = FALSE;
1549     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1550
1551     memset(&ddsd, 0, sizeof(ddsd));
1552     ddsd.dwSize = sizeof(ddsd);
1553     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1554     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1555     U2(ddsd).dwMipMapCount = 3; /* Will create 128x128, 64x64, 32x32 */
1556     ddsd.dwWidth = 128;
1557     ddsd.dwHeight = 128;
1558     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1559     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1560
1561     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
1562     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1563     hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
1564     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1565
1566     /* Try to attach a 16x16 miplevel - Should not work as far I can see */
1567     memset(&ddsd, 0, sizeof(ddsd));
1568     ddsd.dwSize = sizeof(ddsd);
1569     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1570     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1571     ddsd.dwWidth = 16;
1572     ddsd.dwHeight = 16;
1573     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1574     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1575
1576     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
1577     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 128x128 texture root returned %08x\n", hr);
1578     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
1579     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 texture returned %08x\n", hr);
1580     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
1581     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 32x32 texture mip level returned %08x\n", hr);
1582     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
1583     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 surface returned %08x\n", hr);
1584     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
1585     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 64x64 texture sublevel returned %08x\n", hr);
1586     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
1587     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 64x64 texture sublevel to a 16x16 texture returned %08x\n", hr);
1588
1589     IDirectDrawSurface7_Release(surface4);
1590
1591     memset(&ddsd, 0, sizeof(ddsd));
1592     ddsd.dwSize = sizeof(ddsd);
1593     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1594     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
1595     ddsd.dwWidth = 16;
1596     ddsd.dwHeight = 16;
1597     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1598     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1599
1600     if (SUCCEEDED(IDirectDrawSurface7_AddAttachedSurface(surface1, surface4)))
1601     {
1602         IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface4);
1603         refrast = TRUE;
1604     }
1605
1606     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4); /* Succeeds on refrast */
1607     if (refrast)
1608         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1609     else
1610         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1611     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface4);
1612
1613     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);  /* Succeeds on refrast */
1614     if (refrast)
1615         ok(hr == S_OK, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1616     else
1617         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1618     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface1);
1619
1620     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);  /* Succeeds on refrast */
1621     if (refrast)
1622         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1623     else
1624         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1625     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface4);
1626
1627     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
1628     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 offscreen plain surface returned %08x\n", hr);
1629     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface4, 0, surface3);
1630
1631     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);  /* Succeeds on refrast */
1632     if (refrast)
1633         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 64x64 texture sublevel returned %08x\n", hr);
1634     else
1635         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 64x64 texture sublevel returned %08x\n", hr);
1636     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface2, 0, surface4);
1637
1638     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
1639     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 64x64 texture sublevel to a 16x16 offscreen plain surface returned %08x\n", hr);
1640     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface4, 0, surface2);
1641
1642     IDirectDrawSurface7_Release(surface4);
1643     IDirectDrawSurface7_Release(surface3);
1644     IDirectDrawSurface7_Release(surface2);
1645     IDirectDrawSurface7_Release(surface1);
1646
1647     hr = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1648     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1649
1650     /* Creating a back buffer as-is, is not allowed. No need to perform attachment tests */
1651     memset(&ddsd, 0, sizeof(ddsd));
1652     ddsd.dwSize = sizeof(ddsd);
1653     ddsd.dwFlags = DDSD_CAPS;
1654     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER;
1655     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
1656     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1657     /* This old ddraw version happily creates explicit front buffers */
1658     memset(&ddsd, 0, sizeof(ddsd));
1659     ddsd.dwSize = sizeof(ddsd);
1660     ddsd.dwFlags = DDSD_CAPS;
1661     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER;
1662     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1663     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1664     IDirectDrawSurface_Release(surface1);
1665
1666     /* Try a single primary and two offscreen plain surfaces */
1667     memset(&ddsd, 0, sizeof(ddsd));
1668     ddsd.dwSize = sizeof(ddsd);
1669     ddsd.dwFlags = DDSD_CAPS;
1670     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1671     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1672     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1673
1674     memset(&ddsd, 0, sizeof(ddsd));
1675     ddsd.dwSize = sizeof(ddsd);
1676     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1677     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1678     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1679     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1680     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
1681     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1682
1683     memset(&ddsd, 0, sizeof(ddsd));
1684     ddsd.dwSize = sizeof(ddsd);
1685     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1686     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1687     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1688     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1689     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL);
1690     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1691
1692     /* This one has a different size */
1693     memset(&ddsd, 0, sizeof(ddsd));
1694     ddsd.dwSize = sizeof(ddsd);
1695     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1696     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1697     ddsd.dwWidth = 128;
1698     ddsd.dwHeight = 128;
1699     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1700     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1701
1702     hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1703     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1704        "Attaching an offscreen plain surface to a front buffer returned %08x\n", hr);
1705     if(SUCCEEDED(hr))
1706     {
1707         /* Try the reverse without detaching first */
1708         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
1709         ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
1710         hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
1711         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1712     }
1713     hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
1714     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1715        "Attaching a front buffer to an offscreen plain surface returned %08x\n", hr);
1716     if(SUCCEEDED(hr))
1717     {
1718         /* Try to detach reversed */
1719         hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
1720         ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
1721         /* Now the proper detach */
1722         hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
1723         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1724     }
1725     hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3); /* Fails on refrast */
1726     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1727        "Attaching an offscreen plain surface to another offscreen plain surface returned %08x\n", hr);
1728     if(SUCCEEDED(hr))
1729     {
1730         hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
1731         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1732     }
1733     hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
1734     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer of different size returned %08x\n", hr);
1735     hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
1736     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface of different size returned %08x\n", hr);
1737
1738     IDirectDrawSurface_Release(surface4);
1739     IDirectDrawSurface_Release(surface3);
1740     IDirectDrawSurface_Release(surface2);
1741     IDirectDrawSurface_Release(surface1);
1742
1743     /* Test DeleteAttachedSurface and automatic detachment of attached surfaces on release */
1744     memset(&ddsd, 0, sizeof(ddsd));
1745     ddsd.dwSize = sizeof(ddsd);
1746     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1747     ddsd.dwWidth = 64;
1748     ddsd.dwHeight = 64;
1749     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1750     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1751     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
1752     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16;
1753     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xF800;
1754     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x07E0;
1755     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001F;
1756
1757     memset(&ddsd2, 0, sizeof(ddsd2));
1758     ddsd2.dwSize = sizeof(ddsd2);
1759     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1760     ddsd2.dwWidth = ddsd.dwWidth;
1761     ddsd2.dwHeight = ddsd.dwHeight;
1762     ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1763     ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat);
1764     ddsd2.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
1765     U1(ddsd2.ddpfPixelFormat).dwZBufferBitDepth = 16;
1766     U3(ddsd2.ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
1767
1768     hr = IDirectDraw_CreateSurface(lpDD, (DDSURFACEDESC *)&ddsd, &surface1, NULL);
1769     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1770     if (SUCCEEDED(hr))
1771     {
1772         hr = IDirectDraw_CreateSurface(lpDD, (DDSURFACEDESC *)&ddsd2, &surface2, NULL);
1773         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1774         if (SUCCEEDED(hr))
1775         {
1776             /* DeleteAttachedSurface */
1777             hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1778             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1779             if (SUCCEEDED(hr))
1780             {
1781                 ref = getRefcount((IUnknown *)surface2);
1782                 ok(ref == 2, "Got refcount %d, expected 2\n", ref);
1783
1784                 /* Try reattach */
1785                 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1786                 ok(hr == DDERR_SURFACEALREADYATTACHED, "AddAttachedSurface returned %08x\n", hr);
1787
1788                 /* Attaching while already attached to other surface */
1789                 hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL);
1790                 ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1791                 if (SUCCEEDED(hr))
1792                 {
1793                     hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
1794                     todo_wine ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1795                     if (SUCCEEDED(hr))
1796                     {
1797                         hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
1798                         ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1799                     }
1800                     IDirectDrawSurface_Release(surface3);
1801                 }
1802
1803                 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
1804                 ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1805                 ref = getRefcount((IUnknown *)surface2);
1806                 ok(ref == 1, "Got refcount %d, expected 2\n", ref);
1807             }
1808
1809             /* Automatic detachment on release */
1810             hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1811             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1812             ref = getRefcount((IUnknown *)surface2);
1813             ok(ref == 2, "Got refcount %d, expected 2\n", ref);
1814             ref = IDirectDrawSurface_Release(surface1);
1815             ok(!ref, "Got refcount %d, expected 0\n", ref);
1816             ref = getRefcount((IUnknown *)surface2);
1817             ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1818             ref = IDirectDrawSurface_Release(surface2);
1819             ok(!ref, "Got refcount %d, expected 0\n", ref);
1820         }
1821         else
1822             IDirectDrawSurface_Release(surface1);
1823     }
1824
1825     hr =IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
1826     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1827
1828     DestroyWindow(window);
1829 }
1830
1831 struct compare
1832 {
1833     DWORD width, height;
1834     DWORD caps, caps2;
1835     UINT mips;
1836 };
1837
1838 static HRESULT WINAPI CubeTestPaletteEnum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1839 {
1840     HRESULT hr;
1841
1842     hr = IDirectDrawSurface7_SetPalette(surface, context);
1843     if (desc->dwWidth == 64) /* This is for first mimpmap */
1844         ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "SetPalette returned: %x\n",hr);
1845     else
1846         ok(hr == DD_OK, "SetPalette returned: %x\n",hr);
1847
1848     IDirectDrawSurface7_Release(surface);
1849
1850     return DDENUMRET_OK;
1851 }
1852
1853 static HRESULT WINAPI CubeTestLvl2Enum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1854 {
1855     UINT *mips = context;
1856
1857     (*mips)++;
1858     IDirectDrawSurface7_EnumAttachedSurfaces(surface,
1859                                              context,
1860                                              CubeTestLvl2Enum);
1861
1862     return DDENUMRET_OK;
1863 }
1864
1865 static HRESULT WINAPI CubeTestLvl1Enum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1866 {
1867     UINT mips = 0;
1868     UINT *num = context;
1869     static const struct compare expected[] =
1870     {
1871         {
1872             128, 128,
1873             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1874             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ,
1875             7
1876         },
1877         {
1878             128, 128,
1879             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1880             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ,
1881             7
1882         },
1883         {
1884             128, 128,
1885             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1886             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY,
1887             7
1888         },
1889         {
1890             128, 128,
1891             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1892             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY,
1893             7
1894         },
1895         {
1896             128, 128,
1897             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1898             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX,
1899             7
1900         },
1901         {
1902             64, 64, /* This is the first mipmap */
1903             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1904             DDSCAPS2_MIPMAPSUBLEVEL | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX,
1905             6
1906         },
1907     };
1908
1909     mips = 0;
1910     IDirectDrawSurface7_EnumAttachedSurfaces(surface,
1911                                              &mips,
1912                                              CubeTestLvl2Enum);
1913
1914     ok(desc->dwWidth == expected[*num].width, "Surface width is %d expected %d\n", desc->dwWidth, expected[*num].width);
1915     ok(desc->dwHeight == expected[*num].height, "Surface height is %d expected %d\n", desc->dwHeight, expected[*num].height);
1916     ok(desc->ddsCaps.dwCaps == expected[*num].caps, "Surface caps are %08x expected %08x\n", desc->ddsCaps.dwCaps, expected[*num].caps);
1917     ok(desc->ddsCaps.dwCaps2 == expected[*num].caps2, "Surface caps2 are %08x expected %08x\n", desc->ddsCaps.dwCaps2, expected[*num].caps2);
1918     ok(mips == expected[*num].mips, "Surface has %d mipmaps, expected %d\n", mips, expected[*num].mips);
1919
1920     (*num)++;
1921
1922     IDirectDrawSurface7_Release(surface);
1923
1924     return DDENUMRET_OK;
1925 }
1926
1927 static void CubeMapTest(void)
1928 {
1929     IDirectDraw7 *dd7 = NULL;
1930     IDirectDrawSurface7 *cubemap = NULL;
1931     IDirectDrawPalette *palette = NULL;
1932     DDSURFACEDESC2 ddsd;
1933     HRESULT hr;
1934     PALETTEENTRY Table[256];
1935     int i;
1936     UINT num = 0;
1937     UINT ref;
1938     struct enumstruct ctx;
1939
1940     for(i=0; i<256; i++)
1941     {
1942         Table[i].peRed   = 0xff;
1943         Table[i].peGreen = 0;
1944         Table[i].peBlue  = 0;
1945         Table[i].peFlags = 0;
1946     }
1947
1948     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
1949     ok(hr == DD_OK, "IDirectDraw::QueryInterface returned %08x\n", hr);
1950     if (FAILED(hr)) goto err;
1951
1952     memset(&ddsd, 0, sizeof(ddsd));
1953     ddsd.dwSize = sizeof(ddsd);
1954     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1955     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1956     ddsd.dwWidth = 128;
1957     ddsd.dwHeight = 128;
1958     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1959     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1960
1961     /* D3DFMT_R5G6B5 */
1962     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1963     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1964     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1965     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1966     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1967
1968     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1969     if (FAILED(hr))
1970     {
1971         skip("Can't create cubemap surface\n");
1972         goto err;
1973     }
1974
1975     hr = IDirectDrawSurface7_GetSurfaceDesc(cubemap, &ddsd);
1976     ok(hr == DD_OK, "IDirectDrawSurface7_GetSurfaceDesc returned %08x\n", hr);
1977     ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX),
1978        "Root Caps are %08x\n", ddsd.ddsCaps.dwCaps);
1979     ok(ddsd.ddsCaps.dwCaps2 == (DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP),
1980        "Root Caps2 are %08x\n", ddsd.ddsCaps.dwCaps2);
1981
1982     IDirectDrawSurface7_EnumAttachedSurfaces(cubemap,
1983                                              &num,
1984                                              CubeTestLvl1Enum);
1985     ok(num == 6, "Surface has %d attachments\n", num);
1986     IDirectDrawSurface7_Release(cubemap);
1987
1988     /* What happens if I do not specify any faces? */
1989     memset(&ddsd, 0, sizeof(ddsd));
1990     ddsd.dwSize = sizeof(ddsd);
1991     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1992     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1993     ddsd.dwWidth = 128;
1994     ddsd.dwHeight = 128;
1995     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1996     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP;
1997
1998     /* D3DFMT_R5G6B5 */
1999     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2000     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
2001     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
2002     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
2003     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
2004
2005     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
2006     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7::CreateSurface asking for a cube map without faces returned %08x\n", hr);
2007
2008     /* Cube map faces without a cube map? */
2009     memset(&ddsd, 0, sizeof(ddsd));
2010     ddsd.dwSize = sizeof(ddsd);
2011     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2012     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
2013     ddsd.dwWidth = 128;
2014     ddsd.dwHeight = 128;
2015     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
2016     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP_ALLFACES;
2017
2018     /* D3DFMT_R5G6B5 */
2019     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2020     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
2021     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
2022     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
2023     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
2024
2025     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
2026     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7::CreateSurface returned %08x\n", hr);
2027
2028     memset(&ddsd, 0, sizeof(ddsd));
2029     ddsd.dwSize = sizeof(ddsd);
2030     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2031     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
2032     ddsd.dwWidth = 128;
2033     ddsd.dwHeight = 128;
2034     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
2035     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP_POSITIVEX;
2036
2037     /* D3DFMT_R5G6B5 */
2038     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2039     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
2040     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
2041     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
2042     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
2043
2044     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
2045     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7::CreateSurface returned %08x\n", hr);
2046
2047     memset(&ddsd, 0, sizeof(ddsd));
2048     ddsd.dwSize = sizeof(ddsd);
2049     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2050     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
2051     ddsd.dwWidth = 128;
2052     ddsd.dwHeight = 128;
2053     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
2054     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2055
2056     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2057     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2058
2059     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
2060     if (FAILED(hr))
2061     {
2062         skip("Can't create palletized cubemap surface\n");
2063         goto err;
2064     }
2065
2066     hr = IDirectDraw7_CreatePalette(dd7, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL);
2067     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
2068
2069     hr = IDirectDrawSurface7_EnumAttachedSurfaces(cubemap, palette, CubeTestPaletteEnum);
2070     ok(hr == DD_OK, "EnumAttachedSurfaces failed\n");
2071
2072     ref = getRefcount((IUnknown *) palette);
2073     ok(ref == 6, "Refcount is %u, expected 1\n", ref);
2074
2075     IDirectDrawSurface7_Release(cubemap);
2076
2077     ref = getRefcount((IUnknown *) palette);
2078     todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
2079
2080     IDirectDrawPalette_Release(palette);
2081
2082     /* Make sure everything is cleaned up properly. Use the enumSurfaces test infrastructure */
2083     memset(&ctx, 0, sizeof(ctx));
2084     memset(&ddsd, 0, sizeof(ddsd));
2085     ddsd.dwSize = sizeof(DDSURFACEDESC);
2086     hr = IDirectDraw_EnumSurfaces(lpDD, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, (DDSURFACEDESC *) &ddsd, (void *) &ctx, enumCB);
2087     ok(hr == DD_OK, "IDirectDraw_EnumSurfaces returned %08x\n", hr);
2088     ok(ctx.count == 0, "%d surfaces enumerated, expected 0\n", ctx.count);
2089
2090     err:
2091     if (dd7) IDirectDraw7_Release(dd7);
2092 }
2093
2094 static void test_lockrect_invalid(void)
2095 {
2096     unsigned int i, j;
2097
2098     RECT valid[] = {
2099         {60, 60, 68, 68},
2100         {60, 60, 60, 68},
2101         {60, 60, 68, 60},
2102         {120, 60, 128, 68},
2103         {60, 120, 68, 128},
2104     };
2105
2106     RECT invalid[] = {
2107         {68, 60, 60, 68},       /* left > right */
2108         {60, 68, 68, 60},       /* top > bottom */
2109         {-8, 60,  0, 68},       /* left < surface */
2110         {60, -8, 68,  0},       /* top < surface */
2111         {-16, 60, -8, 68},      /* right < surface */
2112         {60, -16, 68, -8},      /* bottom < surface */
2113         {60, 60, 136, 68},      /* right > surface */
2114         {60, 60, 68, 136},      /* bottom > surface */
2115         {136, 60, 144, 68},     /* left > surface */
2116         {60, 136, 68, 144},     /* top > surface */
2117     };
2118
2119     const DWORD dds_caps[] = {
2120         DDSCAPS_OFFSCREENPLAIN
2121     };
2122
2123     for (j = 0; j < (sizeof(dds_caps) / sizeof(*dds_caps)); ++j)
2124     {
2125         IDirectDrawSurface *surface = 0;
2126         DDSURFACEDESC surface_desc = {0};
2127         DDSURFACEDESC locked_desc = {0};
2128         HRESULT hr;
2129
2130         surface_desc.dwSize = sizeof(surface_desc);
2131         surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
2132         surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2133         surface_desc.ddsCaps.dwCaps = dds_caps[j];
2134         surface_desc.dwWidth = 128;
2135         surface_desc.dwHeight = 128;
2136         surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
2137         U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
2138         U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xFF0000;
2139         U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00FF00;
2140         U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000FF;
2141
2142         hr = IDirectDraw_CreateSurface(lpDD, &surface_desc, &surface, NULL);
2143         ok(SUCCEEDED(hr), "CreateSurface failed (0x%08x)\n", hr);
2144         if (FAILED(hr))
2145         {
2146             skip("failed to create surface\n");
2147             continue;
2148         }
2149
2150         hr = IDirectDrawSurface_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
2151         ok(hr == DDERR_INVALIDPARAMS, "Lock returned 0x%08x for NULL DDSURFACEDESC,"
2152                 " expected DDERR_INVALIDPARAMS (0x%08x)\n", hr, DDERR_INVALIDPARAMS);
2153
2154         for (i = 0; i < (sizeof(valid) / sizeof(*valid)); ++i)
2155         {
2156             RECT *rect = &valid[i];
2157
2158             memset(&locked_desc, 0, sizeof(locked_desc));
2159             locked_desc.dwSize = sizeof(locked_desc);
2160
2161             hr = IDirectDrawSurface_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
2162             ok(SUCCEEDED(hr), "Lock failed (0x%08x) for rect [%d, %d]->[%d, %d]\n",
2163                     hr, rect->left, rect->top, rect->right, rect->bottom);
2164
2165             hr = IDirectDrawSurface_Unlock(surface, NULL);
2166             ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2167         }
2168
2169         for (i = 0; i < (sizeof(invalid) / sizeof(*invalid)); ++i)
2170         {
2171             RECT *rect = &invalid[i];
2172
2173             memset(&locked_desc, 1, sizeof(locked_desc));
2174             locked_desc.dwSize = sizeof(locked_desc);
2175
2176             hr = IDirectDrawSurface_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
2177             ok(hr == DDERR_INVALIDPARAMS, "Lock returned 0x%08x for rect [%d, %d]->[%d, %d]"
2178                     ", expected DDERR_INVALIDPARAMS (0x%08x)\n", hr, rect->left, rect->top,
2179                     rect->right, rect->bottom, DDERR_INVALIDPARAMS);
2180             ok(!locked_desc.lpSurface, "IDirectDrawSurface_Lock did not set lpSurface in the surface desc to zero.\n");
2181         }
2182
2183         hr = IDirectDrawSurface_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
2184         ok(hr == DD_OK, "IDirectDrawSurface_Lock(rect = NULL) failed (0x%08x)\n", hr);
2185         hr = IDirectDrawSurface_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
2186         ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned 0x%08x\n", hr);
2187         if(SUCCEEDED(hr)) {
2188             hr = IDirectDrawSurface_Unlock(surface, NULL);
2189             ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2190         }
2191         hr = IDirectDrawSurface_Unlock(surface, NULL);
2192         ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2193
2194         memset(&locked_desc, 0, sizeof(locked_desc));
2195         locked_desc.dwSize = sizeof(locked_desc);
2196         hr = IDirectDrawSurface_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
2197         ok(hr == DD_OK, "IDirectDrawSurface_Lock(rect = [%d, %d]->[%d, %d]) failed (0x%08x)\n",
2198            valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
2199         hr = IDirectDrawSurface_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
2200         ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = [%d, %d]->[%d, %d]) failed (0x%08x)\n",
2201            valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
2202
2203         /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
2204          * Afterwards unlocking the surface fails(NULL rectangle, and both locked rectangles
2205          */
2206
2207         hr = IDirectDrawSurface_Unlock(surface, NULL);
2208         ok(hr == DD_OK, "Unlock returned (0x%08x)\n", hr);
2209
2210         IDirectDrawSurface_Release(surface);
2211     }
2212 }
2213
2214 static void CompressedTest(void)
2215 {
2216     HRESULT hr;
2217     IDirectDrawSurface7 *surface;
2218     DDSURFACEDESC2 ddsd, ddsd2;
2219     IDirectDraw7 *dd7 = NULL;
2220     RECT r = { 0, 0, 128, 128 };
2221     RECT r2 = { 32, 32, 64, 64 };
2222
2223     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
2224     ok(hr == DD_OK, "IDirectDraw::QueryInterface returned %08x\n", hr);
2225
2226     memset(&ddsd, 0, sizeof(ddsd));
2227     ddsd.dwSize = sizeof(ddsd);
2228     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2229     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
2230     ddsd.dwWidth = 128;
2231     ddsd.dwHeight = 128;
2232     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
2233     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
2234     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
2235
2236     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2237     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2238     if (FAILED(hr))
2239     {
2240         skip("failed to create surface\n");
2241         return;
2242     }
2243
2244     memset(&ddsd2, 0, sizeof(ddsd2));
2245     ddsd2.dwSize = sizeof(ddsd2);
2246     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2247     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2248     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2249
2250     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2251        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2252     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2253     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2254     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2255        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2256     ok(U1(ddsd2).dwLinearSize == 8192, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2257     ok(ddsd2.ddsCaps.dwCaps2 == 0, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
2258     IDirectDrawSurface7_Release(surface);
2259
2260     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
2261     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2262     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2263     if (FAILED(hr))
2264     {
2265         skip("failed to create surface\n");
2266         return;
2267     }
2268
2269     memset(&ddsd2, 0, sizeof(ddsd2));
2270     ddsd2.dwSize = sizeof(ddsd2);
2271     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2272     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2273     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2274
2275     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2276        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2277     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2278     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2279     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2280        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2281     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2282     IDirectDrawSurface7_Release(surface);
2283
2284     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
2285     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2286     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2287     if (FAILED(hr))
2288     {
2289         skip("failed to create surface\n");
2290         return;
2291     }
2292
2293     memset(&ddsd2, 0, sizeof(ddsd2));
2294     ddsd2.dwSize = sizeof(ddsd2);
2295     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2296     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2297     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2298
2299     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2300        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2301     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2302     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2303     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2304        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2305     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2306     ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2307
2308     memset(&ddsd2, 0, sizeof(ddsd2));
2309     ddsd2.dwSize = sizeof(ddsd2);
2310     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2311
2312     /* Show that the description is not changed when locking the surface. What is really interesting
2313      * about this is that DDSD_LPSURFACE isn't set.
2314      */
2315     hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2316     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2317
2318     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2319        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2320     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2321     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2322     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2323        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2324     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2325     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2326
2327     hr = IDirectDrawSurface7_Unlock(surface, NULL);
2328     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2329
2330     /* Now what about a locking rect?  */
2331     hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2332     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2333
2334     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2335        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2336     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2337     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2338     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2339        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2340     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2341     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2342
2343     hr = IDirectDrawSurface7_Unlock(surface, &r);
2344     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2345
2346     /* Now what about a different locking offset? */
2347     hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2348     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2349
2350     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2351        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2352     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2353     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2354     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2355        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2356     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2357     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2358
2359     hr = IDirectDrawSurface7_Unlock(surface, &r2);
2360     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2361     IDirectDrawSurface7_Release(surface);
2362
2363     /* Try this with video memory. A kind of surprise. It still has the LINEARSIZE flag set,
2364      * but seems to have a pitch instead.
2365      */
2366     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
2367     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
2368
2369     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2370     ok(hr == DD_OK || hr == DDERR_NOTEXTUREHW || hr == DDERR_INVALIDPARAMS ||
2371        broken(hr == DDERR_NODIRECTDRAWHW), "CreateSurface returned %08x\n", hr);
2372
2373     /* Not supported everywhere */
2374     if(SUCCEEDED(hr))
2375     {
2376         memset(&ddsd2, 0, sizeof(ddsd2));
2377         ddsd2.dwSize = sizeof(ddsd2);
2378         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2379         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2380         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2381
2382         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2383         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2384         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2385         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2386         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2387         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2388         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2389         ok(ddsd2.ddsCaps.dwCaps2 == 0, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
2390         IDirectDrawSurface7_Release(surface);
2391
2392         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
2393         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2394         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2395
2396         memset(&ddsd2, 0, sizeof(ddsd2));
2397         ddsd2.dwSize = sizeof(ddsd2);
2398         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2399         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2400         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2401
2402         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2403         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2404         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2405         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2406         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2407         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2408         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2409         IDirectDrawSurface7_Release(surface);
2410
2411         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
2412         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2413         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2414
2415         memset(&ddsd2, 0, sizeof(ddsd2));
2416         ddsd2.dwSize = sizeof(ddsd2);
2417         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2418         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2419         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2420
2421         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2422         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2423         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2424         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2425         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2426         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2427         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2428         ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2429
2430         memset(&ddsd2, 0, sizeof(ddsd2));
2431         ddsd2.dwSize = sizeof(ddsd2);
2432         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2433
2434         /* Show that the description is not changed when locking the surface. What is really interesting
2435         * about this is that DDSD_LPSURFACE isn't set.
2436         */
2437         hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2438         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2439
2440         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2441         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2442         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2443         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2444         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2445         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2446         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2447         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2448
2449         hr = IDirectDrawSurface7_Unlock(surface, NULL);
2450         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2451
2452         /* Now what about a locking rect?  */
2453         hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2454         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2455
2456         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2457         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2458         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2459         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2460         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2461         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2462         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2463         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2464
2465         hr = IDirectDrawSurface7_Unlock(surface, &r);
2466         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2467
2468         /* Now what about a different locking offset? */
2469         hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2470         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2471
2472         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2473         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2474         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2475         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2476         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2477         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2478         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2479         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2480
2481         hr = IDirectDrawSurface7_Unlock(surface, &r2);
2482         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2483
2484         IDirectDrawSurface7_Release(surface);
2485     }
2486     else
2487     {
2488         skip("Hardware DXTN textures not supported\n");
2489     }
2490
2491     /* What happens to managed textures? Interestingly, Windows reports them as being in system
2492      * memory. The linear size fits again.
2493      */
2494     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2495     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
2496     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
2497
2498     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2499     ok(hr == DD_OK || hr == DDERR_NOTEXTUREHW, "CreateSurface returned %08x\n", hr);
2500
2501     /* Not supported everywhere */
2502     if(SUCCEEDED(hr))
2503     {
2504         memset(&ddsd2, 0, sizeof(ddsd2));
2505         ddsd2.dwSize = sizeof(ddsd2);
2506         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2507         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2508         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2509
2510         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2511         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2512         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2513         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2514         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2515         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2516         ok(U1(ddsd2).dwLinearSize == 8192, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2517         ok(ddsd2.ddsCaps.dwCaps2 == DDSCAPS2_TEXTUREMANAGE, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
2518         IDirectDrawSurface7_Release(surface);
2519
2520         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
2521         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2522         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2523
2524         memset(&ddsd2, 0, sizeof(ddsd2));
2525         ddsd2.dwSize = sizeof(ddsd2);
2526         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2527         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2528         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2529
2530         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2531         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2532         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2533         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2534         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2535         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2536         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2537         IDirectDrawSurface7_Release(surface);
2538
2539         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
2540         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2541         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2542
2543         memset(&ddsd2, 0, sizeof(ddsd2));
2544         ddsd2.dwSize = sizeof(ddsd2);
2545         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2546         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2547         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2548
2549         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2550         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2551         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2552         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2553         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2554         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2555         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2556         ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2557
2558         memset(&ddsd2, 0, sizeof(ddsd2));
2559         ddsd2.dwSize = sizeof(ddsd2);
2560         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2561
2562         /* Show that the description is not changed when locking the surface. What is really interesting
2563         * about this is that DDSD_LPSURFACE isn't set.
2564         */
2565         hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2566         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2567
2568         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2569         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2570         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2571         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2572         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2573         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2574         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2575         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2576
2577         hr = IDirectDrawSurface7_Unlock(surface, NULL);
2578         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2579
2580         /* Now what about a locking rect?  */
2581         hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2582         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2583
2584         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2585         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2586         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2587         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2588         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2589         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2590         ok(U1(ddsd2).dwLinearSize == 16384, "\"Linear\" size is %d\n", U1(ddsd2).dwLinearSize);
2591         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2592
2593         hr = IDirectDrawSurface7_Unlock(surface, &r);
2594         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2595
2596         /* Now what about a different locking offset? */
2597         hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2598         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2599
2600         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2601         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2602         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2603         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2604         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2605         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2606         ok(U1(ddsd2).dwLinearSize == 16384, "\"Linear\" size is %d\n", U1(ddsd2).dwLinearSize);
2607         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2608
2609         hr = IDirectDrawSurface7_Unlock(surface, &r2);
2610         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2611
2612         IDirectDrawSurface7_Release(surface);
2613     }
2614     else
2615     {
2616         skip("Hardware DXTN textures not supported\n");
2617     }
2618
2619     IDirectDraw7_Release(dd7);
2620 }
2621
2622 static void SizeTest(void)
2623 {
2624     LPDIRECTDRAWSURFACE dsurface = NULL;
2625     DDSURFACEDESC desc;
2626     HRESULT ret;
2627     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2628
2629     /* Create an offscreen surface surface without a size */
2630     ZeroMemory(&desc, sizeof(desc));
2631     desc.dwSize = sizeof(desc);
2632     desc.dwFlags = DDSD_CAPS;
2633     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2634     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2635     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without a size info returned %08x (dsurface=%p)\n", ret, dsurface);
2636     if(dsurface)
2637     {
2638         trace("Surface at %p\n", dsurface);
2639         IDirectDrawSurface_Release(dsurface);
2640         dsurface = NULL;
2641     }
2642
2643     /* Create an offscreen surface surface with only a width parameter */
2644     ZeroMemory(&desc, sizeof(desc));
2645     desc.dwSize = sizeof(desc);
2646     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH;
2647     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2648     desc.dwWidth = 128;
2649     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2650     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without height info returned %08x\n", ret);
2651     if(dsurface)
2652     {
2653         IDirectDrawSurface_Release(dsurface);
2654         dsurface = NULL;
2655     }
2656
2657     /* Create an offscreen surface surface with only a height parameter */
2658     ZeroMemory(&desc, sizeof(desc));
2659     desc.dwSize = sizeof(desc);
2660     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT;
2661     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2662     desc.dwHeight = 128;
2663     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2664     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without width info returned %08x\n", ret);
2665     if(dsurface)
2666     {
2667         IDirectDrawSurface_Release(dsurface);
2668         dsurface = NULL;
2669     }
2670
2671     /* Test 0 height. */
2672     memset(&desc, 0, sizeof(desc));
2673     desc.dwSize = sizeof(desc);
2674     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2675     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
2676     desc.dwWidth = 1;
2677     desc.dwHeight = 0;
2678     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2679     ok(ret == DDERR_INVALIDPARAMS, "Creating a 0 height surface returned %#x, expected DDERR_INVALIDPARAMS.\n", ret);
2680     if (SUCCEEDED(ret)) IDirectDrawSurface_Release(dsurface);
2681     dsurface = NULL;
2682
2683     /* Test 0 width. */
2684     memset(&desc, 0, sizeof(desc));
2685     desc.dwSize = sizeof(desc);
2686     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2687     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
2688     desc.dwWidth = 0;
2689     desc.dwHeight = 1;
2690     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2691     ok(ret == DDERR_INVALIDPARAMS, "Creating a 0 width surface returned %#x, expected DDERR_INVALIDPARAMS.\n", ret);
2692     if (SUCCEEDED(ret)) IDirectDrawSurface_Release(dsurface);
2693     dsurface = NULL;
2694
2695     /* Sanity check */
2696     ZeroMemory(&desc, sizeof(desc));
2697     desc.dwSize = sizeof(desc);
2698     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2699     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2700     desc.dwHeight = 128;
2701     desc.dwWidth = 128;
2702     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2703     ok(ret == DD_OK, "Creating an offscreen plain surface with width and height info returned %08x\n", ret);
2704     if(dsurface)
2705     {
2706         IDirectDrawSurface_Release(dsurface);
2707         dsurface = NULL;
2708     }
2709
2710     /* Test a primary surface size */
2711     ret = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_NORMAL);
2712     ok(ret == DD_OK, "SetCooperativeLevel failed with %08x\n", ret);
2713
2714     ZeroMemory(&desc, sizeof(desc));
2715     desc.dwSize = sizeof(desc);
2716     desc.dwFlags = DDSD_CAPS;
2717     desc.ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE;
2718     desc.dwHeight = 128; /* Keep them set to  check what happens */
2719     desc.dwWidth = 128; /* Keep them set to  check what happens */
2720     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2721     ok(ret == DD_OK, "Creating a primary surface without width and height info returned %08x\n", ret);
2722     if(dsurface)
2723     {
2724         ret = IDirectDrawSurface_GetSurfaceDesc(dsurface, &desc);
2725         ok(ret == DD_OK, "GetSurfaceDesc returned %x\n", ret);
2726
2727         IDirectDrawSurface_Release(dsurface);
2728         dsurface = NULL;
2729
2730         ok(desc.dwFlags & DDSD_WIDTH, "Primary surface doesn't have width set\n");
2731         ok(desc.dwFlags & DDSD_HEIGHT, "Primary surface doesn't have height set\n");
2732         ok(desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Surface width differs from screen width\n");
2733         ok(desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Surface height differs from screen height\n");
2734     }
2735     ret = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
2736     ok(ret == DD_OK, "SetCooperativeLevel failed with %08x\n", ret);
2737 }
2738
2739 static void PrivateDataTest(void)
2740 {
2741     HRESULT hr;
2742     IDirectDrawSurface7 *surface7 = NULL;
2743     IDirectDrawSurface *surface = NULL;
2744     DDSURFACEDESC desc;
2745     ULONG ref, ref2;
2746     IUnknown *ptr;
2747     DWORD size = sizeof(IUnknown *);
2748
2749     ZeroMemory(&desc, sizeof(desc));
2750     desc.dwSize = sizeof(desc);
2751     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2752     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2753     desc.dwHeight = 128;
2754     desc.dwWidth = 128;
2755     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface, NULL);
2756     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2757     if(!surface)
2758     {
2759         return;
2760     }
2761     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **) &surface7);
2762     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed with %08x\n", hr);
2763     if(!surface7)
2764     {
2765         IDirectDrawSurface_Release(surface);
2766         return;
2767     }
2768
2769     /* This fails */
2770     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, 0, DDSPD_IUNKNOWNPOINTER);
2771     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2772     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, 5, DDSPD_IUNKNOWNPOINTER);
2773     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2774     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, sizeof(IUnknown *) * 2, DDSPD_IUNKNOWNPOINTER);
2775     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2776
2777     ref = getref((IUnknown *) lpDD);
2778     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2779     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2780     ref2 = getref((IUnknown *) lpDD);
2781     ok(ref2 == ref + 1, "Object reference is %d, expected %d\n", ref2, ref + 1);
2782     hr = IDirectDrawSurface7_FreePrivateData(surface7, &IID_IDirectDrawSurface7);
2783     ok(SUCCEEDED(hr), "IDirectDrawSurface7_FreePrivateData returned %#x.\n", hr);
2784     ref2 = getref((IUnknown *) lpDD);
2785     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2786
2787     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2788     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2789     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, surface7, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2790     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2791     ref2 = getref((IUnknown *) lpDD);
2792     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2793
2794     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2795     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2796     hr = IDirectDrawSurface7_GetPrivateData(surface7, &IID_IDirectDrawSurface7, &ptr, &size);
2797     ok(hr == DD_OK, "IDirectDrawSurface7_GetPrivateData failed with %08x\n", hr);
2798     ref2 = getref((IUnknown *) lpDD);
2799     /* Object is NOT being addrefed */
2800     ok(ptr == (IUnknown *) lpDD, "Returned interface pointer is %p, expected %p\n", ptr, lpDD);
2801     ok(ref2 == ref + 1, "Object reference is %d, expected %d. ptr at %p, orig at %p\n", ref2, ref + 1, ptr, lpDD);
2802
2803     IDirectDrawSurface_Release(surface);
2804     IDirectDrawSurface7_Release(surface7);
2805
2806     /* Destroying the surface frees the held reference */
2807     ref2 = getref((IUnknown *) lpDD);
2808     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2809 }
2810
2811 static void BltParamTest(void)
2812 {
2813     IDirectDrawSurface *surface1 = NULL, *surface2 = NULL;
2814     DDSURFACEDESC desc;
2815     HRESULT hr;
2816     DDBLTFX BltFx;
2817     RECT valid = {10, 10, 20, 20};
2818     RECT invalid1 = {20, 10, 10, 20};
2819     RECT invalid2 = {20, 20, 20, 20};
2820     RECT invalid3 = {-1, -1, 20, 20};
2821     RECT invalid4 = {60, 60, 70, 70};
2822
2823     memset(&desc, 0, sizeof(desc));
2824     desc.dwSize = sizeof(desc);
2825     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2826     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2827     desc.dwHeight = 128;
2828     desc.dwWidth = 128;
2829     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface1, NULL);
2830     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2831
2832     desc.dwHeight = 64;
2833     desc.dwWidth = 64;
2834     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface2, NULL);
2835     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2836
2837     if(0)
2838     {
2839         /* This crashes */
2840         hr = IDirectDrawSurface_BltFast(surface1, 0, 0, NULL, NULL, 0);
2841         ok(hr == DD_OK, "BltFast from NULL surface returned %08x\n", hr);
2842     }
2843     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface2, NULL, 0);
2844     ok(hr == DD_OK, "BltFast from smaller to bigger surface returned %08x\n", hr);
2845     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, NULL, 0);
2846     ok(hr == DDERR_INVALIDRECT, "BltFast from bigger to smaller surface returned %08x\n", hr);
2847     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &valid, 0);
2848     ok(hr == DD_OK, "BltFast from bigger to smaller surface using a valid rectangle returned %08x\n", hr);
2849     hr = IDirectDrawSurface_BltFast(surface2, 60, 60, surface1, &valid, 0);
2850     ok(hr == DDERR_INVALIDRECT, "BltFast with a rectangle resulting in an off-surface write returned %08x\n", hr);
2851     hr = IDirectDrawSurface_BltFast(surface1, 90, 90, surface2, NULL, 0);
2852     ok(hr == DDERR_INVALIDRECT, "BltFast with a rectangle resulting in an off-surface write returned %08x\n", hr);
2853
2854     hr = IDirectDrawSurface_BltFast(surface1, -10, 0, surface2, NULL, 0);
2855     ok(hr == DDERR_INVALIDRECT, "BltFast with an offset resulting in an off-surface write returned %08x\n", hr);
2856     hr = IDirectDrawSurface_BltFast(surface1, 0, -10, surface2, NULL, 0);
2857     ok(hr == DDERR_INVALIDRECT, "BltFast with an offset resulting in an off-surface write returned %08x\n", hr);
2858     hr = IDirectDrawSurface_BltFast(surface2, 20, 20, surface1, &valid, 0);
2859     ok(hr == DD_OK, "BltFast from bigger to smaller surface using a valid rectangle and offset returned %08x\n", hr);
2860
2861     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid1, 0);
2862     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 1 returned %08x\n", hr);
2863     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid2, 0);
2864     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 2 returned %08x\n", hr);
2865     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid3, 0);
2866     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 3 returned %08x\n", hr);
2867     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface2, &invalid4, 0);
2868     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 3 returned %08x\n", hr);
2869     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface1, NULL, 0);
2870     ok(hr == DD_OK, "BltFast blitting a surface onto itself returned %08x\n", hr);
2871
2872     /* Blt(non-fast) tests */
2873     memset(&BltFx, 0, sizeof(BltFx));
2874     BltFx.dwSize = sizeof(BltFx);
2875     U5(BltFx).dwFillColor = 0xaabbccdd;
2876
2877     hr = IDirectDrawSurface_Blt(surface1, &valid, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2878     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a valid rectangle for color fill returned %08x\n", hr);
2879     hr = IDirectDrawSurface_Blt(surface1, &valid, NULL, &invalid3, DDBLT_COLORFILL, &BltFx);
2880     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a invalid, unused rectangle returned %08x\n", hr);
2881     hr = IDirectDrawSurface_Blt(surface2, &invalid1, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2882     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2883     hr = IDirectDrawSurface_Blt(surface2, &invalid2, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2884     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2885     hr = IDirectDrawSurface_Blt(surface2, &invalid3, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2886     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2887     hr = IDirectDrawSurface_Blt(surface2, &invalid4, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2888     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2889
2890     /* Valid on surface 1 */
2891     hr = IDirectDrawSurface_Blt(surface1, &invalid4, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2892     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a subrectangle fill returned %08x\n", hr);
2893
2894     /* Works - stretched blit */
2895     hr = IDirectDrawSurface_Blt(surface1, NULL, surface2, NULL, 0, NULL);
2896     ok(hr == DD_OK, "IDirectDrawSurface_Blt from a smaller to a bigger surface returned %08x\n", hr);
2897     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, NULL, 0, NULL);
2898     ok(hr == DD_OK, "IDirectDrawSurface_Blt from a bigger to a smaller surface %08x\n", hr);
2899
2900     /* Invalid dest rects in sourced blits */
2901     hr = IDirectDrawSurface_Blt(surface2, &invalid1, surface1, NULL, 0, NULL);
2902     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2903     hr = IDirectDrawSurface_Blt(surface2, &invalid2, surface1, NULL, 0, NULL);
2904     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2905     hr = IDirectDrawSurface_Blt(surface2, &invalid3, surface1, NULL, 0, NULL);
2906     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2907     hr = IDirectDrawSurface_Blt(surface2, &invalid4, surface1, NULL, 0, NULL);
2908     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2909
2910     /* Invalid src rects */
2911     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid1, 0, NULL);
2912     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2913     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid2, 0, NULL);
2914     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2915     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid3, 0, NULL);
2916     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2917     hr = IDirectDrawSurface_Blt(surface1, NULL, surface2, &invalid4, 0, NULL);
2918     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2919
2920     IDirectDrawSurface_Release(surface1);
2921     IDirectDrawSurface_Release(surface2);
2922 }
2923
2924 static void PaletteTest(void)
2925 {
2926     HRESULT hr;
2927     LPDIRECTDRAWSURFACE lpSurf = NULL;
2928     IDirectDrawSurface *backbuffer = NULL;
2929     DDSCAPS ddscaps;
2930     DDSURFACEDESC ddsd;
2931     IDirectDrawPalette *palette = NULL;
2932     PALETTEENTRY Table[256];
2933     PALETTEENTRY palEntries[256];
2934     int i;
2935
2936     for(i=0; i<256; i++)
2937     {
2938         Table[i].peRed   = 0xff;
2939         Table[i].peGreen = 0;
2940         Table[i].peBlue  = 0;
2941         Table[i].peFlags = 0;
2942     }
2943
2944     /* Create a 8bit palette without DDPCAPS_ALLOW256 set */
2945     hr = IDirectDraw_CreatePalette(lpDD, DDPCAPS_8BIT, Table, &palette, NULL);
2946     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
2947     if (FAILED(hr)) goto err;
2948     /* Read back the palette and verify the entries. Without DDPCAPS_ALLOW256 set
2949     /  entry 0 and 255 should have been overwritten with black and white */
2950     IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2951     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2952     if(hr == DD_OK)
2953     {
2954         ok((palEntries[0].peRed == 0) && (palEntries[0].peGreen == 0) && (palEntries[0].peBlue == 0),
2955            "Palette entry 0 of a palette without DDPCAPS_ALLOW256 set should be (0,0,0) but it is (%d,%d,%d)\n",
2956            palEntries[0].peRed, palEntries[0].peGreen, palEntries[0].peBlue);
2957         ok((palEntries[255].peRed == 255) && (palEntries[255].peGreen == 255) && (palEntries[255].peBlue == 255),
2958            "Palette entry 255 of a palette without DDPCAPS_ALLOW256 set should be (255,255,255) but it is (%d,%d,%d)\n",
2959            palEntries[255].peRed, palEntries[255].peGreen, palEntries[255].peBlue);
2960
2961         /* Entry 1-254 should contain red */
2962         for(i=1; i<255; i++)
2963             ok((palEntries[i].peRed == 255) && (palEntries[i].peGreen == 0) && (palEntries[i].peBlue == 0),
2964                "Palette entry %d should have contained (255,0,0) but was set to %d,%d,%d)\n",
2965                i, palEntries[i].peRed, palEntries[i].peGreen, palEntries[i].peBlue);
2966     }
2967
2968     /* CreatePalette without DDPCAPS_ALLOW256 ignores entry 0 and 255,
2969     /  now check we are able to update the entries afterwards. */
2970     IDirectDrawPalette_SetEntries(palette , 0, 0, 256, &Table[0]);
2971     ok(hr == DD_OK, "SetEntries failed with %08x\n", hr);
2972     IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2973     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2974     if(hr == DD_OK)
2975     {
2976         ok((palEntries[0].peRed == 0) && (palEntries[0].peGreen == 0) && (palEntries[0].peBlue == 0),
2977            "Palette entry 0 should have been set to (0,0,0) but it contains (%d,%d,%d)\n",
2978            palEntries[0].peRed, palEntries[0].peGreen, palEntries[0].peBlue);
2979         ok((palEntries[255].peRed == 255) && (palEntries[255].peGreen == 255) && (palEntries[255].peBlue == 255),
2980            "Palette entry 255 should have been set to (255,255,255) but it contains (%d,%d,%d)\n",
2981            palEntries[255].peRed, palEntries[255].peGreen, palEntries[255].peBlue);
2982     }
2983     IDirectDrawPalette_Release(palette);
2984
2985     /* Create a 8bit palette with DDPCAPS_ALLOW256 set */
2986     hr = IDirectDraw_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL);
2987     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
2988     if (FAILED(hr)) goto err;
2989
2990     IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2991     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2992     if(hr == DD_OK)
2993     {
2994         /* All entries should contain red */
2995         for(i=0; i<256; i++)
2996             ok((palEntries[i].peRed == 255) && (palEntries[i].peGreen == 0) && (palEntries[i].peBlue == 0),
2997                "Palette entry %d should have contained (255,0,0) but was set to %d,%d,%d)\n",
2998                i, palEntries[i].peRed, palEntries[i].peGreen, palEntries[i].peBlue);
2999     }
3000
3001     /* Try to set palette to a non-palettized surface */
3002     ddsd.dwSize = sizeof(ddsd);
3003     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
3004     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3005     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3006     ddsd.dwWidth = 800;
3007     ddsd.dwHeight = 600;
3008     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
3009     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
3010     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
3011     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
3012     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
3013     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSurf, NULL);
3014     ok(hr==DD_OK, "CreateSurface returned: %x\n",hr);
3015     if (FAILED(hr))
3016     {
3017         skip("failed to create surface\n");
3018         goto err;
3019     }
3020
3021     hr = IDirectDrawSurface_SetPalette(lpSurf, palette);
3022     ok(hr == DDERR_INVALIDPIXELFORMAT, "CreateSurface returned: %x\n",hr);
3023
3024     IDirectDrawPalette_Release(palette);
3025     palette = NULL;
3026
3027     hr = IDirectDrawSurface_GetPalette(lpSurf, &palette);
3028     ok(hr == DDERR_NOPALETTEATTACHED, "CreateSurface returned: %x\n",hr);
3029
3030     err:
3031
3032     if (lpSurf) IDirectDrawSurface_Release(lpSurf);
3033     if (palette) IDirectDrawPalette_Release(palette);
3034
3035     hr = IDirectDraw_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL);
3036     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
3037
3038     ddsd.dwSize = sizeof(ddsd);
3039     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
3040     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_BACKBUFFERCOUNT;
3041     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3042     ddsd.dwWidth = 64;
3043     ddsd.dwHeight = 64;
3044     ddsd.dwBackBufferCount = 1;
3045     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
3046     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
3047
3048     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSurf, NULL);
3049     ok(hr==DD_OK, "CreateSurface returned: %x\n",hr);
3050     if (FAILED(hr))
3051     {
3052         skip("failed to create surface\n");
3053         return;
3054     }
3055
3056     ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
3057     hr = IDirectDrawSurface_GetAttachedSurface(lpSurf, &ddscaps, &backbuffer);
3058     ok(hr == DD_OK, "GetAttachedSurface returned: %x\n",hr);
3059
3060     hr = IDirectDrawSurface_SetPalette(backbuffer, palette);
3061     ok(hr == DD_OK, "SetPalette returned: %x\n",hr);
3062
3063     IDirectDrawPalette_Release(palette);
3064     palette = NULL;
3065
3066     hr = IDirectDrawSurface_GetPalette(backbuffer, &palette);
3067     ok(hr == DD_OK, "CreateSurface returned: %x\n",hr);
3068
3069     IDirectDrawSurface_Release(backbuffer);
3070     IDirectDrawSurface_Release(lpSurf);
3071 }
3072
3073 static void StructSizeTest(void)
3074 {
3075     IDirectDrawSurface *surface1;
3076     IDirectDrawSurface7 *surface7;
3077     union {
3078         DDSURFACEDESC desc1;
3079         DDSURFACEDESC2 desc2;
3080         char blob[1024]; /* To get a bunch of writable memory */
3081     } desc;
3082     DDSURFACEDESC create;
3083     HRESULT hr;
3084
3085     memset(&desc, 0, sizeof(desc));
3086     memset(&create, 0, sizeof(create));
3087
3088     memset(&create, 0, sizeof(create));
3089     create.dwSize = sizeof(create);
3090     create.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
3091     create.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
3092     create.dwHeight = 128;
3093     create.dwWidth = 128;
3094     hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
3095     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
3096     hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface7, (void **) &surface7);
3097     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed with %08x\n", hr);
3098
3099     desc.desc1.dwSize = sizeof(DDSURFACEDESC);
3100     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
3101     ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
3102     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
3103     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
3104
3105     desc.desc2.dwSize = sizeof(DDSURFACEDESC2);
3106     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
3107     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
3108     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
3109     ok(hr == DD_OK, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
3110
3111     desc.desc2.dwSize = 0;
3112     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
3113     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size 0 returned %08x\n", hr);
3114     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
3115     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size 0 returned %08x\n", hr);
3116
3117     desc.desc1.dwSize = sizeof(DDSURFACEDESC) + 1;
3118     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
3119     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
3120     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
3121     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
3122
3123     desc.desc2.dwSize = sizeof(DDSURFACEDESC2) + 1;
3124     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
3125     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
3126     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
3127     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
3128
3129     /* Tests for Lock() */
3130
3131     desc.desc1.dwSize = sizeof(DDSURFACEDESC);
3132     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3133     ok(hr == DD_OK, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
3134     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3135     ok(desc.desc1.dwSize == sizeof(DDSURFACEDESC), "Destination size was changed to %d\n", desc.desc1.dwSize);
3136     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3137     ok(hr == DD_OK, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
3138     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3139     ok(desc.desc2.dwSize == sizeof(DDSURFACEDESC), "Destination size was changed to %d\n", desc.desc1.dwSize);
3140
3141     desc.desc2.dwSize = sizeof(DDSURFACEDESC2);
3142     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3143     ok(hr == DD_OK, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
3144     ok(desc.desc1.dwSize == sizeof(DDSURFACEDESC2), "Destination size was changed to %d\n", desc.desc1.dwSize);
3145     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3146     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3147     ok(hr == DD_OK, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
3148     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3149     ok(desc.desc2.dwSize == sizeof(DDSURFACEDESC2), "Destination size was changed to %d\n", desc.desc1.dwSize);
3150
3151     desc.desc2.dwSize = 0;
3152     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3153     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size 0 returned %08x\n", hr);
3154     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3155     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3156     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size 0 returned %08x\n", hr);
3157     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3158
3159     desc.desc1.dwSize = sizeof(DDSURFACEDESC) + 1;
3160     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3161     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
3162     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3163     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3164     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
3165     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3166
3167     desc.desc2.dwSize = sizeof(DDSURFACEDESC2) + 1;
3168     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3169     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
3170     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3171     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3172     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
3173     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3174
3175     IDirectDrawSurface7_Release(surface7);
3176     IDirectDrawSurface_Release(surface1);
3177 }
3178
3179 static void SurfaceCapsTest(void)
3180 {
3181     DDSURFACEDESC create;
3182     DDSURFACEDESC desc;
3183     HRESULT hr;
3184     IDirectDrawSurface *surface1 = NULL;
3185     DDSURFACEDESC2 create2, desc2;
3186     IDirectDrawSurface7 *surface7 = NULL;
3187     IDirectDraw7 *dd7 = NULL;
3188     DWORD create_caps[] = {
3189         DDSCAPS_OFFSCREENPLAIN,
3190         DDSCAPS_TEXTURE,
3191         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
3192         0,
3193         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD | DDSCAPS_SYSTEMMEMORY,
3194         DDSCAPS_PRIMARYSURFACE,
3195         DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY,
3196         DDSCAPS_3DDEVICE,
3197         DDSCAPS_ZBUFFER,
3198         DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN
3199     };
3200     DWORD expected_caps[] = {
3201         DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3202         DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3203         DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_ALLOCONLOAD,
3204         DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3205         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD | DDSCAPS_SYSTEMMEMORY,
3206         DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_VISIBLE,
3207         DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_VISIBLE,
3208         DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3209         DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY,
3210         DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM
3211     };
3212     UINT i;
3213
3214     /* Tests various surface flags, what changes do they undergo during surface creation. Forsaken
3215      * engine expects texture surfaces without memory flag to get a video memory flag right after
3216      * creation. Currently, Wine adds DDSCAPS_FRONTBUFFER to primary surface, but native doesn't do this
3217      * for single buffered primaries. Because of this primary surface creation tests are todo_wine. No real
3218      * app is known so far to care about this. */
3219
3220     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3221     {
3222         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3223         return ;
3224     }
3225
3226     for (i = 0; i < sizeof(create_caps) / sizeof(DWORD); i++)
3227     {
3228         memset(&create, 0, sizeof(create));
3229         create.dwSize = sizeof(create);
3230         create.ddsCaps.dwCaps = create_caps[i];
3231         create.dwFlags = DDSD_CAPS;
3232
3233         if (!(create.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
3234         {
3235             create.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH;
3236             create.dwHeight = 128;
3237             create.dwWidth = 128;
3238         }
3239
3240         if (create.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
3241         {
3242             create.dwFlags |= DDSD_PIXELFORMAT;
3243             create.ddpfPixelFormat.dwSize = sizeof(create.ddpfPixelFormat);
3244             create.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3245             U1(create.ddpfPixelFormat).dwZBufferBitDepth = 16;
3246             U3(create.ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3247         }
3248
3249         hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
3250         ok(hr == DD_OK, "IDirectDraw_CreateSurface failed with %08x\n", hr);
3251
3252         if (SUCCEEDED(hr))
3253         {
3254             memset(&desc, 0, sizeof(desc));
3255             desc.dwSize = sizeof(DDSURFACEDESC);
3256             hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc);
3257             ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc failed with %08x\n", hr);
3258
3259             if (!(create_caps[i] & DDSCAPS_PRIMARYSURFACE))
3260                 ok(desc.ddsCaps.dwCaps == expected_caps[i],
3261                     "GetSurfaceDesc test %d returned caps %x, expected %x\n", i,
3262                     desc.ddsCaps.dwCaps, expected_caps[i]);
3263             else
3264                 todo_wine ok(desc.ddsCaps.dwCaps == expected_caps[i],
3265                                 "GetSurfaceDesc test %d returned caps %x, expected %x\n", i,
3266                                 desc.ddsCaps.dwCaps, expected_caps[i]);
3267
3268             IDirectDrawSurface_Release(surface1);
3269         }
3270     }
3271
3272     /* Test for differences in ddraw 7 */
3273     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3274     ok(hr == DD_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
3275     if (FAILED(hr))
3276     {
3277         skip("Failed to get IDirectDraw7 interface, skipping tests\n");
3278     }
3279     else
3280     {
3281         for (i = 0; i < sizeof(create_caps) / sizeof(DWORD); i++)
3282         {
3283             memset(&create2, 0, sizeof(create2));
3284             create2.dwSize = sizeof(create2);
3285             create2.ddsCaps.dwCaps = create_caps[i];
3286             create2.dwFlags = DDSD_CAPS;
3287
3288             if (!(create2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
3289             {
3290                 create2.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH;
3291                 create2.dwHeight = 128;
3292                 create2.dwWidth = 128;
3293             }
3294
3295             if (create2.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
3296             {
3297                 create2.dwFlags |= DDSD_PIXELFORMAT;
3298                 U4(create2).ddpfPixelFormat.dwSize = sizeof(U4(create2).ddpfPixelFormat);
3299                 U4(create2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3300                 U1(U4(create2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3301                 U3(U4(create2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3302             }
3303
3304             hr = IDirectDraw7_CreateSurface(dd7, &create2, &surface7, NULL);
3305             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3306
3307             if (SUCCEEDED(hr))
3308             {
3309                 memset(&desc2, 0, sizeof(desc2));
3310                 desc2.dwSize = sizeof(DDSURFACEDESC2);
3311                 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc2);
3312                 ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc failed with %08x\n", hr);
3313
3314                 if (!(create_caps[i] & DDSCAPS_PRIMARYSURFACE))
3315                     ok(desc2.ddsCaps.dwCaps == expected_caps[i],
3316                         "GetSurfaceDesc test %d returned caps %x, expected %x\n", i,
3317                         desc2.ddsCaps.dwCaps, expected_caps[i]);
3318                 else
3319                     todo_wine ok(desc2.ddsCaps.dwCaps == expected_caps[i],
3320                                     "GetSurfaceDesc test %d returned caps %x, expected %x\n", i,
3321                                     desc2.ddsCaps.dwCaps, expected_caps[i]);
3322
3323                 IDirectDrawSurface7_Release(surface7);
3324             }
3325         }
3326
3327         IDirectDraw7_Release(dd7);
3328     }
3329
3330     memset(&create, 0, sizeof(create));
3331     create.dwSize = sizeof(create);
3332     create.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3333     create.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
3334     create.dwWidth = 64;
3335     create.dwHeight = 64;
3336     hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
3337     ok(hr == DDERR_INVALIDCAPS, "Creating a SYSMEM | VIDMEM surface returned 0x%08x, expected DDERR_INVALIDCAPS\n", hr);
3338     if(surface1) IDirectDrawSurface_Release(surface1);
3339 }
3340
3341 static BOOL can_create_primary_surface(void)
3342 {
3343     DDSURFACEDESC ddsd;
3344     IDirectDrawSurface *surface;
3345     HRESULT hr;
3346
3347     memset(&ddsd, 0, sizeof(ddsd));
3348     ddsd.dwSize = sizeof(ddsd);
3349     ddsd.dwFlags = DDSD_CAPS;
3350     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3351     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
3352     if(FAILED(hr)) return FALSE;
3353     IDirectDrawSurface_Release(surface);
3354     return TRUE;
3355 }
3356
3357 static void dctest_surf(IDirectDrawSurface *surf, int ddsdver) {
3358     HRESULT hr;
3359     HDC dc, dc2 = (HDC) 0x1234;
3360     DDSURFACEDESC ddsd;
3361     DDSURFACEDESC2 ddsd2;
3362
3363     memset(&ddsd, 0, sizeof(ddsd));
3364     ddsd.dwSize = sizeof(ddsd);
3365     memset(&ddsd2, 0, sizeof(ddsd2));
3366     ddsd2.dwSize = sizeof(ddsd2);
3367
3368     hr = IDirectDrawSurface_GetDC(surf, &dc);
3369     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
3370
3371     hr = IDirectDrawSurface_GetDC(surf, &dc2);
3372     ok(hr == DDERR_DCALREADYCREATED, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
3373     ok(dc2 == (HDC) 0x1234, "The failed GetDC call changed the dc: %p\n", dc2);
3374
3375     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
3376     ok(hr == DDERR_SURFACEBUSY, "IDirectDrawSurface_Lock returned 0x%08x, expected DDERR_ALREADYLOCKED\n", hr);
3377
3378     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
3379     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
3380     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
3381     ok(hr == DDERR_NODC, "IDirectDrawSurface_ReleaseDC returned 0x%08x, expected DDERR_NODC\n", hr);
3382 }
3383
3384 static void GetDCTest(void)
3385 {
3386     DDSURFACEDESC ddsd;
3387     DDSURFACEDESC2 ddsd2;
3388     IDirectDrawSurface *surf;
3389     IDirectDrawSurface2 *surf2;
3390     IDirectDrawSurface4 *surf4;
3391     IDirectDrawSurface7 *surf7;
3392     IDirectDrawSurface *tmp;
3393     IDirectDrawSurface7 *tmp7;
3394     HRESULT hr;
3395     IDirectDraw2 *dd2;
3396     IDirectDraw4 *dd4;
3397     IDirectDraw7 *dd7;
3398     HDC dc;
3399     ULONG ref;
3400
3401     memset(&ddsd, 0, sizeof(ddsd));
3402     ddsd.dwSize = sizeof(ddsd);
3403     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3404     ddsd.dwWidth = 64;
3405     ddsd.dwHeight = 64;
3406     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3407     memset(&ddsd2, 0, sizeof(ddsd2));
3408     ddsd2.dwSize = sizeof(ddsd2);
3409     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3410     ddsd2.dwWidth = 64;
3411     ddsd2.dwHeight = 64;
3412     ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3413
3414     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surf, NULL);
3415     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3416     dctest_surf(surf, 1);
3417     IDirectDrawSurface_Release(surf);
3418
3419     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
3420     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3421
3422     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3423     ok(hr == DD_OK, "IDirectDraw2_CreateSurface failed: 0x%08x\n", hr);
3424     dctest_surf(surf, 1);
3425
3426     hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2);
3427     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed: 0x%08x\n", hr);
3428     dctest_surf((IDirectDrawSurface *) surf2, 1);
3429
3430     IDirectDrawSurface2_Release(surf2);
3431     IDirectDrawSurface_Release(surf);
3432     IDirectDraw2_Release(dd2);
3433
3434     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
3435     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3436
3437     surf = NULL;
3438     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3439     ok(hr == DD_OK, "IDirectDraw4_CreateSurface failed: 0x%08x\n", hr);
3440     dctest_surf((IDirectDrawSurface *) surf4, 2);
3441
3442     hr = IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **)&surf);
3443     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3444
3445     ref = getRefcount((IUnknown *) surf);
3446     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
3447     ref = getRefcount((IUnknown *) surf4);
3448     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
3449
3450     hr = IDirectDrawSurface4_GetDC(surf4, &dc);
3451     ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr);
3452
3453     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, NULL);
3454     ok(hr == E_INVALIDARG, "Expected hr E_INVALIDARG, got %#x.\n", hr);
3455
3456     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, (IDirectDrawSurface4 **)&tmp);
3457     ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
3458     ok(tmp == surf, "Expected surface %p, got %p.\n\n", surf, tmp);
3459
3460     ref = getRefcount((IUnknown *) surf);
3461     ok(ref == 2, "Refcount is %u, expected 2\n", ref);
3462     ref = getRefcount((IUnknown *) tmp);
3463     ok(ref == 2, "Refcount is %u, expected 2\n", ref);
3464     ref = getRefcount((IUnknown *) surf4);
3465     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
3466
3467     hr = IDirectDrawSurface4_ReleaseDC(surf4, dc);
3468     ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
3469
3470     IDirectDrawSurface_Release(tmp);
3471
3472     dc = CreateCompatibleDC(NULL);
3473     ok(!!dc, "CreateCompatibleDC failed.\n");
3474
3475     tmp = (IDirectDrawSurface *)0xdeadbeef;
3476     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, (IDirectDrawSurface4 **)&tmp);
3477     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3478     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
3479
3480     ok(DeleteDC(dc), "DeleteDC failed.\n");
3481
3482     tmp = (IDirectDrawSurface *)0xdeadbeef;
3483     hr = IDirectDraw4_GetSurfaceFromDC(dd4, NULL, (IDirectDrawSurface4 **)&tmp);
3484     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3485     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
3486
3487     IDirectDrawSurface4_Release(surf4);
3488     IDirectDrawSurface_Release(surf);
3489     IDirectDraw4_Release(dd4);
3490
3491     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3492     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3493
3494     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3495     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed: 0x%08x\n", hr);
3496     dctest_surf((IDirectDrawSurface *) surf7, 2);
3497
3498     hr = IDirectDrawSurface7_GetDC(surf7, &dc);
3499     ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr);
3500
3501     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, NULL);
3502     ok(hr == E_INVALIDARG, "Expected hr E_INVALIDARG, got %#x.\n", hr);
3503
3504     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, &tmp7);
3505     ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
3506     ok(tmp7 == surf7, "Expected surface %p, got %p.\n\n", surf7, tmp7);
3507     IDirectDrawSurface7_Release(tmp7);
3508
3509     hr = IDirectDrawSurface7_ReleaseDC(surf7, dc);
3510     ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
3511
3512     dc = CreateCompatibleDC(NULL);
3513     ok(!!dc, "CreateCompatibleDC failed.\n");
3514
3515     tmp7 = (IDirectDrawSurface7 *)0xdeadbeef;
3516     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, &tmp7);
3517     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3518     ok(!tmp7, "Expected surface NULL, got %p.\n", tmp7);
3519
3520     ok(DeleteDC(dc), "DeleteDC failed.\n");
3521
3522     tmp7 = (IDirectDrawSurface7 *)0xdeadbeef;
3523     hr = IDirectDraw7_GetSurfaceFromDC(dd7, NULL, (IDirectDrawSurface7 **)&tmp7);
3524     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3525     ok(!tmp7, "Expected surface NULL, got %p.\n", tmp7);
3526
3527     IDirectDrawSurface7_Release(surf7);
3528     IDirectDraw7_Release(dd7);
3529 }
3530
3531 static void GetDCFormatTest(void)
3532 {
3533     DDSURFACEDESC2 ddsd;
3534     unsigned int i;
3535     IDirectDrawSurface7 *surface;
3536     IDirectDraw7 *dd7;
3537     HRESULT hr;
3538     HDC dc;
3539
3540     struct
3541     {
3542         const char *name;
3543         DDPIXELFORMAT fmt;
3544         BOOL getdc_capable;
3545         HRESULT alt_result;
3546     } testdata[] = {
3547         {
3548             "D3DFMT_A8R8G8B8",
3549             {
3550                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3551                 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3552             },
3553             TRUE
3554         },
3555         {
3556             "D3DFMT_X8R8G8B8",
3557             {
3558                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3559                 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
3560             },
3561             TRUE
3562         },
3563         {
3564             "D3DFMT_X8B8G8R8",
3565             {
3566                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3567                 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
3568             },
3569             TRUE,
3570             DDERR_CANTCREATEDC /* Vista+ */
3571         },
3572         {
3573             "D3DFMT_X8B8G8R8",
3574             {
3575                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3576                        {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}
3577             },
3578             TRUE,
3579             DDERR_CANTCREATEDC /* Vista+ */
3580         },
3581         {
3582             "D3DFMT_A4R4G4B4",
3583             {
3584                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3585                        {16}, {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}
3586             },
3587             TRUE,
3588             DDERR_CANTCREATEDC /* Vista+ */
3589         },
3590         {
3591             "D3DFMT_X4R4G4B4",
3592             {
3593                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3594                        {16}, {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}
3595             },
3596             TRUE,
3597             DDERR_CANTCREATEDC /* Vista+ */
3598         },
3599         {
3600             "D3DFMT_R5G6B5",
3601             {
3602                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3603                        {16}, {0x0000F800}, {0x000007E0}, {0x0000001F}, {0x00000000}
3604             },
3605             TRUE
3606         },
3607         {
3608             "D3DFMT_A1R5G5B5",
3609             {
3610                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3611                        {16}, {0x00007C00}, {0x000003E0}, {0x0000001F}, {0x00008000}
3612             },
3613             TRUE
3614         },
3615         {
3616             "D3DFMT_X1R5G5B5",
3617             {
3618                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3619                        {16}, {0x00007C00}, {0x000003E0}, {0x0000001F}, {0x00000000}
3620             },
3621             TRUE
3622         },
3623         {
3624             "D3DFMT_R3G3B2",
3625             {
3626                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3627                        { 8}, {0x000000E0}, {0x0000001C}, {0x00000003}, {0x00000000}
3628             },
3629             FALSE
3630         },
3631         {
3632             /* Untested, windows test machine didn't support this format */
3633             "D3DFMT_A2R10G10B10",
3634             {
3635                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3636                        {32}, {0xC0000000}, {0x3FF00000}, {0x000FFC00}, {0x000003FF}
3637             },
3638             TRUE
3639         },
3640         /*
3641          * GetDC on a P8 surface fails unless the display mode is 8 bpp. This is not
3642          * implemented in wine yet, so disable the test for now. Succeeding P8 getDC
3643          * calls are tested in the ddraw.visual test.
3644          *
3645         {
3646             "D3DFMT_P8",
3647             {
3648                 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3649                 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3650             },
3651             FALSE
3652         },
3653          */
3654         {
3655             "D3DFMT_L8",
3656             {
3657                 sizeof(DDPIXELFORMAT), DDPF_LUMINANCE, 0,
3658                 {8 }, {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}
3659             },
3660             FALSE
3661         },
3662         {
3663             "D3DFMT_A8L8",
3664             {
3665                 sizeof(DDPIXELFORMAT), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0,
3666                 {16}, {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}
3667             },
3668             FALSE
3669         },
3670         {
3671             "D3DFMT_DXT1",
3672             {
3673                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'),
3674                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3675             },
3676             FALSE
3677         },
3678         {
3679             "D3DFMT_DXT2",
3680             {
3681                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'),
3682                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3683             },
3684             FALSE
3685         },
3686         {
3687             "D3DFMT_DXT3",
3688             {
3689                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'),
3690                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3691             },
3692             FALSE
3693         },
3694         {
3695             "D3DFMT_DXT4",
3696             {
3697                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'),
3698                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3699             },
3700             FALSE
3701         },
3702         {
3703             "D3DFMT_DXT5",
3704             {
3705                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'),
3706                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3707             },
3708             FALSE
3709         },
3710     };
3711
3712     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3713     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed, hr = 0x%08x\n", hr);
3714
3715     for(i = 0; i < (sizeof(testdata) / sizeof(testdata[0])); i++)
3716     {
3717         memset(&ddsd, 0, sizeof(ddsd));
3718         ddsd.dwSize = sizeof(ddsd);
3719         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3720         ddsd.dwWidth = 64;
3721         ddsd.dwHeight = 64;
3722         U4(ddsd).ddpfPixelFormat = testdata[i].fmt;
3723         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3724
3725         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
3726         if(FAILED(hr))
3727         {
3728             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
3729             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
3730             hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
3731             if(FAILED(hr))
3732             {
3733                 skip("IDirectDraw7_CreateSurface failed, hr = 0x%08x, format %s\n", hr, testdata[i].name);
3734                 continue;
3735             }
3736         }
3737
3738         dc = (void *) 0x1234;
3739         hr = IDirectDrawSurface7_GetDC(surface, &dc);
3740         if(testdata[i].getdc_capable)
3741         {
3742             ok(SUCCEEDED(hr) ||
3743                (testdata[i].alt_result && hr == testdata[i].alt_result),
3744                "GetDC on a %s surface failed(0x%08x), expected it to work\n",
3745                testdata[i].name, hr);
3746         }
3747         else
3748         {
3749             ok(FAILED(hr), "GetDC on a %s surface succeeded(0x%08x), expected it to fail\n",
3750                testdata[i].name, hr);
3751         }
3752
3753         if(SUCCEEDED(hr))
3754         {
3755             IDirectDrawSurface7_ReleaseDC(surface, dc);
3756             ok(hr == DD_OK, "IDirectDrawSurface7_ReleaseDC failed, hr = 0x%08x\n", hr);
3757             dc = 0;
3758         }
3759         else
3760         {
3761             ok(dc == NULL, "After failed GetDC dc is %p\n", dc);
3762         }
3763
3764         IDirectDrawSurface7_Release(surface);
3765     }
3766
3767     IDirectDraw7_Release(dd7);
3768 }
3769
3770 static void BackBufferCreateSurfaceTest(void)
3771 {
3772     DDSURFACEDESC ddsd;
3773     DDSURFACEDESC created_ddsd;
3774     DDSURFACEDESC2 ddsd2;
3775     IDirectDrawSurface *surf;
3776     IDirectDrawSurface4 *surf4;
3777     IDirectDrawSurface7 *surf7;
3778     HRESULT hr;
3779     IDirectDraw2 *dd2;
3780     IDirectDraw4 *dd4;
3781     IDirectDraw7 *dd7;
3782
3783     const DWORD caps = DDSCAPS_BACKBUFFER;
3784     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3785
3786     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3787     {
3788         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3789         return ;
3790     }
3791
3792     memset(&ddsd, 0, sizeof(ddsd));
3793     ddsd.dwSize = sizeof(ddsd);
3794     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3795     ddsd.dwWidth = 64;
3796     ddsd.dwHeight = 64;
3797     ddsd.ddsCaps.dwCaps = caps;
3798     memset(&ddsd2, 0, sizeof(ddsd2));
3799     ddsd2.dwSize = sizeof(ddsd2);
3800     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3801     ddsd2.dwWidth = 64;
3802     ddsd2.dwHeight = 64;
3803     ddsd2.ddsCaps.dwCaps = caps;
3804     memset(&created_ddsd, 0, sizeof(created_ddsd));
3805     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3806
3807     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surf, NULL);
3808     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3809     if (surf != NULL)
3810     {
3811         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3812         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3813         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3814            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3815            expected_caps);
3816         IDirectDrawSurface_Release(surf);
3817     }
3818
3819     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
3820     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3821
3822     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3823     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3824        DDERR_INVALIDCAPS, hr);
3825
3826     IDirectDraw2_Release(dd2);
3827
3828     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
3829     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3830
3831     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3832     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3833        DDERR_INVALIDCAPS, hr);
3834
3835     IDirectDraw4_Release(dd4);
3836
3837     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3838     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3839
3840     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3841     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3842        DDERR_INVALIDCAPS, hr);
3843
3844     IDirectDraw7_Release(dd7);
3845 }
3846
3847 static void BackBufferAttachmentFlipTest(void)
3848 {
3849     HRESULT hr;
3850     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3851     DDSURFACEDESC ddsd;
3852     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3853
3854     hr = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3855     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3856
3857     /* Perform attachment tests on a back-buffer */
3858     memset(&ddsd, 0, sizeof(ddsd));
3859     ddsd.dwSize = sizeof(ddsd);
3860     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3861     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3862     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3863     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3864     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
3865     ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3866
3867     if (surface2 != NULL)
3868     {
3869         /* Try a single primary and a two back buffers */
3870         memset(&ddsd, 0, sizeof(ddsd));
3871         ddsd.dwSize = sizeof(ddsd);
3872         ddsd.dwFlags = DDSD_CAPS;
3873         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3874         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
3875         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3876
3877         memset(&ddsd, 0, sizeof(ddsd));
3878         ddsd.dwSize = sizeof(ddsd);
3879         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3880         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3881         ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3882         ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3883         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL);
3884         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3885
3886         /* This one has a different size */
3887         memset(&ddsd, 0, sizeof(ddsd));
3888         ddsd.dwSize = sizeof(ddsd);
3889         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3890         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3891         ddsd.dwWidth = 128;
3892         ddsd.dwHeight = 128;
3893         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
3894         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3895
3896         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3897         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3898            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3899         if(SUCCEEDED(hr))
3900         {
3901             /* Try flipping the surfaces */
3902             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3903             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3904             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3905             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3906
3907             /* Try the reverse without detaching first */
3908             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3909             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3910             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3911             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3912         }
3913         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3914         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3915            "Attaching a front buffer to a back buffer returned %08x\n", hr);
3916         if(SUCCEEDED(hr))
3917         {
3918             /* Try flipping the surfaces */
3919             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3920             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3921             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3922             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3923
3924             /* Try to detach reversed */
3925             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3926             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3927             /* Now the proper detach */
3928             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3929             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3930         }
3931         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3932         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3933            "Attaching a back buffer to another back buffer returned %08x\n", hr);
3934         if(SUCCEEDED(hr))
3935         {
3936             /* Try flipping the surfaces */
3937             hr = IDirectDrawSurface_Flip(surface3, NULL, DDFLIP_WAIT);
3938             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3939             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3940             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3941             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3942             ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3943
3944             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
3945             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3946         }
3947         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
3948         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
3949         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
3950         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
3951
3952         IDirectDrawSurface_Release(surface4);
3953         IDirectDrawSurface_Release(surface3);
3954         IDirectDrawSurface_Release(surface2);
3955         IDirectDrawSurface_Release(surface1);
3956     }
3957
3958     hr =IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
3959     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3960
3961     DestroyWindow(window);
3962 }
3963
3964 static void CreateSurfaceBadCapsSizeTest(void)
3965 {
3966     DDSURFACEDESC ddsd_ok;
3967     DDSURFACEDESC ddsd_bad1;
3968     DDSURFACEDESC ddsd_bad2;
3969     DDSURFACEDESC ddsd_bad3;
3970     DDSURFACEDESC ddsd_bad4;
3971     DDSURFACEDESC2 ddsd2_ok;
3972     DDSURFACEDESC2 ddsd2_bad1;
3973     DDSURFACEDESC2 ddsd2_bad2;
3974     DDSURFACEDESC2 ddsd2_bad3;
3975     DDSURFACEDESC2 ddsd2_bad4;
3976     IDirectDrawSurface *surf;
3977     IDirectDrawSurface4 *surf4;
3978     IDirectDrawSurface7 *surf7;
3979     HRESULT hr;
3980     IDirectDraw2 *dd2;
3981     IDirectDraw4 *dd4;
3982     IDirectDraw7 *dd7;
3983
3984     const DWORD caps = DDSCAPS_OFFSCREENPLAIN;
3985
3986     memset(&ddsd_ok, 0, sizeof(ddsd_ok));
3987     ddsd_ok.dwSize = sizeof(ddsd_ok);
3988     ddsd_ok.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3989     ddsd_ok.dwWidth = 64;
3990     ddsd_ok.dwHeight = 64;
3991     ddsd_ok.ddsCaps.dwCaps = caps;
3992     memcpy(&ddsd_bad1, &ddsd_ok, sizeof(ddsd_bad1));
3993     ddsd_bad1.dwSize--;
3994     memcpy(&ddsd_bad2, &ddsd_ok, sizeof(ddsd_bad2));
3995     ddsd_bad2.dwSize++;
3996     memcpy(&ddsd_bad3, &ddsd_ok, sizeof(ddsd_bad3));
3997     ddsd_bad3.dwSize = 0;
3998     memcpy(&ddsd_bad4, &ddsd_ok, sizeof(ddsd_bad4));
3999     ddsd_bad4.dwSize = sizeof(DDSURFACEDESC2);
4000
4001     memset(&ddsd2_ok, 0, sizeof(ddsd2_ok));
4002     ddsd2_ok.dwSize = sizeof(ddsd2_ok);
4003     ddsd2_ok.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4004     ddsd2_ok.dwWidth = 64;
4005     ddsd2_ok.dwHeight = 64;
4006     ddsd2_ok.ddsCaps.dwCaps = caps;
4007     memcpy(&ddsd2_bad1, &ddsd2_ok, sizeof(ddsd2_bad1));
4008     ddsd2_bad1.dwSize--;
4009     memcpy(&ddsd2_bad2, &ddsd2_ok, sizeof(ddsd2_bad2));
4010     ddsd2_bad2.dwSize++;
4011     memcpy(&ddsd2_bad3, &ddsd2_ok, sizeof(ddsd2_bad3));
4012     ddsd2_bad3.dwSize = 0;
4013     memcpy(&ddsd2_bad4, &ddsd2_ok, sizeof(ddsd2_bad4));
4014     ddsd2_bad4.dwSize = sizeof(DDSURFACEDESC);
4015
4016     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_ok, &surf, NULL);
4017     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
4018     IDirectDrawSurface_Release(surf);
4019
4020     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_bad1, &surf, NULL);
4021     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4022        DDERR_INVALIDPARAMS, hr);
4023     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_bad2, &surf, NULL);
4024     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4025        DDERR_INVALIDPARAMS, hr);
4026     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_bad3, &surf, NULL);
4027     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4028        DDERR_INVALIDPARAMS, hr);
4029     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_bad4, &surf, NULL);
4030     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4031        DDERR_INVALIDPARAMS, hr);
4032     hr = IDirectDraw_CreateSurface(lpDD, NULL, &surf, NULL);
4033     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4034        DDERR_INVALIDPARAMS, hr);
4035
4036     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
4037     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
4038
4039     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_ok, &surf, NULL);
4040     ok(SUCCEEDED(hr), "IDirectDraw2_CreateSurface failed: 0x%08x\n", hr);
4041     IDirectDrawSurface_Release(surf);
4042
4043     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_bad1, &surf, NULL);
4044     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4045        DDERR_INVALIDPARAMS, hr);
4046     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_bad2, &surf, NULL);
4047     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4048        DDERR_INVALIDPARAMS, hr);
4049     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_bad3, &surf, NULL);
4050     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4051        DDERR_INVALIDPARAMS, hr);
4052     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_bad4, &surf, NULL);
4053     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4054        DDERR_INVALIDPARAMS, hr);
4055     hr = IDirectDraw2_CreateSurface(dd2, NULL, &surf, NULL);
4056     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4057        DDERR_INVALIDPARAMS, hr);
4058
4059     IDirectDraw2_Release(dd2);
4060
4061     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
4062     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
4063
4064     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_ok, &surf4, NULL);
4065     ok(SUCCEEDED(hr), "IDirectDraw4_CreateSurface failed: 0x%08x\n", hr);
4066     IDirectDrawSurface4_Release(surf4);
4067
4068     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_bad1, &surf4, NULL);
4069     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4070        DDERR_INVALIDPARAMS, hr);
4071     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_bad2, &surf4, NULL);
4072     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4073        DDERR_INVALIDPARAMS, hr);
4074     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_bad3, &surf4, NULL);
4075     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4076        DDERR_INVALIDPARAMS, hr);
4077     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_bad4, &surf4, NULL);
4078     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4079        DDERR_INVALIDPARAMS, hr);
4080     hr = IDirectDraw4_CreateSurface(dd4, NULL, &surf4, NULL);
4081     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4082        DDERR_INVALIDPARAMS, hr);
4083
4084     IDirectDraw4_Release(dd4);
4085
4086     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
4087     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
4088
4089     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_ok, &surf7, NULL);
4090     ok(SUCCEEDED(hr), "IDirectDraw7_CreateSurface failed: 0x%08x\n", hr);
4091     IDirectDrawSurface7_Release(surf7);
4092
4093     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_bad1, &surf7, NULL);
4094     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4095        DDERR_INVALIDPARAMS, hr);
4096     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_bad2, &surf7, NULL);
4097     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4098        DDERR_INVALIDPARAMS, hr);
4099     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_bad3, &surf7, NULL);
4100     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4101        DDERR_INVALIDPARAMS, hr);
4102     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_bad4, &surf7, NULL);
4103     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4104        DDERR_INVALIDPARAMS, hr);
4105     hr = IDirectDraw7_CreateSurface(dd7, NULL, &surf7, NULL);
4106     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
4107        DDERR_INVALIDPARAMS, hr);
4108
4109     IDirectDraw7_Release(dd7);
4110 }
4111
4112 static void reset_ddsd(DDSURFACEDESC *ddsd)
4113 {
4114     memset(ddsd, 0, sizeof(*ddsd));
4115     ddsd->dwSize = sizeof(*ddsd);
4116 }
4117
4118 static void no_ddsd_caps_test(void)
4119 {
4120     DDSURFACEDESC ddsd;
4121     HRESULT hr;
4122     IDirectDrawSurface *surface;
4123
4124     reset_ddsd(&ddsd);
4125     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
4126     ddsd.dwWidth = 128;
4127     ddsd.dwHeight = 128;
4128     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4129     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4130     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4131     reset_ddsd(&ddsd);
4132     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4133     IDirectDrawSurface_Release(surface);
4134     ok(ddsd.dwFlags & DDSD_CAPS, "DDSD_CAPS is not set\n");
4135     ok(ddsd.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN, "DDSCAPS_OFFSCREENPLAIN is not set\n");
4136
4137     reset_ddsd(&ddsd);
4138     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4139     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4140     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4141     reset_ddsd(&ddsd);
4142     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4143     IDirectDrawSurface_Release(surface);
4144     ok(ddsd.dwFlags & DDSD_CAPS, "DDSD_CAPS is not set\n");
4145     ok(ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE, "DDSCAPS_OFFSCREENPLAIN is not set\n");
4146
4147     reset_ddsd(&ddsd);
4148     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
4149     ddsd.dwWidth = 128;
4150     ddsd.dwHeight = 128;
4151     ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4152     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4153     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw_CreateSurface returned %#x, expected DDERR_INVALIDCAPS.\n", hr);
4154 }
4155
4156 static void dump_format(const DDPIXELFORMAT *fmt)
4157 {
4158     trace("dwFlags %08x, FourCC %08x, dwZBufferBitDepth %u, stencil %u\n", fmt->dwFlags, fmt->dwFourCC,
4159           U1(*fmt).dwZBufferBitDepth, U2(*fmt).dwStencilBitDepth);
4160     trace("dwZBitMask %08x, dwStencilBitMask %08x, dwRGBZBitMask %08x\n", U3(*fmt).dwZBitMask,
4161           U4(*fmt).dwStencilBitMask, U5(*fmt).dwRGBZBitMask);
4162 }
4163
4164 static void zbufferbitdepth_test(void)
4165 {
4166     enum zfmt_succeed
4167     {
4168         ZFMT_SUPPORTED_ALWAYS,
4169         ZFMT_SUPPORTED_NEVER,
4170         ZFMT_SUPPORTED_HWDEPENDENT
4171     };
4172     struct
4173     {
4174         DWORD depth;
4175         enum zfmt_succeed supported;
4176         DDPIXELFORMAT pf;
4177     }
4178     test_data[] =
4179     {
4180         {
4181             16, ZFMT_SUPPORTED_ALWAYS,
4182             {
4183                 sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4184                 {16}, {0}, {0x0000ffff}, {0x00000000}, {0x00000000}
4185             }
4186         },
4187         {
4188             24, ZFMT_SUPPORTED_HWDEPENDENT,
4189             {
4190                 sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4191                 {24}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4192             }
4193         },
4194         {
4195             32, ZFMT_SUPPORTED_HWDEPENDENT,
4196             {
4197                 sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4198                 {32}, {0}, {0xffffffff}, {0x00000000}, {0x00000000}
4199             }
4200         },
4201         /* Returns DDERR_INVALIDPARAMS instead of DDERR_INVALIDPIXELFORMAT.
4202          * Disabled for now
4203         {
4204             0, ZFMT_SUPPORTED_NEVER
4205         },
4206         */
4207         {
4208             15, ZFMT_SUPPORTED_NEVER
4209         },
4210         {
4211             28, ZFMT_SUPPORTED_NEVER
4212         },
4213         {
4214             40, ZFMT_SUPPORTED_NEVER
4215         },
4216     };
4217
4218     DDSURFACEDESC ddsd;
4219     IDirectDrawSurface *surface;
4220     HRESULT hr;
4221     unsigned int i;
4222     DDCAPS caps;
4223
4224     memset(&caps, 0, sizeof(caps));
4225     caps.dwSize = sizeof(caps);
4226     hr = IDirectDraw_GetCaps(lpDD, &caps, NULL);
4227     ok(SUCCEEDED(hr), "IDirectDraw_GetCaps failed, hr %#x.\n", hr);
4228     if (!(caps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
4229     {
4230         skip("Z buffers not supported, skipping DDSD_ZBUFFERBITDEPTH test\n");
4231         return;
4232     }
4233
4234     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
4235     {
4236         reset_ddsd(&ddsd);
4237         ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH;
4238         ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4239         ddsd.dwWidth = 256;
4240         ddsd.dwHeight = 256;
4241         U2(ddsd).dwZBufferBitDepth = test_data[i].depth;
4242
4243         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4244         if (test_data[i].supported == ZFMT_SUPPORTED_ALWAYS)
4245         {
4246             ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4247         }
4248         else if (test_data[i].supported == ZFMT_SUPPORTED_NEVER)
4249         {
4250             ok(hr == DDERR_INVALIDPIXELFORMAT, "IDirectDraw_CreateSurface returned %#x, expected %x.\n",
4251                hr, DDERR_INVALIDPIXELFORMAT);
4252         }
4253         if (!surface) continue;
4254
4255         reset_ddsd(&ddsd);
4256         hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4257         ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4258         IDirectDrawSurface_Release(surface);
4259
4260         ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n");
4261         ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n");
4262         /* Yet the ddpfPixelFormat member contains valid data */
4263         if (memcmp(&ddsd.ddpfPixelFormat, &test_data[i].pf, ddsd.ddpfPixelFormat.dwSize))
4264         {
4265             ok(0, "Unexpected format for depth %u\n", test_data[i].depth);
4266             dump_format(&ddsd.ddpfPixelFormat);
4267         }
4268     }
4269
4270     /* DDSD_ZBUFFERBITDEPTH vs DDSD_PIXELFORMAT? */
4271     reset_ddsd(&ddsd);
4272     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_ZBUFFERBITDEPTH;
4273     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4274     ddsd.dwWidth = 256;
4275     ddsd.dwHeight = 256;
4276     U2(ddsd).dwZBufferBitDepth = 24;
4277     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4278     ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4279     U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth = 16;
4280     U3(ddsd.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4281
4282     surface = NULL;
4283     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4284     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4285     if (!surface) return;
4286     reset_ddsd(&ddsd);
4287     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4288     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4289     IDirectDrawSurface_Release(surface);
4290     ok(U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth == 16, "Expected a 16bpp depth buffer, got %ubpp\n",
4291        U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth);
4292     ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n");
4293     ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n");
4294     ok(U2(ddsd).dwZBufferBitDepth == 16, "Expected dwZBufferBitDepth=16, got %u\n",
4295        U2(ddsd).dwZBufferBitDepth);
4296
4297     /* DDSD_PIXELFORMAT vs invalid ZBUFFERBITDEPTH */
4298     reset_ddsd(&ddsd);
4299     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_PIXELFORMAT;
4300     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4301     ddsd.dwWidth = 256;
4302     ddsd.dwHeight = 256;
4303     U2(ddsd).dwZBufferBitDepth = 40;
4304     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4305     ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4306     U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth = 16;
4307     U3(ddsd.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4308     surface = NULL;
4309     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4310     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4311     if (surface) IDirectDrawSurface_Release(surface);
4312
4313     /* Create a PIXELFORMAT-only surface, see if ZBUFFERBITDEPTH is set */
4314     reset_ddsd(&ddsd);
4315     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4316     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4317     ddsd.dwWidth = 256;
4318     ddsd.dwHeight = 256;
4319     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4320     ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4321     U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth = 16;
4322     U3(ddsd.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4323     surface = NULL;
4324     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4325     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4326     reset_ddsd(&ddsd);
4327     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4328     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4329     IDirectDrawSurface_Release(surface);
4330     ok(U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth == 16, "Expected a 16bpp depth buffer, got %ubpp\n",
4331        U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth);
4332     ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n");
4333     ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n");
4334     ok(U2(ddsd).dwZBufferBitDepth == 16, "Expected dwZBufferBitDepth=16, got %u\n",
4335        U2(ddsd).dwZBufferBitDepth);
4336 }
4337
4338 static void test_ddsd(DDSURFACEDESC *ddsd, BOOL expect_pf, BOOL expect_zd, const char *name, DWORD z_bit_depth)
4339 {
4340     IDirectDrawSurface *surface;
4341     IDirectDrawSurface7 *surface7;
4342     HRESULT hr;
4343     DDSURFACEDESC out;
4344     DDSURFACEDESC2 out2;
4345
4346     hr = IDirectDraw_CreateSurface(lpDD, ddsd, &surface, NULL);
4347     if (hr == DDERR_NOZBUFFERHW)
4348     {
4349         skip("Z buffers not supported, skipping Z flag test\n");
4350         return;
4351     }
4352     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4353     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **) &surface7);
4354     ok(SUCCEEDED(hr), "IDirectDrawSurface_QueryInterface failed, hr %#x.\n", hr);
4355
4356     reset_ddsd(&out);
4357     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &out);
4358     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4359     memset(&out2, 0, sizeof(out2));
4360     out2.dwSize = sizeof(out2);
4361     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &out2);
4362     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4363
4364     if (expect_pf)
4365     {
4366         ok(out.dwFlags & DDSD_PIXELFORMAT, "%s surface: Expected DDSD_PIXELFORMAT to be set\n", name);
4367         ok(out2.dwFlags & DDSD_PIXELFORMAT,
4368                 "%s surface: Expected DDSD_PIXELFORMAT to be set in DDSURFACEDESC2\n", name);
4369     }
4370     else
4371     {
4372         ok(!(out.dwFlags & DDSD_PIXELFORMAT), "%s surface: Expected DDSD_PIXELFORMAT not to be set\n", name);
4373         ok(out2.dwFlags & DDSD_PIXELFORMAT,
4374                 "%s surface: Expected DDSD_PIXELFORMAT to be set in DDSURFACEDESC2\n", name);
4375     }
4376     if (expect_zd)
4377     {
4378         ok(out.dwFlags & DDSD_ZBUFFERBITDEPTH, "%s surface: Expected DDSD_ZBUFFERBITDEPTH to be set\n", name);
4379         ok(U2(out).dwZBufferBitDepth == z_bit_depth, "ZBufferBitDepth is %u, expected %u\n",
4380                 U2(out).dwZBufferBitDepth, z_bit_depth);
4381         ok(!(out2.dwFlags & DDSD_ZBUFFERBITDEPTH),
4382                 "%s surface: Did not expect DDSD_ZBUFFERBITDEPTH to be set in DDSURFACEDESC2\n", name);
4383         /* dwMipMapCount and dwZBufferBitDepth share the same union */
4384         ok(U2(out2).dwMipMapCount == 0, "dwMipMapCount is %u, expected 0\n", U2(out2).dwMipMapCount);
4385     }
4386     else
4387     {
4388         ok(!(out.dwFlags & DDSD_ZBUFFERBITDEPTH), "%s surface: Expected DDSD_ZBUFFERBITDEPTH not to be set\n", name);
4389         ok(U2(out).dwZBufferBitDepth == 0, "ZBufferBitDepth is %u, expected 0\n", U2(out).dwZBufferBitDepth);
4390         ok(!(out2.dwFlags & DDSD_ZBUFFERBITDEPTH),
4391                 "%s surface: Did not expect DDSD_ZBUFFERBITDEPTH to be set in DDSURFACEDESC2\n", name);
4392         ok(U2(out2).dwMipMapCount == 0, "dwMipMapCount is %u, expected 0\n", U2(out2).dwMipMapCount);
4393     }
4394
4395     reset_ddsd(&out);
4396     hr = IDirectDrawSurface_Lock(surface, NULL, &out, 0, NULL);
4397     if (SUCCEEDED(hr))
4398     {
4399         hr = IDirectDrawSurface_Unlock(surface, NULL);
4400         ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4401
4402         /* DDSD_ZBUFFERBITDEPTH is never set on Nvidia, but follows GetSurfaceDesc rules on AMD */
4403         if (!expect_zd)
4404         {
4405             ok(!(out.dwFlags & DDSD_ZBUFFERBITDEPTH),
4406                 "Lock %s surface: Expected DDSD_ZBUFFERBITDEPTH not to be set\n", name);
4407         }
4408
4409         /* DDSD_PIXELFORMAT follows GetSurfaceDesc rules */
4410         if (expect_pf)
4411         {
4412             ok(out.dwFlags & DDSD_PIXELFORMAT, "%s surface: Expected DDSD_PIXELFORMAT to be set\n", name);
4413         }
4414         else
4415         {
4416             ok(!(out.dwFlags & DDSD_PIXELFORMAT),
4417                 "Lock %s surface: Expected DDSD_PIXELFORMAT not to be set\n", name);
4418         }
4419         if (out.dwFlags & DDSD_ZBUFFERBITDEPTH)
4420             ok(U2(out).dwZBufferBitDepth == z_bit_depth, "ZBufferBitDepth is %u, expected %u\n",
4421                     U2(out).dwZBufferBitDepth, z_bit_depth);
4422         else
4423             ok(U2(out).dwZBufferBitDepth == 0, "ZBufferBitDepth is %u, expected 0\n", U2(out).dwZBufferBitDepth);
4424     }
4425
4426     hr = IDirectDrawSurface7_Lock(surface7, NULL, &out2, 0, NULL);
4427     ok(SUCCEEDED(hr), "IDirectDrawSurface7_Lock failed, hr %#x.\n", hr);
4428     if (SUCCEEDED(hr))
4429     {
4430         hr = IDirectDrawSurface7_Unlock(surface7, NULL);
4431         ok(SUCCEEDED(hr), "IDirectDrawSurface7_Unlock failed, hr %#x.\n", hr);
4432         /* DDSD_PIXELFORMAT is always set, DDSD_ZBUFFERBITDEPTH never */
4433         ok(out2.dwFlags & DDSD_PIXELFORMAT,
4434                 "Lock %s surface: Expected DDSD_PIXELFORMAT to be set in DDSURFACEDESC2\n", name);
4435         ok(!(out2.dwFlags & DDSD_ZBUFFERBITDEPTH),
4436                 "Lock %s surface: Did not expect DDSD_ZBUFFERBITDEPTH to be set in DDSURFACEDESC2\n", name);
4437         ok(U2(out2).dwMipMapCount == 0, "dwMipMapCount is %u, expected 0\n", U2(out2).dwMipMapCount);
4438     }
4439
4440     IDirectDrawSurface7_Release(surface7);
4441     IDirectDrawSurface_Release(surface);
4442 }
4443
4444 static void pixelformat_flag_test(void)
4445 {
4446     DDSURFACEDESC ddsd;
4447     DDCAPS caps;
4448     HRESULT hr;
4449
4450     memset(&caps, 0, sizeof(caps));
4451     caps.dwSize = sizeof(caps);
4452     hr = IDirectDraw_GetCaps(lpDD, &caps, NULL);
4453     ok(SUCCEEDED(hr), "IDirectDraw_GetCaps failed, hr %#x.\n", hr);
4454     if (!(caps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
4455     {
4456         skip("Z buffers not supported, skipping DDSD_PIXELFORMAT test\n");
4457         return;
4458     }
4459
4460     reset_ddsd(&ddsd);
4461     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4462     ddsd.dwWidth = 64;
4463     ddsd.dwHeight = 64;
4464     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4465     test_ddsd(&ddsd, TRUE, FALSE, "offscreen plain", ~0U);
4466
4467     reset_ddsd(&ddsd);
4468     ddsd.dwFlags = DDSD_CAPS;
4469     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4470     test_ddsd(&ddsd, TRUE, FALSE, "primary", ~0U);
4471
4472     reset_ddsd(&ddsd);
4473     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
4474     ddsd.dwWidth = 64;
4475     ddsd.dwHeight = 64;
4476     U2(ddsd).dwZBufferBitDepth = 16;
4477     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4478     test_ddsd(&ddsd, FALSE, TRUE, "Z buffer", 16);
4479 }
4480
4481 static void set_surface_desc_test(void)
4482 {
4483     HRESULT hr;
4484     DDSURFACEDESC ddsd;
4485     IDirectDrawSurface *surface;
4486     IDirectDrawSurface3 *surface3;
4487     BYTE data[16*16*4];
4488
4489     reset_ddsd(&ddsd);
4490     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4491     ddsd.dwWidth = 8;
4492     ddsd.dwHeight = 8;
4493     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4494     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4495     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4496     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4497     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4498     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4499     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
4500
4501     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4502     ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4503
4504     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **) &surface3);
4505     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4506     IDirectDrawSurface_Release(surface);
4507
4508     reset_ddsd(&ddsd);
4509     ddsd.dwFlags = DDSD_LPSURFACE;
4510     ddsd.lpSurface = data;
4511     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4512     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4513
4514     /* Redundantly setting the same lpSurface is not an error */
4515     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4516     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4517
4518     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
4519     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4520
4521     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
4522     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4523
4524     IDirectDrawSurface_Release(surface3);
4525
4526     reset_ddsd(&ddsd);
4527     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4528     ddsd.dwWidth = 8;
4529     ddsd.dwHeight = 8;
4530     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4531     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4532     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4533     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4534     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4535     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4536     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
4537
4538     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4539     ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4540     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **) &surface3);
4541     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4542     IDirectDrawSurface_Release(surface);
4543     hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4544     ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
4545
4546     /* Setting the caps is an error. This also means the original description cannot be reapplied */
4547     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4548     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4549
4550     ddsd.dwFlags = DDSD_CAPS;
4551     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4552     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4553
4554     /* TODO: The INVALIDCAPS return value suggests that some caps can be set. */
4555     ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
4556     ddsd.lpSurface = data;
4557     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4558     ok(hr == DDERR_INVALIDCAPS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDCAPS);
4559     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
4560     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4561     ok(hr == DDERR_INVALIDCAPS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDCAPS);
4562
4563     /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too */
4564     reset_ddsd(&ddsd);
4565     ddsd.dwFlags = DDSD_HEIGHT;
4566     ddsd.dwHeight = 16;
4567     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4568     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4569
4570     ddsd.lpSurface = data;
4571     ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
4572     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4573     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4574
4575     ddsd.dwHeight = 0;
4576     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4577     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4578
4579     reset_ddsd(&ddsd);
4580     hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4581     ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
4582     ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
4583     ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
4584
4585     /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
4586     reset_ddsd(&ddsd);
4587     ddsd.dwFlags = DDSD_PITCH;
4588     U1(ddsd).lPitch = 8 * 4;
4589     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4590     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4591
4592     ddsd.dwFlags = DDSD_WIDTH;
4593     ddsd.dwWidth = 16;
4594     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4595     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4596
4597     ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
4598     ddsd.lpSurface = data;
4599     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4600     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4601
4602     ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
4603     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4604     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4605
4606     ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4607     U1(ddsd).lPitch = 16 * 4;
4608     ddsd.dwWidth = 16;
4609     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4610     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4611
4612     reset_ddsd(&ddsd);
4613     hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4614     ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
4615     ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
4616     ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
4617     ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
4618
4619     /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise
4620      *
4621      * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
4622     ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4623     U1(ddsd).lPitch = 4 * 4;
4624     ddsd.lpSurface = data;
4625     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4626     ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "SetSurfaceDesc failed, hr %#x.\n", hr);
4627
4628     U1(ddsd).lPitch = 4;
4629     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4630     ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "SetSurfaceDesc failed, hr %#x.\n", hr);
4631
4632     U1(ddsd).lPitch = 16 * 4 + 1;
4633     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4634     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4635
4636     U1(ddsd).lPitch = 16 * 4 + 3;
4637     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4638     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4639
4640     U1(ddsd).lPitch = -4; /* lPitch is signed */
4641     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4642     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4643
4644     U1(ddsd).lPitch = 16 * 4;
4645     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4646     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4647
4648     reset_ddsd(&ddsd);
4649     ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4650     U1(ddsd).lPitch = 0;
4651     ddsd.dwWidth = 16;
4652     ddsd.lpSurface = data;
4653     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4654     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4655
4656     ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4657     U1(ddsd).lPitch = 16 * 4;
4658     ddsd.dwWidth = 0;
4659     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4660     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4661
4662     /* Setting the pixelformat without lpsurface is an error, but with LPSURFACE it works */
4663     ddsd.dwFlags = DDSD_PIXELFORMAT;
4664     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4665     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4666     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4667     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4668     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4669     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4670     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4671     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4672
4673     ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
4674     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4675     ok(hr == DD_OK, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DD_OK);
4676
4677     /* Can't set color keys */
4678     reset_ddsd(&ddsd);
4679     ddsd.dwFlags = DDSD_CKSRCBLT;
4680     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
4681     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
4682     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4683     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4684
4685     ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
4686     ddsd.lpSurface = data;
4687     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4688     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4689
4690     IDirectDrawSurface_Release(surface3);
4691
4692     /* Need systemmemory surfaces
4693      *
4694      * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot */
4695     reset_ddsd(&ddsd);
4696     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4697     ddsd.dwWidth = 8;
4698     ddsd.dwHeight = 8;
4699     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4700     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4701     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4702     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4703     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4704     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4705     ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
4706
4707     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4708     ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "CreateSurface failed, hr %#x.\n", hr);
4709     if (FAILED(hr))
4710     {
4711         skip("Cannot create a video memory surface, skipping vidmem SetSurfaceDesc test.\n");
4712         return;
4713     }
4714     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **) &surface3);
4715     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4716     IDirectDrawSurface_Release(surface);
4717
4718     reset_ddsd(&ddsd);
4719     ddsd.dwFlags = DDSD_LPSURFACE;
4720     ddsd.lpSurface = data;
4721     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4722     ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc returned %#x, expected %#x.\n",
4723             hr, DDERR_INVALIDSURFACETYPE);
4724
4725     ddsd.dwFlags = DDSD_WIDTH;
4726     ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc returned %#x, expected %#x.\n",
4727             hr, DDERR_INVALIDSURFACETYPE);
4728
4729     IDirectDrawSurface3_Release(surface3);
4730 }
4731
4732 static BOOL fourcc_supported(DWORD fourcc, DWORD caps)
4733 {
4734     DDSURFACEDESC ddsd;
4735     HRESULT hr;
4736     IDirectDrawSurface *surface;
4737
4738     reset_ddsd(&ddsd);
4739     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4740     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
4741     ddsd.dwWidth = 4;
4742     ddsd.dwHeight = 4;
4743     ddsd.ddsCaps.dwCaps = caps;
4744     ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4745     ddsd.ddpfPixelFormat.dwFourCC = fourcc;
4746     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4747     if (FAILED(hr))
4748     {
4749         return FALSE;
4750     }
4751     IDirectDrawSurface_Release(surface);
4752     return TRUE;
4753 }
4754
4755 static void partial_block_lock_test(void)
4756 {
4757     IDirectDrawSurface7 *surface;
4758     HRESULT hr;
4759     DDSURFACEDESC2 ddsd;
4760     IDirectDraw7 *dd7;
4761     const struct
4762     {
4763         DWORD caps, caps2;
4764         const char *name;
4765         BOOL success;
4766     }
4767     pools[] =
4768     {
4769         {
4770             DDSCAPS_VIDEOMEMORY, 0,
4771             "D3DPOOL_DEFAULT", FALSE
4772         },
4773         {
4774             DDSCAPS_SYSTEMMEMORY, 0,
4775             "D3DPOOL_SYSTEMMEM", TRUE
4776         },
4777         {
4778             0, DDSCAPS2_TEXTUREMANAGE,
4779             "D3DPOOL_MANAGED", TRUE
4780         }
4781     };
4782     const struct
4783     {
4784         DWORD fourcc;
4785         DWORD caps;
4786         const char *name;
4787         unsigned int block_width;
4788         unsigned int block_height;
4789     }
4790     formats[] =
4791     {
4792         {MAKEFOURCC('D','X','T','1'), DDSCAPS_TEXTURE, "D3DFMT_DXT1", 4, 4},
4793         {MAKEFOURCC('D','X','T','2'), DDSCAPS_TEXTURE, "D3DFMT_DXT2", 4, 4},
4794         {MAKEFOURCC('D','X','T','3'), DDSCAPS_TEXTURE, "D3DFMT_DXT3", 4, 4},
4795         {MAKEFOURCC('D','X','T','4'), DDSCAPS_TEXTURE, "D3DFMT_DXT4", 4, 4},
4796         {MAKEFOURCC('D','X','T','5'), DDSCAPS_TEXTURE, "D3DFMT_DXT5", 4, 4},
4797         /* ATI2N surfaces aren't available in ddraw */
4798         {MAKEFOURCC('U','Y','V','Y'), DDSCAPS_OVERLAY, "D3DFMT_UYVY", 2, 1},
4799         {MAKEFOURCC('Y','U','Y','2'), DDSCAPS_OVERLAY, "D3DFMT_YUY2", 2, 1},
4800     };
4801     unsigned int i, j;
4802     RECT rect;
4803
4804     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
4805     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4806
4807     for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
4808     {
4809         if (!fourcc_supported(formats[i].fourcc, formats[i].caps | DDSCAPS_VIDEOMEMORY))
4810         {
4811             skip("%s surfaces not supported, skipping partial block lock test\n", formats[i].name);
4812             continue;
4813         }
4814
4815         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); j++)
4816         {
4817             if (formats[i].caps & DDSCAPS_OVERLAY && !(pools[j].caps & DDSCAPS_VIDEOMEMORY))
4818                 continue;
4819
4820             memset(&ddsd, 0, sizeof(ddsd));
4821             ddsd.dwSize = sizeof(ddsd);
4822             ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
4823             ddsd.dwWidth = 128;
4824             ddsd.dwHeight = 128;
4825             ddsd.ddsCaps.dwCaps = pools[j].caps | formats[i].caps;
4826             ddsd.ddsCaps.dwCaps2 = pools[j].caps2;
4827             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4828             U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4829             hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
4830             ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x, format %s, pool %s\n",
4831                 hr, formats[i].name, pools[j].name);
4832
4833             /* All Windows versions allow partial block locks with DDSCAPS_SYSTEMMEMORY and
4834              * DDSCAPS2_TEXTUREMANAGE, just like in d3d8 and d3d9. Windows XP also allows those locks
4835              * with DDSCAPS_VIDEOMEMORY. Windows Vista and Windows 7 disallow partial locks of vidmem
4836              * surfaces, making the ddraw behavior consistent with d3d8 and 9.
4837              *
4838              * Mark the Windows XP behavior as broken until we find an application that needs it */
4839             if (formats[i].block_width > 1)
4840             {
4841                 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
4842                 hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4843                 ok(!SUCCEEDED(hr) == !pools[j].success || broken(SUCCEEDED(hr)),
4844                         "Partial block lock %s, expected %s, format %s, pool %s\n",
4845                         SUCCEEDED(hr) ? "succeeded" : "failed", pools[j].success ? "success" : "failure",
4846                         formats[i].name, pools[j].name);
4847                 if (SUCCEEDED(hr))
4848                 {
4849                     hr = IDirectDrawSurface7_Unlock(surface, NULL);
4850                     ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4851                 }
4852
4853                 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
4854                 hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4855                 ok(!SUCCEEDED(hr) == !pools[j].success || broken(SUCCEEDED(hr)),
4856                         "Partial block lock %s, expected %s, format %s, pool %s\n",
4857                         SUCCEEDED(hr) ? "succeeded" : "failed", pools[j].success ? "success" : "failure",
4858                         formats[i].name, pools[j].name);
4859                 if (SUCCEEDED(hr))
4860                 {
4861                     hr = IDirectDrawSurface7_Unlock(surface, NULL);
4862                     ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4863                 }
4864             }
4865
4866             if (formats[i].block_height > 1)
4867             {
4868                 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
4869                 hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4870                 ok(!SUCCEEDED(hr) == !pools[j].success || broken(SUCCEEDED(hr)),
4871                         "Partial block lock %s, expected %s, format %s, pool %s\n",
4872                         SUCCEEDED(hr) ? "succeeded" : "failed", pools[j].success ? "success" : "failure",
4873                         formats[i].name, pools[j].name);
4874                 if (SUCCEEDED(hr))
4875                 {
4876                     hr = IDirectDrawSurface7_Unlock(surface, NULL);
4877                     ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4878                 }
4879
4880                 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
4881                 hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4882                 ok(!SUCCEEDED(hr) == !pools[j].success || broken(SUCCEEDED(hr)),
4883                         "Partial block lock %s, expected %s, format %s, pool %s\n",
4884                         SUCCEEDED(hr) ? "succeeded" : "failed", pools[j].success ? "success" : "failure",
4885                         formats[i].name, pools[j].name);
4886                 if (SUCCEEDED(hr))
4887                 {
4888                     hr = IDirectDrawSurface7_Unlock(surface, NULL);
4889                     ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4890                 }
4891             }
4892
4893             SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
4894             hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4895             ok(SUCCEEDED(hr), "Full block lock returned %08x, expected %08x, format %s, pool %s\n",
4896                     hr, DD_OK, formats[i].name, pools[j].name);
4897             if (SUCCEEDED(hr))
4898             {
4899                 hr = IDirectDrawSurface7_Unlock(surface, NULL);
4900                 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4901             }
4902
4903             IDirectDrawSurface7_Release(surface);
4904         }
4905     }
4906
4907     IDirectDraw7_Release(dd7);
4908 }
4909
4910 static void create_surface_test(void)
4911 {
4912     HRESULT hr;
4913     IDirectDraw2 *ddraw2;
4914     IDirectDraw4 *ddraw4;
4915     IDirectDraw7 *ddraw7;
4916     IDirectDrawSurface *surface;
4917     IDirectDrawSurface4 *surface4;
4918     IDirectDrawSurface7 *surface7;
4919
4920     hr = IDirectDraw_CreateSurface(lpDD, NULL, &surface, NULL);
4921     ok(hr == DDERR_INVALIDPARAMS, "CreateSurface(ddsd=NULL) returned %#x,"
4922             " expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4923
4924     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &ddraw2);
4925     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4926
4927     hr = IDirectDraw2_CreateSurface(ddraw2, NULL, &surface, NULL);
4928     ok(hr == DDERR_INVALIDPARAMS, "CreateSurface(ddsd=NULL) returned %#x,"
4929             " expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4930
4931     IDirectDraw2_Release(ddraw2);
4932
4933     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &ddraw4);
4934     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4935
4936     hr = IDirectDraw4_CreateSurface(ddraw4, NULL, &surface4, NULL);
4937     ok(hr == DDERR_INVALIDPARAMS, "CreateSurface(ddsd=NULL) returned %#x,"
4938             " expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4939
4940     IDirectDraw4_Release(ddraw4);
4941
4942     if (!pDirectDrawCreateEx)
4943     {
4944         skip("DirectDrawCreateEx not available, skipping IDirectDraw7 tests.\n");
4945         return;
4946     }
4947     hr = pDirectDrawCreateEx(NULL, (void **) &ddraw7, &IID_IDirectDraw7, NULL);
4948     ok(SUCCEEDED(hr), "DirectDrawCreateEx failed, hr %#x.\n", hr);
4949
4950     hr = IDirectDraw7_CreateSurface(ddraw7, NULL, &surface7, NULL);
4951     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "CreateSurface(ddsd=NULL, pre-SCL) returned %#x,"
4952             " expected %#x.\n", hr, DDERR_NOCOOPERATIVELEVELSET);
4953
4954     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, NULL, DDSCL_NORMAL);
4955     ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
4956
4957     hr = IDirectDraw7_CreateSurface(ddraw7, NULL, &surface7, NULL);
4958     ok(hr == DDERR_INVALIDPARAMS, "CreateSurface(ddsd=NULL) returned %#x,"
4959             " expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4960
4961     IDirectDraw7_Release(ddraw7);
4962 }
4963
4964 START_TEST(dsurface)
4965 {
4966     HRESULT ret;
4967     IDirectDraw4 *dd4;
4968
4969     HMODULE ddraw_mod = GetModuleHandleA("ddraw.dll");
4970     pDirectDrawCreateEx = (void *) GetProcAddress(ddraw_mod, "DirectDrawCreateEx");
4971
4972     if (!CreateDirectDraw())
4973         return;
4974
4975     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
4976     if (ret == E_NOINTERFACE)
4977     {
4978         win_skip("DirectDraw4 and higher are not supported\n");
4979         ReleaseDirectDraw();
4980         return;
4981     }
4982     IDirectDraw_Release(dd4);
4983
4984     if(!can_create_primary_surface())
4985     {
4986         skip("Unable to create primary surface\n");
4987         return;
4988     }
4989
4990     ddcaps.dwSize = sizeof(DDCAPS);
4991     ret = IDirectDraw_GetCaps(lpDD, &ddcaps, NULL);
4992     if (ret != DD_OK)
4993     {
4994         skip("IDirectDraw_GetCaps failed with %08x\n", ret);
4995         return;
4996     }
4997
4998     MipMapCreationTest();
4999     SrcColorKey32BlitTest();
5000     QueryInterface();
5001     GetDDInterface_1();
5002     GetDDInterface_2();
5003     GetDDInterface_4();
5004     GetDDInterface_7();
5005     IFaceRefCount();
5006     EnumTest();
5007     AttachmentTest();
5008     AttachmentTest7();
5009     CubeMapTest();
5010     test_lockrect_invalid();
5011     CompressedTest();
5012     SizeTest();
5013     PrivateDataTest();
5014     BltParamTest();
5015     StructSizeTest();
5016     PaletteTest();
5017     SurfaceCapsTest();
5018     GetDCTest();
5019     GetDCFormatTest();
5020     BackBufferCreateSurfaceTest();
5021     BackBufferAttachmentFlipTest();
5022     CreateSurfaceBadCapsSizeTest();
5023     no_ddsd_caps_test();
5024     zbufferbitdepth_test();
5025     pixelformat_flag_test();
5026     set_surface_desc_test();
5027     partial_block_lock_test();
5028     create_surface_test();
5029     ReleaseDirectDraw();
5030 }