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