ddraw/tests: Fix a couple of return value checks.
[wine] / dlls / ddraw / tests / d3d.c
1 /*
2  * Some unit tests for d3d functions
3  *
4  * Copyright (C) 2005 Antoine Chavasse
5  * Copyright (C) 2006,2011 Stefan Dösinger for CodeWeavers
6  * Copyright (C) 2008 Alexander Dorofeyev
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #define COBJMACROS
24
25 #include "wine/test.h"
26 #include <limits.h>
27 #include "initguid.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "unknwn.h"
31
32 static LPDIRECTDRAW7           lpDD = NULL;
33 static LPDIRECT3D7             lpD3D = NULL;
34 static LPDIRECTDRAWSURFACE7    lpDDS = NULL;
35 static LPDIRECTDRAWSURFACE7    lpDDSdepth = NULL;
36 static LPDIRECT3DDEVICE7       lpD3DDevice = NULL;
37 static LPDIRECT3DVERTEXBUFFER7 lpVBufSrc = NULL;
38
39 static IDirectDraw *DirectDraw1 = NULL;
40 static IDirectDrawSurface *Surface1 = NULL;
41 static IDirect3D *Direct3D1 = NULL;
42 static IDirect3DDevice *Direct3DDevice1 = NULL;
43 static IDirect3DExecuteBuffer *ExecuteBuffer = NULL;
44 static IDirect3DViewport *Viewport = NULL;
45 static IDirect3DLight *Light = NULL;
46
47 typedef struct {
48     int total;
49     int rgb;
50     int hal;
51     int tnlhal;
52     int unk;
53 } D3D7ETest;
54
55 typedef struct {
56     HRESULT desired_ret;
57     int total;
58 } D3D7ECancelTest;
59
60 #define MAX_ENUMERATION_COUNT 10
61 typedef struct
62 {
63     unsigned int count;
64     char *callback_description_ptrs[MAX_ENUMERATION_COUNT];
65     char callback_description_strings[MAX_ENUMERATION_COUNT][100];
66     char *callback_name_ptrs[MAX_ENUMERATION_COUNT];
67     char callback_name_strings[MAX_ENUMERATION_COUNT][100];
68 } D3D7ELifetimeTest;
69
70 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
71
72 static void init_function_pointers(void)
73 {
74     HMODULE hmod = GetModuleHandleA("ddraw.dll");
75     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
76 }
77
78
79 static ULONG getRefcount(IUnknown *iface)
80 {
81     IUnknown_AddRef(iface);
82     return IUnknown_Release(iface);
83 }
84
85 static HRESULT WINAPI SurfaceCounter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
86 {
87     UINT *num = context;
88     (*num)++;
89     IDirectDrawSurface_Release(surface);
90     return DDENUMRET_OK;
91 }
92
93 static BOOL CreateDirect3D(void)
94 {
95     HRESULT rc;
96     DDSURFACEDESC2 ddsd;
97     UINT num;
98
99     rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
100         &IID_IDirectDraw7, NULL);
101     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
102     if (!lpDD) {
103         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
104         return FALSE;
105     }
106
107     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
108     ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
109
110     rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
111     if (rc == E_NOINTERFACE) return FALSE;
112     ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
113
114     memset(&ddsd, 0, sizeof(ddsd));
115     ddsd.dwSize = sizeof(ddsd);
116     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
117     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
118     ddsd.dwWidth = 256;
119     ddsd.dwHeight = 256;
120     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
121     if (FAILED(rc))
122         return FALSE;
123
124     num = 0;
125     IDirectDraw7_EnumSurfaces(lpDD, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST, NULL, &num, SurfaceCounter);
126     ok(num == 1, "Has %d surfaces, expected 1\n", num);
127
128     memset(&ddsd, 0, sizeof(ddsd));
129     ddsd.dwSize = sizeof(ddsd);
130     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
131     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
132     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
133     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
134     U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 16;
135     U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
136     ddsd.dwWidth = 256;
137     ddsd.dwHeight = 256;
138     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDSdepth, NULL);
139     ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
140     if (FAILED(rc)) {
141         lpDDSdepth = NULL;
142     } else {
143         rc = IDirectDrawSurface_AddAttachedSurface(lpDDS, lpDDSdepth);
144         ok(rc == DD_OK, "IDirectDrawSurface_AddAttachedSurface returned %x\n", rc);
145         if (FAILED(rc))
146             return FALSE;
147     }
148
149     rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
150         &lpD3DDevice);
151     ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
152     if (!lpD3DDevice) {
153         trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
154         rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
155             &lpD3DDevice);
156         if (!lpD3DDevice) {
157             trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
158             rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
159                 &lpD3DDevice);
160             if (!lpD3DDevice) {
161                 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
162                 return FALSE;
163             }
164         }
165     }
166
167     return TRUE;
168 }
169
170 static void ReleaseDirect3D(void)
171 {
172     if (lpD3DDevice != NULL)
173     {
174         IDirect3DDevice7_Release(lpD3DDevice);
175         lpD3DDevice = NULL;
176     }
177
178     if (lpDDSdepth != NULL)
179     {
180         IDirectDrawSurface_Release(lpDDSdepth);
181         lpDDSdepth = NULL;
182     }
183
184     if (lpDDS != NULL)
185     {
186         IDirectDrawSurface_Release(lpDDS);
187         lpDDS = NULL;
188     }
189
190     if (lpD3D != NULL)
191     {
192         IDirect3D7_Release(lpD3D);
193         lpD3D = NULL;
194     }
195
196     if (lpDD != NULL)
197     {
198         IDirectDraw_Release(lpDD);
199         lpDD = NULL;
200     }
201 }
202
203 static void LightTest(void)
204 {
205     HRESULT rc;
206     D3DLIGHT7 light;
207     D3DLIGHT7 defaultlight;
208     BOOL bEnabled = FALSE;
209     float one = 1.0f;
210     float zero= 0.0f;
211     D3DMATERIAL7 mat;
212     BOOL enabled;
213     unsigned int i;
214     D3DDEVICEDESC7 caps;
215
216     /* Set a few lights with funky indices. */
217     memset(&light, 0, sizeof(light));
218     light.dltType = D3DLIGHT_DIRECTIONAL;
219     U1(light.dcvDiffuse).r = 0.5f;
220     U2(light.dcvDiffuse).g = 0.6f;
221     U3(light.dcvDiffuse).b = 0.7f;
222     U2(light.dvDirection).y = 1.f;
223
224     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
225     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
226     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
227     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
228     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
229     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
230
231
232     /* Try to retrieve a light beyond the indices of the lights that have
233        been set. */
234     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
235     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
236     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
237     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
238
239
240     /* Try to retrieve one of the lights that have been set */
241     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
242     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
243
244
245     /* Enable a light that have been previously set. */
246     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
247     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
248
249
250     /* Enable some lights that have not been previously set, and verify that
251        they have been initialized with proper default values. */
252     memset(&defaultlight, 0, sizeof(D3DLIGHT7));
253     defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
254     U1(defaultlight.dcvDiffuse).r = 1.f;
255     U2(defaultlight.dcvDiffuse).g = 1.f;
256     U3(defaultlight.dcvDiffuse).b = 1.f;
257     U3(defaultlight.dvDirection).z = 1.f;
258
259     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
260     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
261     memset(&light, 0, sizeof(D3DLIGHT7));
262     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
263     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
264     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
265         "light data doesn't match expected default values\n" );
266
267     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
268     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
269     memset(&light, 0, sizeof(D3DLIGHT7));
270     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
271     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
272     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
273         "light data doesn't match expected default values\n" );
274
275
276     /* Disable one of the light that have been previously enabled. */
277     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
278     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
279
280     /* Try to retrieve the enable status of some lights */
281     /* Light 20 is supposed to be disabled */
282     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
283     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
284     ok(!bEnabled, "GetLightEnable says the light is enabled\n");
285
286     /* Light 10 is supposed to be enabled */
287     bEnabled = FALSE;
288     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
289     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
290     ok(bEnabled, "GetLightEnable says the light is disabled\n");
291
292     /* Light 80 has not been set */
293     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
294     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
295
296     /* Light 23 has not been set */
297     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
298     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
299
300     /* Set some lights with invalid parameters */
301     memset(&light, 0, sizeof(D3DLIGHT7));
302     light.dltType = 0;
303     U1(light.dcvDiffuse).r = 1.f;
304     U2(light.dcvDiffuse).g = 1.f;
305     U3(light.dcvDiffuse).b = 1.f;
306     U3(light.dvDirection).z = 1.f;
307     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
308     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
309
310     memset(&light, 0, sizeof(D3DLIGHT7));
311     light.dltType = 12345;
312     U1(light.dcvDiffuse).r = 1.f;
313     U2(light.dcvDiffuse).g = 1.f;
314     U3(light.dcvDiffuse).b = 1.f;
315     U3(light.dvDirection).z = 1.f;
316     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
317     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
318
319     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
320     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
321
322     memset(&light, 0, sizeof(D3DLIGHT7));
323     light.dltType = D3DLIGHT_SPOT;
324     U1(light.dcvDiffuse).r = 1.f;
325     U2(light.dcvDiffuse).g = 1.f;
326     U3(light.dcvDiffuse).b = 1.f;
327     U3(light.dvDirection).z = 1.f;
328
329     light.dvAttenuation0 = -one / zero; /* -INFINITY */
330     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
331     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
332
333     light.dvAttenuation0 = -1.0;
334     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
335     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
336
337     light.dvAttenuation0 = 0.0;
338     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
339     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
340
341     light.dvAttenuation0 = 1.0;
342     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
343     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
344
345     light.dvAttenuation0 = one / zero; /* +INFINITY */
346     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
347     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
348
349     light.dvAttenuation0 = zero / zero; /* NaN */
350     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
351     ok(rc==D3D_OK ||
352        broken(rc==DDERR_INVALIDPARAMS), "SetLight returned: %x\n", rc);
353
354     /* Directional light ignores attenuation */
355     light.dltType = D3DLIGHT_DIRECTIONAL;
356     light.dvAttenuation0 = -1.0;
357     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
358     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
359
360     memset(&mat, 0, sizeof(mat));
361     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
362     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial returned: %x\n", rc);
363
364     U4(mat).power = 129.0;
365     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
366     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = 129.0) returned: %x\n", rc);
367     memset(&mat, 0, sizeof(mat));
368     rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
369     ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
370     ok(U4(mat).power == 129, "Returned power is %f\n", U4(mat).power);
371
372     U4(mat).power = -1.0;
373     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
374     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = -1.0) returned: %x\n", rc);
375     memset(&mat, 0, sizeof(mat));
376     rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
377     ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
378     ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
379
380     memset(&caps, 0, sizeof(caps));
381     rc = IDirect3DDevice7_GetCaps(lpD3DDevice, &caps);
382     ok(rc == D3D_OK, "IDirect3DDevice7_GetCaps failed with %x\n", rc);
383
384     if ( caps.dwMaxActiveLights == (DWORD) -1) {
385         /* Some cards without T&L Support return -1 (Examples: Voodoo Banshee, RivaTNT / NV4) */
386         skip("T&L not supported\n");
387         return;
388     }
389
390     for(i = 1; i <= caps.dwMaxActiveLights; i++) {
391         rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, TRUE);
392         ok(rc == D3D_OK, "Enabling light %u failed with %x\n", i, rc);
393         rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i, &enabled);
394         ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i, rc);
395         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
396     }
397
398     /* TODO: Test the rendering results in this situation */
399     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, TRUE);
400     ok(rc == D3D_OK, "Enabling one light more than supported returned %x\n", rc);
401     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i + 1, &enabled);
402     ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i + 1,  rc);
403     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
404     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, FALSE);
405     ok(rc == D3D_OK, "Disabling the additional returned %x\n", rc);
406
407     for(i = 1; i <= caps.dwMaxActiveLights; i++) {
408         rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, FALSE);
409         ok(rc == D3D_OK, "Disabling light %u failed with %x\n", i, rc);
410     }
411 }
412
413 static void StateTest( void )
414 {
415     HRESULT rc;
416
417     /* The msdn says its undocumented, does it return an error too? */
418     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
419     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
420     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
421     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
422 }
423
424
425 static void SceneTest(void)
426 {
427     HRESULT                      hr;
428
429     /* Test an EndScene without BeginScene. Should return an error */
430     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
431     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
432
433     /* Test a normal BeginScene / EndScene pair, this should work */
434     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
435     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
436     if (SUCCEEDED(hr))
437     {
438         hr = IDirect3DDevice7_EndScene(lpD3DDevice);
439         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
440     }
441
442     if (lpDDSdepth)
443     {
444         DDBLTFX fx;
445         memset(&fx, 0, sizeof(fx));
446         fx.dwSize = sizeof(fx);
447
448         hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
449         ok(hr == D3D_OK, "Depthfill failed outside a BeginScene / EndScene pair, hr 0x%08x\n", hr);
450
451         hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
452         ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
453         if (SUCCEEDED(hr))
454         {
455             hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
456             ok(hr == D3D_OK || broken(hr == E_FAIL),
457                     "Depthfill failed in a BeginScene / EndScene pair, hr 0x%08x\n", hr);
458             hr = IDirect3DDevice7_EndScene(lpD3DDevice);
459             ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
460         }
461     }
462     else
463     {
464         skip("Depth stencil creation failed at startup, skipping depthfill test\n");
465     }
466
467     /* Test another EndScene without having begun a new scene. Should return an error */
468     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
469     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
470
471     /* Two nested BeginScene and EndScene calls */
472     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
473     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
474     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
475     ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
476     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
477     ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
478     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
479     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
480
481     /* TODO: Verify that blitting works in the same way as in d3d9 */
482 }
483
484 static void LimitTest(void)
485 {
486     IDirectDrawSurface7 *pTexture = NULL;
487     HRESULT hr;
488     int i;
489     DDSURFACEDESC2 ddsd;
490
491     memset(&ddsd, 0, sizeof(ddsd));
492     ddsd.dwSize = sizeof(ddsd);
493     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
494     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
495     ddsd.dwWidth = 16;
496     ddsd.dwHeight = 16;
497     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
498     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
499     if(!pTexture) return;
500
501     for(i = 0; i < 8; i++) {
502         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
503         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
504         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
505         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
506         hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
507         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
508     }
509
510     IDirectDrawSurface7_Release(pTexture);
511 }
512
513 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
514 {
515     UINT ver = *((UINT *) ctx);
516     if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
517     {
518         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
519            "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
520         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
521            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
522         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
523            "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
524         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
525            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
526
527         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
528            "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
529         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
530            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
531         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
532            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
533         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
534            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
535
536         ok(hal->dcmColorModel == 0, "RGB Device %u hal caps has colormodel %u\n", ver, hal->dcmColorModel);
537         ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device %u hel caps has colormodel %u\n", ver, hel->dcmColorModel);
538     }
539     else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
540     {
541         trace("HAL Device %d\n", ver);
542         ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device %u hal caps has colormodel %u\n", ver, hel->dcmColorModel);
543         ok(hel->dcmColorModel == 0, "HAL Device %u hel caps has colormodel %u\n", ver, hel->dcmColorModel);
544     }
545     else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
546     {
547         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
548            "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
549         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
550            "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
551         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
552            "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
553         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
554            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
555
556         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
557            "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
558         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
559            "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
560         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
561            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
562         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
563            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
564     }
565     else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
566     {
567         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
568            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
569         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
570            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
571         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
572            "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
573         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
574            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
575
576         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
577            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
578         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
579            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
580         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
581            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
582         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
583            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
584
585         ok(hal->dcmColorModel == 0, "Ramp Device %u hal caps has colormodel %u\n", ver, hal->dcmColorModel);
586         ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device %u hel caps has colormodel %u\n",
587                 ver, hel->dcmColorModel);
588     }
589     else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
590     {
591         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
592            "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
593         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
594            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
595         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
596            "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
597         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
598            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
599
600         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
601            "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
602         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
603            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
604         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
605            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
606         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
607            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
608
609         ok(hal->dcmColorModel == 0, "MMX Device %u hal caps has colormodel %u\n", ver, hal->dcmColorModel);
610         ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device %u hel caps has colormodel %u\n", ver, hel->dcmColorModel);
611     }
612     else
613     {
614         ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
615         if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
616         else trace("hal line does NOT have pow2 set\n");
617         if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
618         else trace("hal tri does NOT have pow2 set\n");
619         if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
620         else trace("hel line does NOT have pow2 set\n");
621         if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
622         else trace("hel tri does NOT have pow2 set\n");
623     }
624     return DDENUMRET_OK;
625 }
626
627 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
628 {
629     D3D7ETest *d3d7et = Context;
630     if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
631         d3d7et->rgb++;
632     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
633         d3d7et->hal++;
634     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
635         d3d7et->tnlhal++;
636     else
637         d3d7et->unk++;
638
639     d3d7et->total++;
640
641     return DDENUMRET_OK;
642 }
643
644 static HRESULT WINAPI enumDevicesCancelTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
645 {
646     D3D7ECancelTest *d3d7et = Context;
647
648     d3d7et->total++;
649
650     return d3d7et->desired_ret;
651 }
652
653 static HRESULT WINAPI enumDevicesLifetimeTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
654 {
655     D3D7ELifetimeTest *ctx = Context;
656
657     if (ctx->count == MAX_ENUMERATION_COUNT)
658     {
659         ok(0, "Enumerated too many devices for context in callback\n");
660         return DDENUMRET_CANCEL;
661     }
662
663     ctx->callback_description_ptrs[ctx->count] = DeviceDescription;
664     strcpy(ctx->callback_description_strings[ctx->count], DeviceDescription);
665     ctx->callback_name_ptrs[ctx->count] = DeviceName;
666     strcpy(ctx->callback_name_strings[ctx->count], DeviceName);
667
668     ctx->count++;
669     return DDENUMRET_OK;
670 }
671
672 /*  Check the deviceGUID of devices enumerated by
673     IDirect3D7_EnumDevices. */
674 static void D3D7EnumTest(void)
675 {
676     HRESULT hr;
677     D3D7ETest d3d7et;
678     D3D7ECancelTest d3d7_cancel_test;
679
680     hr = IDirect3D7_EnumDevices(lpD3D, NULL, NULL);
681     ok(hr == DDERR_INVALIDPARAMS, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
682
683     memset(&d3d7et, 0, sizeof(d3d7et));
684     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et);
685     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
686
687     /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
688     ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
689
690     /* We make two additional assumptions. */
691     ok(d3d7et.rgb, "No RGB Device enumerated.\n");
692
693     if(d3d7et.tnlhal)
694         ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
695
696     d3d7_cancel_test.desired_ret = DDENUMRET_CANCEL;
697     d3d7_cancel_test.total = 0;
698     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesCancelTest7, &d3d7_cancel_test);
699     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
700
701     ok(d3d7_cancel_test.total == 1, "Enumerated a total of %u devices\n",
702        d3d7_cancel_test.total);
703
704     /* An enumeration callback can return any value besides DDENUMRET_OK to stop enumeration. */
705     d3d7_cancel_test.desired_ret = E_INVALIDARG;
706     d3d7_cancel_test.total = 0;
707     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesCancelTest7, &d3d7_cancel_test);
708     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
709
710     ok(d3d7_cancel_test.total == 1, "Enumerated a total of %u devices\n",
711        d3d7_cancel_test.total);
712 }
713
714 static void D3D7EnumLifetimeTest(void)
715 {
716     D3D7ELifetimeTest ctx, ctx2;
717     HRESULT hr;
718     unsigned int i;
719
720     ctx.count = 0;
721     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesLifetimeTest7, &ctx);
722     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
723
724     /* The enumeration strings remain valid even after IDirect3D7_EnumDevices finishes. */
725     for (i = 0; i < ctx.count; i++)
726     {
727         ok(!strcmp(ctx.callback_description_ptrs[i], ctx.callback_description_strings[i]),
728            "Got '%s' and '%s'\n", ctx.callback_description_ptrs[i], ctx.callback_description_strings[i]);
729         ok(!strcmp(ctx.callback_name_ptrs[i], ctx.callback_name_strings[i]),
730            "Got '%s' and '%s'\n", ctx.callback_name_ptrs[i], ctx.callback_name_strings[i]);
731     }
732
733     ctx2.count = 0;
734     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesLifetimeTest7, &ctx2);
735     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
736
737     /* The enumeration strings and their order are identical across enumerations. */
738     ok(ctx.count == ctx2.count, "Enumerated %u and %u devices\n", ctx.count, ctx2.count);
739     if (ctx.count == ctx2.count)
740     {
741         for (i = 0; i < ctx.count; i++)
742         {
743             ok(ctx.callback_description_ptrs[i] == ctx2.callback_description_ptrs[i],
744                "Unequal description pointers %p and %p\n", ctx.callback_description_ptrs[i], ctx2.callback_description_ptrs[i]);
745             ok(!strcmp(ctx.callback_description_strings[i], ctx2.callback_description_strings[i]),
746                "Got '%s' and '%s'\n", ctx.callback_description_strings[i], ctx2.callback_description_strings[i]);
747             ok(ctx.callback_name_ptrs[i] == ctx2.callback_name_ptrs[i],
748                "Unequal name pointers %p and %p\n", ctx.callback_name_ptrs[i], ctx2.callback_name_ptrs[i]);
749             ok(!strcmp(ctx.callback_name_strings[i], ctx2.callback_name_strings[i]),
750                "Got '%s' and '%s'\n", ctx.callback_name_strings[i], ctx2.callback_name_strings[i]);
751         }
752     }
753
754     /* Try altering the contents of the enumeration strings. */
755     for (i = 0; i < ctx2.count; i++)
756     {
757         strcpy(ctx2.callback_description_ptrs[i], "Fake Description");
758         strcpy(ctx2.callback_name_ptrs[i], "Fake Device");
759     }
760
761     ctx2.count = 0;
762     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesLifetimeTest7, &ctx2);
763     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
764
765     /* The original contents of the enumeration strings are not restored. */
766     ok(ctx.count == ctx2.count, "Enumerated %u and %u devices\n", ctx.count, ctx2.count);
767     if (ctx.count == ctx2.count)
768     {
769         for (i = 0; i < ctx.count; i++)
770         {
771             ok(ctx.callback_description_ptrs[i] == ctx2.callback_description_ptrs[i],
772                "Unequal description pointers %p and %p\n", ctx.callback_description_ptrs[i], ctx2.callback_description_ptrs[i]);
773             ok(strcmp(ctx.callback_description_strings[i], ctx2.callback_description_strings[i]) != 0,
774                "Got '%s' and '%s'\n", ctx.callback_description_strings[i], ctx2.callback_description_strings[i]);
775             ok(ctx.callback_name_ptrs[i] == ctx2.callback_name_ptrs[i],
776                "Unequal name pointers %p and %p\n", ctx.callback_name_ptrs[i], ctx2.callback_name_ptrs[i]);
777             ok(strcmp(ctx.callback_name_strings[i], ctx2.callback_name_strings[i]) != 0,
778                "Got '%s' and '%s'\n", ctx.callback_name_strings[i], ctx2.callback_name_strings[i]);
779         }
780     }
781 }
782
783 static void CapsTest(void)
784 {
785     IDirect3D3 *d3d3;
786     IDirect3D3 *d3d2;
787     IDirectDraw *dd1;
788     HRESULT hr;
789     UINT ver;
790
791     hr = DirectDrawCreate(NULL, &dd1, NULL);
792     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
793     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
794     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
795
796     hr = IDirect3D3_EnumDevices(d3d3, NULL, NULL);
797     ok(hr == DDERR_INVALIDPARAMS, "IDirect3D3_EnumDevices returned 0x%08x\n", hr);
798
799     ver = 3;
800     IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
801
802     IDirect3D3_Release(d3d3);
803     IDirectDraw_Release(dd1);
804
805     hr = DirectDrawCreate(NULL, &dd1, NULL);
806     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
807     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
808     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
809
810     hr = IDirect3D2_EnumDevices(d3d2, NULL, NULL);
811     ok(hr == DDERR_INVALIDPARAMS, "IDirect3D2_EnumDevices returned 0x%08x\n", hr);
812
813     ver = 2;
814     IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
815
816     IDirect3D2_Release(d3d2);
817     IDirectDraw_Release(dd1);
818 }
819
820 struct v_in {
821     float x, y, z;
822 };
823 struct v_out {
824     float x, y, z, rhw;
825 };
826
827 static BOOL D3D1_createObjects(void)
828 {
829     HRESULT hr;
830     DDSURFACEDESC ddsd;
831     D3DEXECUTEBUFFERDESC desc;
832     D3DVIEWPORT vp_data;
833
834     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
835     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
836     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
837     if (!DirectDraw1) {
838         return FALSE;
839     }
840
841     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
842     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
843
844     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
845     if (hr == E_NOINTERFACE) return FALSE;
846     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
847     if (!Direct3D1) {
848         return FALSE;
849     }
850
851     memset(&ddsd, 0, sizeof(ddsd));
852     ddsd.dwSize = sizeof(ddsd);
853     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
854     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
855     ddsd.dwWidth = 256;
856     ddsd.dwHeight = 256;
857     IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
858     if (!Surface1) {
859         skip("DDSCAPS_3DDEVICE surface not available\n");
860         return FALSE;
861     }
862
863     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
864     ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
865     if(!Direct3DDevice1) {
866         return FALSE;
867     }
868
869     memset(&desc, 0, sizeof(desc));
870     desc.dwSize = sizeof(desc);
871     desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
872     desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
873     desc.dwBufferSize = 128;
874     desc.lpData = NULL;
875     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
876     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
877     if(!ExecuteBuffer) {
878         return FALSE;
879     }
880
881     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
882     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
883     if(!Viewport) {
884         return FALSE;
885     }
886
887     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
888     ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
889
890     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
891     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
892     vp_data.dwSize = sizeof(vp_data);
893     vp_data.dwX = 0;
894     vp_data.dwY = 0;
895     vp_data.dwWidth = 256;
896     vp_data.dwHeight = 256;
897     vp_data.dvScaleX = 1;
898     vp_data.dvScaleY = 1;
899     vp_data.dvMaxX = 256;
900     vp_data.dvMaxY = 256;
901     vp_data.dvMinZ = 0;
902     vp_data.dvMaxZ = 1;
903     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
904     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
905
906     hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
907     ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
908     if (!Light)
909         return FALSE;
910
911     return TRUE;
912 }
913
914 static void D3D1_releaseObjects(void)
915 {
916     if (Light) IDirect3DLight_Release(Light);
917     if (Viewport) IDirect3DViewport_Release(Viewport);
918     if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
919     if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
920     if (Surface1) IDirectDrawSurface_Release(Surface1);
921     if (Direct3D1) IDirect3D_Release(Direct3D1);
922     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
923 }
924
925 static void ViewportTest(void)
926 {
927     HRESULT hr;
928     LPDIRECT3DVIEWPORT2 Viewport2;
929     IDirect3DViewport3 *Viewport3;
930     D3DVIEWPORT vp1_data, ret_vp1_data;
931     D3DVIEWPORT2 vp2_data, ret_vp2_data;
932     float infinity;
933
934     *(DWORD*)&infinity = 0x7f800000;
935
936     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
937     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
938
939     hr = IDirect3DViewport_QueryInterface(Viewport, &IID_IDirect3DViewport2, (void**) &Viewport2);
940     ok(hr==D3D_OK, "QueryInterface returned: %x\n", hr);
941     ok(Viewport2 == (IDirect3DViewport2 *)Viewport, "IDirect3DViewport2 iface diffrent from IDirect3DViewport\n");
942
943     hr = IDirect3DViewport_QueryInterface(Viewport, &IID_IDirect3DViewport3, (void**) &Viewport3);
944     ok(hr==D3D_OK, "QueryInterface returned: %x\n", hr);
945     ok(Viewport3 == (IDirect3DViewport3 *)Viewport, "IDirect3DViewport3 iface diffrent from IDirect3DViewport\n");
946     IDirect3DViewport3_Release(Viewport3);
947
948     vp1_data.dwSize = sizeof(vp1_data);
949     vp1_data.dwX = 0;
950     vp1_data.dwY = 1;
951     vp1_data.dwWidth = 256;
952     vp1_data.dwHeight = 257;
953     vp1_data.dvMaxX = 0;
954     vp1_data.dvMaxY = 0;
955     vp1_data.dvScaleX = 0;
956     vp1_data.dvScaleY = 0;
957     vp1_data.dvMinZ = 0.25;
958     vp1_data.dvMaxZ = 0.75;
959
960     vp2_data.dwSize = sizeof(vp2_data);
961     vp2_data.dwX = 2;
962     vp2_data.dwY = 3;
963     vp2_data.dwWidth = 258;
964     vp2_data.dwHeight = 259;
965     vp2_data.dvClipX = 0;
966     vp2_data.dvClipY = 0;
967     vp2_data.dvClipWidth = 0;
968     vp2_data.dvClipHeight = 0;
969     vp2_data.dvMinZ = 0.1;
970     vp2_data.dvMaxZ = 0.9;
971
972     hr = IDirect3DViewport2_SetViewport(Viewport2, &vp1_data);
973     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport returned %08x\n", hr);
974
975     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
976     ret_vp1_data.dwSize = sizeof(vp1_data);
977
978     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
979     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
980
981     ok(ret_vp1_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp1_data.dwX);
982     ok(ret_vp1_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp1_data.dwY);
983     ok(ret_vp1_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp1_data.dwWidth);
984     ok(ret_vp1_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp1_data.dwHeight);
985     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
986     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
987     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
988     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
989     ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
990     ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
991
992     hr = IDirect3DViewport2_SetViewport2(Viewport2, &vp2_data);
993     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport2 returned %08x\n", hr);
994
995     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
996     ret_vp2_data.dwSize = sizeof(vp2_data);
997
998     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
999     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1000
1001     ok(ret_vp2_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp2_data.dwX);
1002     ok(ret_vp2_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp2_data.dwY);
1003     ok(ret_vp2_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp2_data.dwWidth);
1004     ok(ret_vp2_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp2_data.dwHeight);
1005     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1006     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1007     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1008         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1009     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1010         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1011     ok(ret_vp2_data.dvMinZ == vp2_data.dvMinZ, "dvMinZ is %f, expected %f\n", ret_vp2_data.dvMinZ, vp2_data.dvMinZ);
1012     ok(ret_vp2_data.dvMaxZ == vp2_data.dvMaxZ, "dvMaxZ is %f, expected %f\n", ret_vp2_data.dvMaxZ, vp2_data.dvMaxZ);
1013
1014     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1015     ret_vp1_data.dwSize = sizeof(vp1_data);
1016
1017     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1018     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1019
1020     ok(ret_vp1_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp2_data.dwX);
1021     ok(ret_vp1_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp2_data.dwY);
1022     ok(ret_vp1_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp2_data.dwWidth);
1023     ok(ret_vp1_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp2_data.dwHeight);
1024     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1025     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1026     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1027     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1028     todo_wine ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1029     todo_wine ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1030
1031     hr = IDirect3DViewport2_SetViewport2(Viewport2, &vp2_data);
1032     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport2 returned %08x\n", hr);
1033
1034     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1035     ret_vp2_data.dwSize = sizeof(vp2_data);
1036
1037     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1038     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1039
1040     ok(ret_vp2_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp2_data.dwX);
1041     ok(ret_vp2_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp2_data.dwY);
1042     ok(ret_vp2_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp2_data.dwWidth);
1043     ok(ret_vp2_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp2_data.dwHeight);
1044     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1045     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1046     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1047         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1048     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1049         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1050     ok(ret_vp2_data.dvMinZ == vp2_data.dvMinZ, "dvMinZ is %f, expected %f\n", ret_vp2_data.dvMinZ, vp2_data.dvMinZ);
1051     ok(ret_vp2_data.dvMaxZ == vp2_data.dvMaxZ, "dvMaxZ is %f, expected %f\n", ret_vp2_data.dvMaxZ, vp2_data.dvMaxZ);
1052
1053     hr = IDirect3DViewport2_SetViewport(Viewport2, &vp1_data);
1054     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport returned %08x\n", hr);
1055
1056     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1057     ret_vp1_data.dwSize = sizeof(vp1_data);
1058
1059     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1060     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1061
1062     ok(ret_vp1_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp1_data.dwX);
1063     ok(ret_vp1_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp1_data.dwY);
1064     ok(ret_vp1_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp1_data.dwWidth);
1065     ok(ret_vp1_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp1_data.dwHeight);
1066     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1067     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1068     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1069     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1070     ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1071     ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1072
1073     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1074     ret_vp2_data.dwSize = sizeof(vp2_data);
1075
1076     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1077     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1078
1079     ok(ret_vp2_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp1_data.dwX);
1080     ok(ret_vp2_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp1_data.dwY);
1081     ok(ret_vp2_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp1_data.dwWidth);
1082     ok(ret_vp2_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp1_data.dwHeight);
1083     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1084     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1085     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1086         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1087     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1088         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1089     ok(ret_vp2_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp2_data.dvMinZ);
1090     ok(ret_vp2_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp2_data.dvMaxZ);
1091
1092     IDirect3DViewport2_Release(Viewport2);
1093
1094     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1095     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1096 }
1097
1098 #define SET_VP_DATA(vp_data) \
1099     vp_data.dwSize = sizeof(vp_data); \
1100     vp_data.dwX = 0; \
1101     vp_data.dwY = 0; \
1102     vp_data.dwWidth = 256; \
1103     vp_data.dwHeight = 256; \
1104     vp_data.dvMaxX = 256; \
1105     vp_data.dvMaxY = 256; \
1106     vp_data.dvScaleX = 5; \
1107     vp_data.dvScaleY = 5; \
1108     vp_data.dvMinZ = -25; \
1109     vp_data.dvMaxZ = 60;
1110
1111 static void Direct3D1Test(void)
1112 {
1113     HRESULT hr;
1114     D3DEXECUTEBUFFERDESC desc;
1115     D3DVIEWPORT vp_data;
1116     D3DINSTRUCTION *instr;
1117     D3DBRANCH *branch;
1118     IDirect3D *Direct3D_alt;
1119     IDirect3DLight *d3dlight;
1120     ULONG refcount;
1121     unsigned int idx = 0;
1122     static struct v_in testverts[] = {
1123         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
1124         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1125     };
1126     static struct v_in cliptest[] = {
1127         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
1128         {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1129     };
1130     static struct v_in offscreentest[] = {
1131         {128.1, 0.0, 0.0},
1132     };
1133     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1134     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1135     D3DTRANSFORMDATA transformdata;
1136     DWORD i = FALSE;
1137
1138     /* Interface consistency check. */
1139     hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1140     ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1141     ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1142     IDirect3D_Release(Direct3D_alt);
1143
1144     memset(&desc, 0, sizeof(desc));
1145     desc.dwSize = sizeof(desc);
1146     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1147     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1148
1149     memset(desc.lpData, 0, 128);
1150     instr = desc.lpData;
1151     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1152     instr[idx].bSize = sizeof(*branch);
1153     instr[idx].wCount = 1;
1154     idx++;
1155     branch = (D3DBRANCH *) &instr[idx];
1156     branch->dwMask = 0x0;
1157     branch->dwValue = 1;
1158     branch->bNegate = TRUE;
1159     branch->dwOffset = 0;
1160     idx += (sizeof(*branch) / sizeof(*instr));
1161     instr[idx].bOpcode = D3DOP_EXIT;
1162     instr[idx].bSize = 0;
1163     instr[idx].wCount = 0;
1164     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1165     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1166
1167     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1168     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1169
1170     memset(&desc, 0, sizeof(desc));
1171     desc.dwSize = sizeof(desc);
1172
1173     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1174     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1175
1176     memset(desc.lpData, 0, 128);
1177     instr = desc.lpData;
1178     idx = 0;
1179     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1180     instr[idx].bSize = sizeof(*branch);
1181     instr[idx].wCount = 1;
1182     idx++;
1183     branch = (D3DBRANCH *) &instr[idx];
1184     branch->dwMask = 0x0;
1185     branch->dwValue = 1;
1186     branch->bNegate = TRUE;
1187     branch->dwOffset = 64;
1188     instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1189     instr[0].bOpcode = D3DOP_EXIT;
1190     instr[0].bSize = 0;
1191     instr[0].wCount = 0;
1192     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1193     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1194
1195     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1196     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1197
1198     /* Test rendering 0 triangles */
1199     memset(&desc, 0, sizeof(desc));
1200     desc.dwSize = sizeof(desc);
1201
1202     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1203     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1204
1205     memset(desc.lpData, 0, 128);
1206     instr = desc.lpData;
1207
1208     instr->bOpcode = D3DOP_TRIANGLE;
1209     instr->bSize = sizeof(D3DOP_TRIANGLE);
1210     instr->wCount = 0;
1211     instr++;
1212     instr->bOpcode = D3DOP_EXIT;
1213     instr->bSize = 0;
1214     instr->wCount = 0;
1215     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1216     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1217
1218     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1219     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1220
1221     memset(&transformdata, 0, sizeof(transformdata));
1222     transformdata.dwSize = sizeof(transformdata);
1223     transformdata.lpIn = testverts;
1224     transformdata.dwInSize = sizeof(testverts[0]);
1225     transformdata.lpOut = out;
1226     transformdata.dwOutSize = sizeof(out[0]);
1227
1228     transformdata.lpHOut = NULL;
1229     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1230                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1231                                              &i);
1232     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1233
1234     transformdata.lpHOut = outH;
1235     memset(outH, 0xcc, sizeof(outH));
1236     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1237                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1238                                              &i);
1239     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1240     ok(i == 0, "Offscreen is %d\n", i);
1241
1242     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1243         static const struct v_out cmp[] = {
1244             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1245             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1246         };
1247
1248         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1249            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1250            "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1,
1251            out[i].x, out[i].y, out[i].z, out[i].rhw,
1252            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1253     }
1254     for(i = 0; i < sizeof(outH); i++) {
1255         if(((unsigned char *) outH)[i] != 0xcc) {
1256             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1257             break;
1258         }
1259     }
1260
1261     SET_VP_DATA(vp_data);
1262     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1263     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1264     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1265                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1266                                              &i);
1267     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1268     ok(i == 0, "Offscreen is %d\n", i);
1269
1270     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1271         static const struct v_out cmp[] = {
1272             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1273             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1274         };
1275         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1276            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1277            "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1,
1278            out[i].x, out[i].y, out[i].z, out[i].rhw,
1279            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1280     }
1281
1282     SET_VP_DATA(vp_data);
1283     vp_data.dwX = 10;
1284     vp_data.dwY = 20;
1285     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1286     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1287     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1288                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1289                                              &i);
1290     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1291     ok(i == 0, "Offscreen is %d\n", i);
1292     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1293         static const struct v_out cmp[] = {
1294             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1295             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1296         };
1297         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1298            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1299            "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1,
1300            out[i].x, out[i].y, out[i].z, out[i].rhw,
1301            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1302     }
1303
1304     memset(out, 0xcc, sizeof(out));
1305     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1306                                              &transformdata, D3DTRANSFORM_CLIPPED,
1307                                              &i);
1308     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1309     ok(i == 0, "Offscreen is %d\n", i);
1310     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1311         static const D3DHVERTEX cmpH[] = {
1312             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1313             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1314             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1315         };
1316         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1317            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1318            "HVertex %d differs. Got %08x %f %f %f, expected %08x %f %f %f\n", i + 1,
1319            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1320            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1321
1322         /* No scheme has been found behind those return values. It seems to be
1323          * whatever data windows has when throwing the vertex away. Modify the
1324          * input test vertices to test this more. Depending on the input data
1325          * it can happen that the z coord gets written into y, or similar things
1326          */
1327         if(0)
1328         {
1329             static const struct v_out cmp[] = {
1330                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1331                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1332             };
1333             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1334                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1335                 "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1,
1336                out[i].x, out[i].y, out[i].z, out[i].rhw,
1337                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1338         }
1339     }
1340     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1341         ok(((DWORD *) out)[i] != 0xcccccccc,
1342                 "Regular output DWORD %d remained untouched\n", i);
1343     }
1344
1345     transformdata.lpIn = cliptest;
1346     transformdata.dwInSize = sizeof(cliptest[0]);
1347     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1348                                              &transformdata, D3DTRANSFORM_CLIPPED,
1349                                              &i);
1350     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1351     ok(i == 0, "Offscreen is %d\n", i);
1352     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1353         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1354         {
1355             0,
1356             0,
1357             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1358             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1359         };
1360         ok(Flags[i] == outH[i].dwFlags,
1361            "Cliptest %d differs. Got %08x expected %08x\n", i + 1,
1362            outH[i].dwFlags, Flags[i]);
1363     }
1364
1365     SET_VP_DATA(vp_data);
1366     vp_data.dwWidth = 10;
1367     vp_data.dwHeight = 1000;
1368     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1369     i = 10;
1370     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1371     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1372                                              &transformdata, D3DTRANSFORM_CLIPPED,
1373                                              &i);
1374     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1375     ok(i == 0, "Offscreen is %d\n", i);
1376     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1377         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1378         {
1379             D3DCLIP_RIGHT,
1380             D3DCLIP_LEFT,
1381             D3DCLIP_RIGHT | D3DCLIP_BACK,
1382             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1383         };
1384         ok(Flags[i] == outH[i].dwFlags,
1385            "Cliptest %d differs. Got %08x expected %08x\n", i + 1,
1386            outH[i].dwFlags, Flags[i]);
1387     }
1388
1389     SET_VP_DATA(vp_data);
1390     vp_data.dwWidth = 256;
1391     vp_data.dwHeight = 256;
1392     vp_data.dvScaleX = 1;
1393     vp_data.dvScaleY = 1;
1394     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1395     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1396     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1397                                              &transformdata, D3DTRANSFORM_CLIPPED,
1398                                              &i);
1399     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1400     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1401     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1402         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1403         {
1404             0,
1405             0,
1406             D3DCLIP_BACK,
1407             D3DCLIP_FRONT,
1408         };
1409         ok(Flags[i] == outH[i].dwFlags,
1410            "Cliptest %d differs. Got %08x expected %08x\n", i + 1,
1411            outH[i].dwFlags, Flags[i]);
1412     }
1413
1414     /* Finally try to figure out how the DWORD dwOffscreen works.
1415      * Apparently no vertex is offscreen with clipping off,
1416      * and with clipping on the offscreen flag is set if only one vertex
1417      * is transformed, and this vertex is offscreen.
1418      */
1419     SET_VP_DATA(vp_data);
1420     vp_data.dwWidth = 5;
1421     vp_data.dwHeight = 5;
1422     vp_data.dvScaleX = 10000;
1423     vp_data.dvScaleY = 10000;
1424     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1425     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1426     transformdata.lpIn = cliptest;
1427     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1428                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1429                                              &i);
1430     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1431     ok(i == 0, "Offscreen is %d\n", i);
1432     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1433                                              &transformdata, D3DTRANSFORM_CLIPPED,
1434                                              &i);
1435     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1436     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1437     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1438                                              &transformdata, D3DTRANSFORM_CLIPPED,
1439                                              &i);
1440     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1441     ok(i == 0, "Offscreen is %d\n", i);
1442     transformdata.lpIn = cliptest + 1;
1443     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1444                                              &transformdata, D3DTRANSFORM_CLIPPED,
1445                                              &i);
1446     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1447     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1448
1449     transformdata.lpIn = offscreentest;
1450     transformdata.dwInSize = sizeof(offscreentest[0]);
1451     SET_VP_DATA(vp_data);
1452     vp_data.dwWidth = 257;
1453     vp_data.dwHeight = 257;
1454     vp_data.dvScaleX = 1;
1455     vp_data.dvScaleY = 1;
1456     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1457     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1458     i = 12345;
1459     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1460                                              &transformdata, D3DTRANSFORM_CLIPPED,
1461                                              &i);
1462     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1463     ok(i == 0, "Offscreen is %d\n", i);
1464     vp_data.dwWidth = 256;
1465     vp_data.dwHeight = 256;
1466     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1467     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1468     i = 12345;
1469     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1470                                              &transformdata, D3DTRANSFORM_CLIPPED,
1471                                              &i);
1472     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1473     ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1474
1475     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1476                                              &transformdata, 0,
1477                                              &i);
1478     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1479
1480     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1481     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1482
1483     hr = IDirect3DViewport_AddLight(Viewport, Light);
1484     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1485     refcount = getRefcount((IUnknown*) Light);
1486     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1487
1488     hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1489     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1490     ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1491     refcount = getRefcount((IUnknown*) Light);
1492     ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1493
1494     hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1495     ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1496     refcount = getRefcount((IUnknown*) Light);
1497     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1498
1499     IDirect3DLight_Release(Light);
1500 }
1501
1502 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1503 {
1504     int i;
1505
1506     for (i = 0; i < 256; i++) {
1507        if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1508            table1[i].peBlue != table2[i].peBlue) return FALSE;
1509     }
1510
1511     return TRUE;
1512 }
1513
1514 /* test palette handling in IDirect3DTexture_Load */
1515 static void TextureLoadTest(void)
1516 {
1517     IDirectDrawSurface *TexSurface = NULL;
1518     IDirect3DTexture *Texture = NULL;
1519     IDirectDrawSurface *TexSurface2 = NULL;
1520     IDirect3DTexture *Texture2 = NULL;
1521     IDirectDrawPalette *palette = NULL;
1522     IDirectDrawPalette *palette2 = NULL;
1523     IDirectDrawPalette *palette_tmp = NULL;
1524     PALETTEENTRY table1[256], table2[256], table_tmp[256];
1525     HRESULT hr;
1526     DDSURFACEDESC ddsd;
1527     int i;
1528
1529     memset (&ddsd, 0, sizeof (ddsd));
1530     ddsd.dwSize = sizeof (ddsd);
1531     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1532     ddsd.dwHeight = 128;
1533     ddsd.dwWidth = 128;
1534     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1535     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1536     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1537     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1538
1539     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1540     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1541     if (FAILED(hr)) {
1542         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1543         goto cleanup;
1544     }
1545
1546     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1547                 (void *)&Texture);
1548     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1549     if (FAILED(hr)) {
1550         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1551         goto cleanup;
1552     }
1553
1554     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1555     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1556     if (FAILED(hr)) {
1557         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1558         goto cleanup;
1559     }
1560
1561     hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1562                 (void *)&Texture2);
1563     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1564     if (FAILED(hr)) {
1565         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1566         goto cleanup;
1567     }
1568
1569     /* test load of Texture to Texture */
1570     hr = IDirect3DTexture_Load(Texture, Texture);
1571     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1572
1573     /* test Load when both textures have no palette */
1574     hr = IDirect3DTexture_Load(Texture2, Texture);
1575     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1576
1577     for (i = 0; i < 256; i++) {
1578         table1[i].peRed = i;
1579         table1[i].peGreen = i;
1580         table1[i].peBlue = i;
1581         table1[i].peFlags = 0;
1582     }
1583
1584     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1585     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1586     if (FAILED(hr)) {
1587         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1588         goto cleanup;
1589     }
1590
1591     /* test Load when source texture has palette and destination has no palette */
1592     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1593     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1594     hr = IDirect3DTexture_Load(Texture2, Texture);
1595     ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1596
1597     for (i = 0; i < 256; i++) {
1598         table2[i].peRed = 255 - i;
1599         table2[i].peGreen = 255 - i;
1600         table2[i].peBlue = 255 - i;
1601         table2[i].peFlags = 0;
1602     }
1603
1604     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1605     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1606     if (FAILED(hr)) {
1607         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1608         goto cleanup;
1609     }
1610
1611     /* test Load when source has no palette and destination has a palette */
1612     hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1613     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1614     hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1615     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1616     hr = IDirect3DTexture_Load(Texture2, Texture);
1617     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1618     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1619     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1620     if (!palette_tmp) {
1621         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1622         goto cleanup;
1623     } else {
1624         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1625         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1626         ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1627         IDirectDrawPalette_Release(palette_tmp);
1628     }
1629
1630     /* test Load when both textures have palettes */
1631     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1632     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1633     hr = IDirect3DTexture_Load(Texture2, Texture);
1634     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1635     hr = IDirect3DTexture_Load(Texture2, Texture);
1636     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1637     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1638     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1639     if (!palette_tmp) {
1640         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1641         goto cleanup;
1642     } else {
1643         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1644         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1645         ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1646         IDirectDrawPalette_Release(palette_tmp);
1647     }
1648
1649     cleanup:
1650
1651     if (palette) IDirectDrawPalette_Release(palette);
1652     if (palette2) IDirectDrawPalette_Release(palette2);
1653     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1654     if (Texture) IDirect3DTexture_Release(Texture);
1655     if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1656     if (Texture2) IDirect3DTexture_Release(Texture2);
1657 }
1658
1659 static void VertexBufferDescTest(void)
1660 {
1661     HRESULT rc;
1662     D3DVERTEXBUFFERDESC desc;
1663     union mem_t
1664     {
1665         D3DVERTEXBUFFERDESC desc2;
1666         unsigned char buffer[512];
1667     } mem;
1668
1669     memset(&desc, 0, sizeof(desc));
1670     desc.dwSize = sizeof(desc);
1671     desc.dwCaps = 0;
1672     desc.dwFVF = D3DFVF_XYZ;
1673     desc.dwNumVertices = 1;
1674     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1675     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1676     if (!lpVBufSrc)
1677     {
1678         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1679         goto out;
1680     }
1681
1682     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1683     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1684     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1685     if(rc != D3D_OK)
1686         skip("GetVertexBuffer Failed!\n");
1687     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1688     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1689     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1690     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1691     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1692
1693     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1694     mem.desc2.dwSize = 0;
1695     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1696     if(rc != D3D_OK)
1697         skip("GetVertexBuffer Failed!\n");
1698     ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1699     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1700     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1701     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1702     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1703
1704     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1705     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1706     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1707     if(rc != D3D_OK)
1708         skip("GetVertexBuffer Failed!\n");
1709     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1710     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1711     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1712     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1713     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1714
1715 out:
1716     IDirect3DVertexBuffer7_Release(lpVBufSrc);
1717 }
1718
1719 static void D3D7_OldRenderStateTest(void)
1720 {
1721     HRESULT hr;
1722     DWORD val;
1723
1724     /* Test reaction to some deprecated states in D3D7. */
1725     hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1726     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1727     hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1728     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1729     hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1730     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1731     hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1732     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1733 }
1734
1735 #define IS_VALUE_NEAR(a, b)    ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1736 #define MIN(a, b)    ((a) < (b) ? (a) : (b))
1737
1738 static void DeviceLoadTest(void)
1739 {
1740     DDSURFACEDESC2 ddsd;
1741     IDirectDrawSurface7 *texture_levels[2][8];
1742     IDirectDrawSurface7 *cube_face_levels[2][6][8];
1743     DWORD flags;
1744     HRESULT hr;
1745     DDBLTFX ddbltfx;
1746     RECT loadrect;
1747     POINT loadpoint;
1748     int i, i1, i2;
1749     unsigned diff_count = 0, diff_count2 = 0;
1750     unsigned x, y;
1751     BOOL load_mip_subset_broken = FALSE;
1752     IDirectDrawPalette *palettes[5];
1753     PALETTEENTRY table1[256];
1754     DDCOLORKEY ddckey;
1755     D3DDEVICEDESC7 d3dcaps;
1756
1757     /* Test loading of texture subrectangle with a mipmap surface. */
1758     memset(texture_levels, 0, sizeof(texture_levels));
1759     memset(cube_face_levels, 0, sizeof(cube_face_levels));
1760     memset(palettes, 0, sizeof(palettes));
1761
1762     for (i = 0; i < 2; i++)
1763     {
1764         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1765         ddsd.dwSize = sizeof(ddsd);
1766         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1767         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1768         ddsd.dwWidth = 128;
1769         ddsd.dwHeight = 128;
1770         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1771         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1772         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1773         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1774         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1775         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1776         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1777         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1778         if (FAILED(hr)) goto out;
1779
1780         /* Check the number of created mipmaps */
1781         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1782         ddsd.dwSize = sizeof(ddsd);
1783         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1784         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1785         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1786         if (U2(ddsd).dwMipMapCount != 8) goto out;
1787
1788         for (i1 = 1; i1 < 8; i1++)
1789         {
1790             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1791             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1792             if (FAILED(hr)) goto out;
1793         }
1794     }
1795
1796     for (i1 = 0; i1 < 8; i1++)
1797     {
1798         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1799         ddsd.dwSize = sizeof(ddsd);
1800         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1801         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1802         if (FAILED(hr)) goto out;
1803
1804         for (y = 0 ; y < ddsd.dwHeight; y++)
1805         {
1806             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1807
1808             for (x = 0; x < ddsd.dwWidth;  x++)
1809             {
1810                 /* x stored in green component, y in blue. */
1811                 DWORD color = 0xff0000 | (x << 8)  | y;
1812                 *textureRow++ = color;
1813             }
1814         }
1815
1816         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1817         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1818     }
1819
1820     for (i1 = 0; i1 < 8; i1++)
1821     {
1822         memset(&ddbltfx, 0, sizeof(ddbltfx));
1823         ddbltfx.dwSize = sizeof(ddbltfx);
1824         U5(ddbltfx).dwFillColor = 0;
1825         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1826         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1827     }
1828
1829     /* First test some broken coordinates. */
1830     loadpoint.x = loadpoint.y = 0;
1831     loadrect.left = 0;
1832     loadrect.top = 0;
1833     loadrect.right = 0;
1834     loadrect.bottom = 0;
1835     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1836     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1837
1838     loadpoint.x = loadpoint.y = 50;
1839     loadrect.left = 0;
1840     loadrect.top = 0;
1841     loadrect.right = 100;
1842     loadrect.bottom = 100;
1843     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1844     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1845
1846     /* Test actual loading. */
1847     loadpoint.x = loadpoint.y = 31;
1848     loadrect.left = 30;
1849     loadrect.top = 20;
1850     loadrect.right = 93;
1851     loadrect.bottom = 52;
1852
1853     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1854     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1855
1856     for (i1 = 0; i1 < 8; i1++)
1857     {
1858         diff_count = 0;
1859         diff_count2 = 0;
1860
1861         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1862         ddsd.dwSize = sizeof(ddsd);
1863         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1864         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1865         if (FAILED(hr)) goto out;
1866
1867         for (y = 0 ; y < ddsd.dwHeight; y++)
1868         {
1869             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1870
1871             for (x = 0; x < ddsd.dwWidth;  x++)
1872             {
1873                 DWORD color = *textureRow++;
1874
1875                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1876                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1877                 {
1878                     if (color & 0xffffff) diff_count++;
1879                 }
1880                 else
1881                 {
1882                     DWORD r = (color & 0xff0000) >> 16;
1883                     DWORD g = (color & 0xff00) >> 8;
1884                     DWORD b = (color & 0xff);
1885
1886                     if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1887                 }
1888
1889                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1890                    technically be correct as it's not precisely defined by docs. */
1891                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1892                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1893                 {
1894                     if (color & 0xffffff) diff_count2++;
1895                 }
1896                 else
1897                 {
1898                     DWORD r = (color & 0xff0000) >> 16;
1899                     DWORD g = (color & 0xff00) >> 8;
1900                     DWORD b = (color & 0xff);
1901
1902                     if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1903                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1904                 }
1905             }
1906         }
1907
1908         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1909         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1910
1911         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1912                 MIN(diff_count, diff_count2), i1);
1913
1914         loadpoint.x /= 2;
1915         loadpoint.y /= 2;
1916         loadrect.top /= 2;
1917         loadrect.left /= 2;
1918         loadrect.right = (loadrect.right + 1) / 2;
1919         loadrect.bottom = (loadrect.bottom + 1) / 2;
1920     }
1921
1922     /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1923      * qemu Win98 / directx7 / RGB software rasterizer):
1924      * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1925     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1926     */
1927
1928     /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1929     for (i = 0; i < 2; i++)
1930     {
1931         for (i1 = 7; i1 >= 0; i1--)
1932         {
1933             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1934         }
1935     }
1936     memset(texture_levels, 0, sizeof(texture_levels));
1937
1938     /* Test texture size mismatch. */
1939     for (i = 0; i < 2; i++)
1940     {
1941         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1942         ddsd.dwSize = sizeof(ddsd);
1943         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1944         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1945         ddsd.dwWidth = i ? 256 : 128;
1946         ddsd.dwHeight = 128;
1947         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1948         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1949         if (FAILED(hr)) goto out;
1950     }
1951
1952     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1953     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1954
1955     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1956     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1957
1958     IDirectDrawSurface7_Release(texture_levels[0][0]);
1959     IDirectDrawSurface7_Release(texture_levels[1][0]);
1960     memset(texture_levels, 0, sizeof(texture_levels));
1961
1962     memset(&d3dcaps, 0, sizeof(d3dcaps));
1963     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1964     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1965
1966     if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1967     {
1968         skip("No cubemap support\n");
1969     }
1970     else
1971     {
1972         /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1973         for (i = 0; i < 2; i++)
1974         {
1975             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1976             ddsd.dwSize = sizeof(ddsd);
1977             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1978             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1979             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1980             ddsd.dwWidth = 128;
1981             ddsd.dwHeight = 128;
1982             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1983             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1984             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1985             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1986             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1987             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1988             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1989             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1990             if (FAILED(hr)) goto out;
1991
1992             flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1993             for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1994             {
1995                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1996                 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1997                 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1998                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1999                 if (FAILED(hr)) goto out;
2000             }
2001
2002             for (i1 = 0; i1 < 6; i1++)
2003             {
2004                 /* Check the number of created mipmaps */
2005                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2006                 ddsd.dwSize = sizeof(ddsd);
2007                 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
2008                 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2009                 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2010                 if (U2(ddsd).dwMipMapCount != 8) goto out;
2011
2012                 for (i2 = 1; i2 < 8; i2++)
2013                 {
2014                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
2015                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
2016                     hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
2017                     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2018                     if (FAILED(hr)) goto out;
2019                 }
2020             }
2021         }
2022
2023         for (i = 0; i < 6; i++)
2024             for (i1 = 0; i1 < 8; i1++)
2025             {
2026                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2027                 ddsd.dwSize = sizeof(ddsd);
2028                 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2029                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2030                 if (FAILED(hr)) goto out;
2031
2032                 for (y = 0 ; y < ddsd.dwHeight; y++)
2033                 {
2034                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2035
2036                     for (x = 0; x < ddsd.dwWidth;  x++)
2037                     {
2038                         /* face number in low 4 bits of red, x stored in green component, y in blue. */
2039                         DWORD color = 0xf00000 | (i << 16) | (x << 8)  | y;
2040                         *textureRow++ = color;
2041                     }
2042                 }
2043
2044                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
2045                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2046             }
2047
2048         for (i = 0; i < 6; i++)
2049             for (i1 = 0; i1 < 8; i1++)
2050             {
2051                 memset(&ddbltfx, 0, sizeof(ddbltfx));
2052                 ddbltfx.dwSize = sizeof(ddbltfx);
2053                 U5(ddbltfx).dwFillColor = 0;
2054                 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2055                 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2056             }
2057
2058         loadpoint.x = loadpoint.y = 10;
2059         loadrect.left = 30;
2060         loadrect.top = 20;
2061         loadrect.right = 93;
2062         loadrect.bottom = 52;
2063
2064         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2065                                         DDSCAPS2_CUBEMAP_ALLFACES);
2066         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2067
2068         for (i = 0; i < 6; i++)
2069         {
2070             loadpoint.x = loadpoint.y = 10;
2071             loadrect.left = 30;
2072             loadrect.top = 20;
2073             loadrect.right = 93;
2074             loadrect.bottom = 52;
2075
2076             for (i1 = 0; i1 < 8; i1++)
2077             {
2078                 diff_count = 0;
2079                 diff_count2 = 0;
2080
2081                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2082                 ddsd.dwSize = sizeof(ddsd);
2083                 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2084                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2085                 if (FAILED(hr)) goto out;
2086
2087                 for (y = 0 ; y < ddsd.dwHeight; y++)
2088                 {
2089                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2090
2091                     for (x = 0; x < ddsd.dwWidth;  x++)
2092                     {
2093                         DWORD color = *textureRow++;
2094
2095                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2096                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2097                         {
2098                             if (color & 0xffffff) diff_count++;
2099                         }
2100                         else
2101                         {
2102                             DWORD r = (color & 0xff0000) >> 16;
2103                             DWORD g = (color & 0xff00) >> 8;
2104                             DWORD b = (color & 0xff);
2105
2106                             if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2107                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2108                         }
2109
2110                         /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2111                         technically be correct as it's not precisely defined by docs. */
2112                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2113                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2114                         {
2115                             if (color & 0xffffff) diff_count2++;
2116                         }
2117                         else
2118                         {
2119                             DWORD r = (color & 0xff0000) >> 16;
2120                             DWORD g = (color & 0xff00) >> 8;
2121                             DWORD b = (color & 0xff);
2122
2123                             if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2124                                 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2125                         }
2126                     }
2127                 }
2128
2129                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2130                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2131
2132                 ok(diff_count == 0 || diff_count2 == 0,
2133                     "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2134                     MIN(diff_count, diff_count2), i, i1);
2135
2136                 loadpoint.x /= 2;
2137                 loadpoint.y /= 2;
2138                 loadrect.top /= 2;
2139                 loadrect.left /= 2;
2140                 loadrect.right = (loadrect.right + 1) / 2;
2141                 loadrect.bottom = (loadrect.bottom + 1) / 2;
2142             }
2143         }
2144
2145         for (i = 0; i < 2; i++)
2146             for (i1 = 5; i1 >= 0; i1--)
2147                 for (i2 = 7; i2 >= 0; i2--)
2148                 {
2149                     if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2150                 }
2151         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2152
2153         /* Test cubemap loading from regular texture. */
2154         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2155         ddsd.dwSize = sizeof(ddsd);
2156         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2157         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2158         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2159         ddsd.dwWidth = 128;
2160         ddsd.dwHeight = 128;
2161         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2162         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2163         if (FAILED(hr)) goto out;
2164
2165         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2166         ddsd.dwSize = sizeof(ddsd);
2167         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2168         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2169         ddsd.dwWidth = 128;
2170         ddsd.dwHeight = 128;
2171         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2172         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2173         if (FAILED(hr)) goto out;
2174
2175         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2176                                         DDSCAPS2_CUBEMAP_ALLFACES);
2177         ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2178
2179         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2180         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2181         IDirectDrawSurface7_Release(texture_levels[0][0]);
2182         memset(texture_levels, 0, sizeof(texture_levels));
2183
2184         /* Partial cube maps(e.g. created with an explicitly set DDSCAPS2_CUBEMAP_POSITIVEX flag)
2185          * BSOD some Windows machines when an app tries to create them(Radeon X1600, Windows XP,
2186          * Catalyst 10.2 driver, 6.14.10.6925)
2187          */
2188     }
2189
2190     /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2191     for (i = 0; i < 2; i++)
2192     {
2193         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2194         ddsd.dwSize = sizeof(ddsd);
2195         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2196         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2197         ddsd.dwWidth = 128;
2198         ddsd.dwHeight = 128;
2199         U2(ddsd).dwMipMapCount = i ? 4 : 8;
2200         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2201         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2202         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2203         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2204         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2205         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2206         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2207         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2208         if (FAILED(hr)) goto out;
2209
2210         /* Check the number of created mipmaps */
2211         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2212         ddsd.dwSize = sizeof(ddsd);
2213         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2214         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2215         ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2216         if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2217
2218         for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2219         {
2220             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2221             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2222             if (FAILED(hr)) goto out;
2223         }
2224     }
2225
2226     for (i1 = 0; i1 < 8; i1++)
2227     {
2228         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2229         ddsd.dwSize = sizeof(ddsd);
2230         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2231         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2232         if (FAILED(hr)) goto out;
2233
2234         for (y = 0 ; y < ddsd.dwHeight; y++)
2235         {
2236             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2237
2238             for (x = 0; x < ddsd.dwWidth;  x++)
2239             {
2240                 /* x stored in green component, y in blue. */
2241                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2242                 *textureRow++ = color;
2243             }
2244         }
2245
2246         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2247         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2248     }
2249
2250     for (i1 = 0; i1 < 4; i1++)
2251     {
2252         memset(&ddbltfx, 0, sizeof(ddbltfx));
2253         ddbltfx.dwSize = sizeof(ddbltfx);
2254         U5(ddbltfx).dwFillColor = 0;
2255         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2256         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2257     }
2258
2259     loadpoint.x = loadpoint.y = 31;
2260     loadrect.left = 30;
2261     loadrect.top = 20;
2262     loadrect.right = 93;
2263     loadrect.bottom = 52;
2264
2265     /* Destination mip levels are a subset of source mip levels. */
2266     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2267     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2268
2269     for (i1 = 0; i1 < 4; i1++)
2270     {
2271         diff_count = 0;
2272         diff_count2 = 0;
2273
2274         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2275         ddsd.dwSize = sizeof(ddsd);
2276         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2277         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2278         if (FAILED(hr)) goto out;
2279
2280         for (y = 0 ; y < ddsd.dwHeight; y++)
2281         {
2282             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2283
2284             for (x = 0; x < ddsd.dwWidth;  x++)
2285             {
2286                 DWORD color = *textureRow++;
2287
2288                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2289                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2290                 {
2291                     if (color & 0xffffff) diff_count++;
2292                 }
2293                 else
2294                 {
2295                     DWORD r = (color & 0xff0000) >> 16;
2296                     DWORD g = (color & 0xff00) >> 8;
2297                     DWORD b = (color & 0xff);
2298
2299                     if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2300                         b != y + loadrect.top - loadpoint.y) diff_count++;
2301                 }
2302
2303                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2304                 technically be correct as it's not precisely defined by docs. */
2305                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2306                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2307                 {
2308                     if (color & 0xffffff) diff_count2++;
2309                 }
2310                 else
2311                 {
2312                     DWORD r = (color & 0xff0000) >> 16;
2313                     DWORD g = (color & 0xff00) >> 8;
2314                     DWORD b = (color & 0xff);
2315
2316                     if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2317                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2318                 }
2319             }
2320         }
2321
2322         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2323         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2324
2325         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2326              MIN(diff_count, diff_count2), i1);
2327
2328         loadpoint.x /= 2;
2329         loadpoint.y /= 2;
2330         loadrect.top /= 2;
2331         loadrect.left /= 2;
2332         loadrect.right = (loadrect.right + 1) / 2;
2333         loadrect.bottom = (loadrect.bottom + 1) / 2;
2334     }
2335
2336     /* Destination mip levels are a superset of source mip levels (should fail). */
2337     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2338     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2339
2340     for (i = 0; i < 2; i++)
2341     {
2342         for (i1 = 7; i1 >= 0; i1--)
2343         {
2344             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2345         }
2346     }
2347     memset(texture_levels, 0, sizeof(texture_levels));
2348
2349     /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2350     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2351     ddsd.dwSize = sizeof(ddsd);
2352     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2353     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2354     ddsd.dwWidth = 128;
2355     ddsd.dwHeight = 128;
2356     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2357     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2358     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2359     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2360     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2361     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2362     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2363     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2364     if (FAILED(hr)) goto out;
2365
2366     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2367     ddsd.dwSize = sizeof(ddsd);
2368     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2369     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2370     ddsd.dwWidth = 32;
2371     ddsd.dwHeight = 32;
2372     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2373     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2374     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2375     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2376     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2377     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2378     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2379     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2380     if (FAILED(hr)) goto out;
2381
2382     for (i1 = 1; i1 < 8; i1++)
2383     {
2384         hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2385         ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2386         if (FAILED(hr)) goto out;
2387     }
2388
2389     for (i1 = 0; i1 < 8; i1++)
2390     {
2391         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2392         ddsd.dwSize = sizeof(ddsd);
2393         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2394         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2395         if (FAILED(hr)) goto out;
2396
2397         for (y = 0 ; y < ddsd.dwHeight; y++)
2398         {
2399             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2400
2401             for (x = 0; x < ddsd.dwWidth;  x++)
2402             {
2403                 /* x stored in green component, y in blue. */
2404                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2405                 *textureRow++ = color;
2406             }
2407         }
2408
2409         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2410         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2411     }
2412
2413     memset(&ddbltfx, 0, sizeof(ddbltfx));
2414     ddbltfx.dwSize = sizeof(ddbltfx);
2415     U5(ddbltfx).dwFillColor = 0;
2416     hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2417     ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2418
2419     loadpoint.x = loadpoint.y = 32;
2420     loadrect.left = 32;
2421     loadrect.top = 32;
2422     loadrect.right = 96;
2423     loadrect.bottom = 96;
2424
2425     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2426     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2427
2428     loadpoint.x /= 4;
2429     loadpoint.y /= 4;
2430     loadrect.top /= 4;
2431     loadrect.left /= 4;
2432     loadrect.right = (loadrect.right + 3) / 4;
2433     loadrect.bottom = (loadrect.bottom + 3) / 4;
2434
2435     /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2436      * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2437      * copied subrectangles divided more than needed, without apparent logic. But it works
2438      * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2439      * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2440      * The following code attempts to detect broken results, actual tests will then be skipped
2441      */
2442     load_mip_subset_broken = TRUE;
2443     diff_count = 0;
2444
2445     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2446     ddsd.dwSize = sizeof(ddsd);
2447     hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2448     ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2449     if (FAILED(hr)) goto out;
2450
2451     for (y = 0 ; y < ddsd.dwHeight; y++)
2452     {
2453         DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2454
2455         for (x = 0; x < ddsd.dwWidth;  x++)
2456         {
2457             DWORD color = *textureRow++;
2458
2459             if (x < 2 || x >= 2 + 4 ||
2460                 y < 2 || y >= 2 + 4)
2461             {
2462                 if (color & 0xffffff) diff_count++;
2463             }
2464             else
2465             {
2466                 DWORD r = (color & 0xff0000) >> 16;
2467
2468                 if ((r & (0xf0)) != 0xf0) diff_count++;
2469             }
2470         }
2471     }
2472
2473     if (diff_count) load_mip_subset_broken = FALSE;
2474
2475     if (load_mip_subset_broken) {
2476         skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2477     } else {
2478         diff_count = 0;
2479
2480         for (y = 0 ; y < ddsd.dwHeight; y++)
2481         {
2482             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2483
2484             for (x = 0; x < ddsd.dwWidth;  x++)
2485             {
2486                 DWORD color = *textureRow++;
2487
2488                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2489                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2490                 {
2491                     if (color & 0xffffff) diff_count++;
2492                 }
2493                 else
2494                 {
2495                     DWORD r = (color & 0xff0000) >> 16;
2496                     DWORD g = (color & 0xff00) >> 8;
2497                     DWORD b = (color & 0xff);
2498
2499                     if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2500                         b != y + loadrect.top - loadpoint.y) diff_count++;
2501                 }
2502             }
2503         }
2504     }
2505
2506     hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2507     ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2508
2509     ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2510
2511     for (i = 0; i < 2; i++)
2512     {
2513         for (i1 = 7; i1 >= 0; i1--)
2514         {
2515             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2516         }
2517     }
2518     memset(texture_levels, 0, sizeof(texture_levels));
2519
2520     if (!load_mip_subset_broken)
2521     {
2522         /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2523         * surface (than first source mip level)
2524         */
2525         for (i = 0; i < 2; i++)
2526         {
2527             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2528             ddsd.dwSize = sizeof(ddsd);
2529             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2530             if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2531             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2532             ddsd.dwWidth = i ? 32 : 128;
2533             ddsd.dwHeight = i ? 32 : 128;
2534             if (i) U2(ddsd).dwMipMapCount = 4;
2535             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2536             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2537             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2538             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2539             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2540             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2541             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2542             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2543             if (FAILED(hr)) goto out;
2544
2545             /* Check the number of created mipmaps */
2546             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2547             ddsd.dwSize = sizeof(ddsd);
2548             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2549             ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2550             ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2551             if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2552
2553             for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2554             {
2555                 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2556                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2557                 if (FAILED(hr)) goto out;
2558             }
2559         }
2560
2561         for (i1 = 0; i1 < 8; i1++)
2562         {
2563             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2564             ddsd.dwSize = sizeof(ddsd);
2565             hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2566             ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2567             if (FAILED(hr)) goto out;
2568
2569             for (y = 0 ; y < ddsd.dwHeight; y++)
2570             {
2571                 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2572
2573                 for (x = 0; x < ddsd.dwWidth;  x++)
2574                 {
2575                     /* x stored in green component, y in blue. */
2576                     DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2577                     *textureRow++ = color;
2578                 }
2579             }
2580
2581             hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2582             ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2583         }
2584
2585         for (i1 = 0; i1 < 4; i1++)
2586         {
2587             memset(&ddbltfx, 0, sizeof(ddbltfx));
2588             ddbltfx.dwSize = sizeof(ddbltfx);
2589             U5(ddbltfx).dwFillColor = 0;
2590             hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2591             ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2592         }
2593
2594         loadpoint.x = loadpoint.y = 0;
2595         loadrect.left = 0;
2596         loadrect.top = 0;
2597         loadrect.right = 64;
2598         loadrect.bottom = 64;
2599
2600         hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2601         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2602
2603         i = 0;
2604         for (i1 = 0; i1 < 8 && i < 4; i1++)
2605         {
2606             DDSURFACEDESC2 ddsd2;
2607
2608             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2609             ddsd.dwSize = sizeof(ddsd);
2610             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2611             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2612
2613             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2614             ddsd2.dwSize = sizeof(ddsd2);
2615             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2616             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2617
2618             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2619             {
2620                 diff_count = 0;
2621
2622                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2623                 ddsd.dwSize = sizeof(ddsd);
2624                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2625                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2626                 if (FAILED(hr)) goto out;
2627
2628                 for (y = 0 ; y < ddsd.dwHeight; y++)
2629                 {
2630                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2631
2632                     for (x = 0; x < ddsd.dwWidth;  x++)
2633                     {
2634                         DWORD color = *textureRow++;
2635
2636                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2637                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2638                         {
2639                             if (color & 0xffffff) diff_count++;
2640                         }
2641                         else
2642                         {
2643                             DWORD r = (color & 0xff0000) >> 16;
2644                             DWORD g = (color & 0xff00) >> 8;
2645                             DWORD b = (color & 0xff);
2646
2647                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2648                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2649                         }
2650                     }
2651                 }
2652
2653                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2654                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2655
2656                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2657
2658                 i++;
2659             }
2660
2661             loadpoint.x /= 2;
2662             loadpoint.y /= 2;
2663             loadrect.top /= 2;
2664             loadrect.left /= 2;
2665             loadrect.right = (loadrect.right + 1) / 2;
2666             loadrect.bottom = (loadrect.bottom + 1) / 2;
2667         }
2668
2669         for (i = 0; i < 2; i++)
2670         {
2671             for (i1 = 7; i1 >= 0; i1--)
2672             {
2673                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2674             }
2675         }
2676         memset(texture_levels, 0, sizeof(texture_levels));
2677     }
2678
2679     /* Test palette copying. */
2680     for (i = 0; i < 2; i++)
2681     {
2682         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2683         ddsd.dwSize = sizeof(ddsd);
2684         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2685         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2686         ddsd.dwWidth = 128;
2687         ddsd.dwHeight = 128;
2688         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2689         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2690         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2691         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2692         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2693         if (FAILED(hr)) goto out;
2694
2695         /* Check the number of created mipmaps */
2696         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2697         ddsd.dwSize = sizeof(ddsd);
2698         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2699         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2700         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2701         if (U2(ddsd).dwMipMapCount != 8) goto out;
2702
2703         for (i1 = 1; i1 < 8; i1++)
2704         {
2705             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2706             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2707             if (FAILED(hr)) goto out;
2708         }
2709     }
2710
2711     memset(table1, 0, sizeof(table1));
2712     for (i = 0; i < 3; i++)
2713     {
2714         table1[0].peBlue = i + 1;
2715         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2716         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2717         if (FAILED(hr))
2718         {
2719             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2720             goto out;
2721         }
2722     }
2723
2724     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2725     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2726
2727     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2728     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2729
2730     hr = IDirectDrawSurface7_GetPalette(texture_levels[0][1], &palettes[4]);
2731     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2732
2733     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2734     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2735
2736     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2737     ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2738     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2739     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2740
2741     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2742     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2743
2744     memset(table1, 0, sizeof(table1));
2745     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2746     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2747     if (SUCCEEDED(hr))
2748     {
2749         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2750         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2751         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2752     }
2753
2754     /* Test colorkey copying. */
2755     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2756     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2757     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2758     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2759     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2760
2761     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2762     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2763
2764     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2765     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2766
2767     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2768     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2769     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2770         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2771
2772     out:
2773
2774     for (i = 0; i < 5; i++)
2775     {
2776         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2777     }
2778
2779     for (i = 0; i < 2; i++)
2780     {
2781         for (i1 = 7; i1 >= 0; i1--)
2782         {
2783             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2784         }
2785     }
2786
2787     for (i = 0; i < 2; i++)
2788         for (i1 = 5; i1 >= 0; i1--)
2789             for (i2 = 7; i2 >= 0; i2--)
2790             {
2791                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2792             }
2793 }
2794
2795 static void SetMaterialTest(void)
2796 {
2797     HRESULT rc;
2798
2799     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2800     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2801 }
2802
2803 static void ComputeSphereVisibility(void)
2804 {
2805     D3DMATRIX proj, view, world;
2806     D3DVALUE radius[3];
2807     D3DVECTOR center[3];
2808     DWORD result[3];
2809     HRESULT rc;
2810
2811     world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2812     world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2813     world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2814     world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2815
2816     view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2817     view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2818     view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2819     view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2820
2821     proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2822     proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2823     proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2824     proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2825
2826     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2827     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2828     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2829
2830     U1(center[0]).x=11.461533;
2831     U2(center[0]).y=-4.761727;
2832     U3(center[0]).z=-1.171646;
2833
2834     radius[0]=38.252632;
2835
2836     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2837
2838     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2839     ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2840
2841     U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
2842     radius[0]=4.354097;
2843     U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
2844     radius[1]=12.500704;
2845     U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
2846     radius[2]=17.251318;
2847
2848     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2849
2850     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2851     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2852     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2853     ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2854     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2855     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2856
2857     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2858     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2859     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2860     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2861
2862     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2863     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2864     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2865     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2866
2867     U1(center[0]).x=0.0;
2868     U2(center[0]).y=0.0;
2869     U3(center[0]).z=0.05;
2870
2871     radius[0]=0.04;
2872
2873     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2874     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2875
2876     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2877
2878     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2879     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2880
2881     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2882     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2883     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2884     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2885
2886     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2887
2888     U1(center[0]).x=0.0;
2889     U2(center[0]).y=0.0;
2890     U3(center[0]).z=0.5;
2891
2892     radius[0]=0.5;
2893
2894     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2895
2896     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2897     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2898
2899     U1(center[0]).x=0.0;
2900     U2(center[0]).y=0.0;
2901     U3(center[0]).z=0.0;
2902
2903     radius[0]=0.0;
2904
2905     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2906
2907     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2908     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2909
2910     U1(center[0]).x=-1.0;
2911     U2(center[0]).y=-1.0;
2912     U3(center[0]).z=0.50;
2913
2914     radius[0]=0.25;
2915
2916     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2917
2918     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2919     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
2920
2921     U1(center[0]).x=-20.0;
2922     U2(center[0]).y=0.0;
2923     U3(center[0]).z=0.50;
2924
2925     radius[0]=3.0;
2926
2927     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2928
2929     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2930     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2931
2932     U1(center[0]).x=20.0;
2933     U2(center[0]).y=0.0;
2934     U3(center[0]).z=0.50;
2935
2936     radius[0]=3.0f;
2937
2938     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2939
2940     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2941     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
2942
2943     U1(center[0]).x=0.0;
2944     U2(center[0]).y=-20.0;
2945     U3(center[0]).z=0.50;
2946
2947     radius[0]=3.0;
2948
2949     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2950
2951     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2952     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
2953
2954     U1(center[0]).x=0.0;
2955     U2(center[0]).y=20.0;
2956     U3(center[0]).z=0.5;
2957
2958     radius[0]=3.0;
2959
2960     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2961
2962     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2963     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
2964
2965     U1(center[0]).x=0.0;
2966     U2(center[0]).y=0.0;
2967     U3(center[0]).z=-20;
2968
2969     radius[0]=3.0;
2970
2971     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2972
2973     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2974     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
2975
2976     U1(center[0]).x=0.0;
2977     U2(center[0]).y=0.0;
2978     U3(center[0]).z=20.0;
2979
2980     radius[0]=3.0;
2981
2982     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2983
2984     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2985     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
2986 }
2987
2988 static void SetRenderTargetTest(void)
2989 {
2990     HRESULT hr;
2991     IDirectDrawSurface7 *newrt, *failrt, *oldrt, *temprt;
2992     D3DVIEWPORT7 vp;
2993     DDSURFACEDESC2 ddsd, ddsd2;
2994     DWORD stateblock;
2995     ULONG refcount;
2996
2997     memset(&ddsd, 0, sizeof(ddsd));
2998     ddsd.dwSize = sizeof(ddsd);
2999     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3000     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
3001     ddsd.dwWidth = 64;
3002     ddsd.dwHeight = 64;
3003
3004     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
3005     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3006     if(FAILED(hr))
3007     {
3008         skip("Skipping SetRenderTarget test\n");
3009         return;
3010     }
3011
3012     memset(&ddsd2, 0, sizeof(ddsd2));
3013     ddsd2.dwSize = sizeof(ddsd2);
3014     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3015     ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER;
3016     ddsd2.dwWidth = 64;
3017     ddsd2.dwHeight = 64;
3018     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
3019     U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3020     U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3021     U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3022
3023     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd2, &failrt, NULL);
3024     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3025
3026     memset(&vp, 0, sizeof(vp));
3027     vp.dwX = 10;
3028     vp.dwY = 10;
3029     vp.dwWidth = 246;
3030     vp.dwHeight = 246;
3031     vp.dvMinZ = 0.25;
3032     vp.dvMaxZ = 0.75;
3033     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3034     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3035
3036     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3037     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3038
3039     refcount = getRefcount((IUnknown*) oldrt);
3040     ok(refcount == 3, "Refcount should be 3, returned is %d\n", refcount);
3041
3042     refcount = getRefcount((IUnknown*) failrt);
3043     ok(refcount == 1, "Refcount should be 1, returned is %d\n", refcount);
3044
3045     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, failrt, 0);
3046     ok(hr != D3D_OK, "IDirect3DDevice7_SetRenderTarget succeeded\n");
3047
3048     refcount = getRefcount((IUnknown*) oldrt);
3049     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3050
3051     refcount = getRefcount((IUnknown*) failrt);
3052     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3053
3054     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &temprt);
3055     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3056     ok(failrt == temprt, "Wrong iface returned\n");
3057
3058     refcount = getRefcount((IUnknown*) failrt);
3059     ok(refcount == 3, "Refcount should be 3, returned is %d\n", refcount);
3060
3061     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3062     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3063
3064     refcount = getRefcount((IUnknown*) failrt);
3065     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3066
3067     memset(&vp, 0xff, sizeof(vp));
3068     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3069     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3070     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3071     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3072     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3073     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3074     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.25\n", vp.dvMinZ);
3075     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.75\n", vp.dvMaxZ);
3076
3077     memset(&vp, 0, sizeof(vp));
3078     vp.dwX = 0;
3079     vp.dwY = 0;
3080     vp.dwWidth = 64;
3081     vp.dwHeight = 64;
3082     vp.dvMinZ = 0.0;
3083     vp.dvMaxZ = 1.0;
3084     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3085     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3086
3087     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3088     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3089     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3090     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3091
3092     /* Check this twice, before and after ending the stateblock */
3093     memset(&vp, 0xff, sizeof(vp));
3094     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3095     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3096     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3097     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3098     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3099     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3100     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3101     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3102
3103     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3104     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3105
3106     memset(&vp, 0xff, sizeof(vp));
3107     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3108     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3109     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3110     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3111     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3112     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3113     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3114     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3115
3116     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3117     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3118
3119     memset(&vp, 0, sizeof(vp));
3120     vp.dwX = 0;
3121     vp.dwY = 0;
3122     vp.dwWidth = 256;
3123     vp.dwHeight = 256;
3124     vp.dvMinZ = 0.0;
3125     vp.dvMaxZ = 0.0;
3126     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3127     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3128
3129     IDirectDrawSurface7_Release(oldrt);
3130     IDirectDrawSurface7_Release(newrt);
3131     IDirectDrawSurface7_Release(failrt);
3132     IDirectDrawSurface7_Release(failrt);
3133 }
3134
3135 static const UINT *expect_messages;
3136
3137 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3138 {
3139     if (expect_messages && message == *expect_messages) ++expect_messages;
3140
3141     return DefWindowProcA(hwnd, message, wparam, lparam);
3142 }
3143
3144 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
3145  * interface. This prevents subsequent SetCooperativeLevel() calls on a
3146  * different window from failing with DDERR_HWNDALREADYSET. */
3147 static void fix_wndproc(HWND window, LONG_PTR proc)
3148 {
3149     IDirectDraw7 *ddraw7;
3150     HRESULT hr;
3151
3152     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3153     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 object, hr %#x.\n", hr);
3154     if (FAILED(hr)) return;
3155
3156     SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
3157     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3158     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3159     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3160     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3161
3162     IDirectDraw7_Release(ddraw7);
3163 }
3164
3165 static void test_wndproc(void)
3166 {
3167     LONG_PTR proc, ddraw_proc;
3168     IDirectDraw7 *ddraw7;
3169     WNDCLASSA wc = {0};
3170     HWND window;
3171     HRESULT hr;
3172     ULONG ref;
3173
3174     static const UINT messages[] =
3175     {
3176         WM_WINDOWPOSCHANGING,
3177         WM_MOVE,
3178         WM_SIZE,
3179         WM_WINDOWPOSCHANGING,
3180         WM_ACTIVATE,
3181         WM_SETFOCUS,
3182         0,
3183     };
3184
3185     /* DDSCL_EXCLUSIVE replaces the window's window proc. */
3186     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3187     if (FAILED(hr))
3188     {
3189         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3190         return;
3191     }
3192
3193     wc.lpfnWndProc = test_proc;
3194     wc.lpszClassName = "d3d7_test_wndproc_wc";
3195     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3196
3197     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test",
3198             WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3199
3200     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3201     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3202             (LONG_PTR)test_proc, proc);
3203
3204     expect_messages = messages;
3205
3206     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3207     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3208     if (FAILED(hr))
3209     {
3210         IDirectDraw7_Release(ddraw7);
3211         goto done;
3212     }
3213
3214     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3215     expect_messages = NULL;
3216
3217     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3218     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3219             (LONG_PTR)test_proc, proc);
3220
3221     ref = IDirectDraw7_Release(ddraw7);
3222     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3223
3224     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3225     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3226             (LONG_PTR)test_proc, proc);
3227
3228     /* DDSCL_NORMAL doesn't. */
3229     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3230     if (FAILED(hr))
3231     {
3232         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3233         return;
3234     }
3235
3236     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3237     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3238             (LONG_PTR)test_proc, proc);
3239
3240     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3241     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3242     if (FAILED(hr))
3243     {
3244         IDirectDraw7_Release(ddraw7);
3245         goto done;
3246     }
3247
3248     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3249     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3250             (LONG_PTR)test_proc, proc);
3251
3252     ref = IDirectDraw7_Release(ddraw7);
3253     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3254
3255     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3256     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3257             (LONG_PTR)test_proc, proc);
3258
3259     /* The original window proc is only restored by ddraw if the current
3260      * window proc matches the one ddraw set. This also affects switching
3261      * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
3262     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3263     if (FAILED(hr))
3264     {
3265         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3266         return;
3267     }
3268
3269     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3270     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3271             (LONG_PTR)test_proc, proc);
3272
3273     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3274     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3275     if (FAILED(hr))
3276     {
3277         IDirectDraw7_Release(ddraw7);
3278         goto done;
3279     }
3280
3281     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3282     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3283             (LONG_PTR)test_proc, proc);
3284     ddraw_proc = proc;
3285
3286     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3287     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3288     if (FAILED(hr))
3289     {
3290         IDirectDraw7_Release(ddraw7);
3291         goto done;
3292     }
3293
3294     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3295     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3296             (LONG_PTR)test_proc, proc);
3297
3298     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3299     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3300     if (FAILED(hr))
3301     {
3302         IDirectDraw7_Release(ddraw7);
3303         goto done;
3304     }
3305
3306     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3307     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3308             (LONG_PTR)test_proc, proc);
3309
3310     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3311     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3312     if (FAILED(hr))
3313     {
3314         IDirectDraw7_Release(ddraw7);
3315         goto done;
3316     }
3317
3318     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3319     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3320             (LONG_PTR)DefWindowProcA, proc);
3321
3322     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3323     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3324     if (FAILED(hr))
3325     {
3326         IDirectDraw7_Release(ddraw7);
3327         goto done;
3328     }
3329
3330     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
3331     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3332             (LONG_PTR)DefWindowProcA, proc);
3333
3334     ref = IDirectDraw7_Release(ddraw7);
3335     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3336
3337     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3338     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3339             (LONG_PTR)test_proc, proc);
3340
3341     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3342     if (FAILED(hr))
3343     {
3344         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3345         return;
3346     }
3347
3348     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3349     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3350             (LONG_PTR)test_proc, proc);
3351
3352     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3353     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3354     if (FAILED(hr))
3355     {
3356         IDirectDraw7_Release(ddraw7);
3357         goto done;
3358     }
3359
3360     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3361     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3362             (LONG_PTR)test_proc, proc);
3363
3364     ref = IDirectDraw7_Release(ddraw7);
3365     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3366
3367     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3368     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3369             (LONG_PTR)DefWindowProcA, proc);
3370
3371 done:
3372     fix_wndproc(window, (LONG_PTR)test_proc);
3373     expect_messages = NULL;
3374     DestroyWindow(window);
3375     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
3376 }
3377
3378 static void VertexBufferLockRest(void)
3379 {
3380     D3DVERTEXBUFFERDESC desc;
3381     IDirect3DVertexBuffer7 *buffer;
3382     HRESULT hr;
3383     unsigned int i;
3384     void *data;
3385     const struct
3386     {
3387         DWORD flags;
3388         const char *debug_string;
3389         HRESULT result;
3390     }
3391     test_data[] =
3392     {
3393         {0,                                         "(none)",                                       D3D_OK },
3394         {DDLOCK_WAIT,                               "DDLOCK_WAIT",                                  D3D_OK },
3395         {DDLOCK_EVENT,                              "DDLOCK_EVENT",                                 D3D_OK },
3396         {DDLOCK_READONLY,                           "DDLOCK_READONLY",                              D3D_OK },
3397         {DDLOCK_WRITEONLY,                          "DDLOCK_WRITEONLY",                             D3D_OK },
3398         {DDLOCK_NOSYSLOCK,                          "DDLOCK_NOSYSLOCK",                             D3D_OK },
3399         {DDLOCK_NOOVERWRITE,                        "DDLOCK_NOOVERWRITE",                           D3D_OK },
3400         {DDLOCK_DISCARDCONTENTS,                    "DDLOCK_DISCARDCONTENTS",                       D3D_OK },
3401
3402         {DDLOCK_READONLY | DDLOCK_WRITEONLY,        "DDLOCK_READONLY | DDLOCK_WRITEONLY",           D3D_OK },
3403         {DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS,  "DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS",     D3D_OK },
3404         {0xdeadbeef,                                "0xdeadbeef",                                   D3D_OK },
3405     };
3406
3407     memset(&desc, 0 , sizeof(desc));
3408     desc.dwSize = sizeof(desc);
3409     desc.dwCaps = 0;
3410     desc.dwFVF = D3DFVF_XYZ;
3411     desc.dwNumVertices = 64;
3412     hr = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &buffer, 0);
3413     ok(hr == D3D_OK, "IDirect3D7_CreateVertexBuffer failed, 0x%08x\n", hr);
3414
3415     for(i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
3416     {
3417         hr = IDirect3DVertexBuffer7_Lock(buffer, test_data[i].flags, &data, NULL);
3418         ok(hr == test_data[i].result, "Lock flags %s returned 0x%08x, expected 0x%08x\n",
3419             test_data[i].debug_string, hr, test_data[i].result);
3420         if(SUCCEEDED(hr))
3421         {
3422             ok(data != NULL, "The data pointer returned by Lock is NULL\n");
3423             hr = IDirect3DVertexBuffer7_Unlock(buffer);
3424             ok(hr == D3D_OK, "IDirect3DVertexBuffer7_Unlock failed, 0x%08x\n", hr);
3425         }
3426     }
3427
3428     IDirect3DVertexBuffer7_Release(buffer);
3429 }
3430
3431 static void FindDevice(void)
3432 {
3433     static const struct
3434     {
3435         const GUID *guid;
3436         int todo;
3437     } deviceGUIDs[] =
3438     {
3439         {&IID_IDirect3DRampDevice, 1},
3440         {&IID_IDirect3DRGBDevice},
3441     };
3442
3443     static const GUID *nonexistent_deviceGUIDs[] = {&IID_IDirect3DMMXDevice,
3444                                                     &IID_IDirect3DRefDevice,
3445                                                     &IID_IDirect3DTnLHalDevice,
3446                                                     &IID_IDirect3DNullDevice};
3447
3448     D3DFINDDEVICESEARCH search = {0};
3449     D3DFINDDEVICERESULT result = {0};
3450     IDirect3DDevice *d3dhal;
3451     HRESULT hr;
3452     int i;
3453
3454     /* Test invalid parameters. */
3455     hr = IDirect3D_FindDevice(Direct3D1, NULL, NULL);
3456     ok(hr == DDERR_INVALIDPARAMS,
3457        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3458
3459     hr = IDirect3D_FindDevice(Direct3D1, NULL, &result);
3460     ok(hr == DDERR_INVALIDPARAMS,
3461        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3462
3463     hr = IDirect3D_FindDevice(Direct3D1, &search, NULL);
3464     ok(hr == DDERR_INVALIDPARAMS,
3465        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3466
3467     search.dwSize = 0;
3468     result.dwSize = 0;
3469
3470     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3471     ok(hr == DDERR_INVALIDPARAMS,
3472        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3473
3474     search.dwSize = sizeof(search) + 1;
3475     result.dwSize = sizeof(result) + 1;
3476
3477     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3478     ok(hr == DDERR_INVALIDPARAMS,
3479        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3480
3481     /* Specifying no flags is permitted. */
3482     search.dwSize = sizeof(search);
3483     search.dwFlags = 0;
3484     result.dwSize = sizeof(result);
3485
3486     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3487     ok(hr == D3D_OK,
3488        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3489
3490     /* Try an arbitrary non-device GUID. */
3491     search.dwSize = sizeof(search);
3492     search.dwFlags = D3DFDS_GUID;
3493     search.guid = IID_IDirect3D;
3494     result.dwSize = sizeof(result);
3495
3496     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3497     ok(hr == DDERR_NOTFOUND,
3498        "Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", hr);
3499
3500     /* These GUIDs appear to be never present. */
3501     for (i = 0; i < sizeof(nonexistent_deviceGUIDs)/sizeof(nonexistent_deviceGUIDs[0]); i++)
3502     {
3503         search.dwSize = sizeof(search);
3504         search.dwFlags = D3DFDS_GUID;
3505         search.guid = *nonexistent_deviceGUIDs[i];
3506         result.dwSize = sizeof(result);
3507
3508         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3509         ok(hr == DDERR_NOTFOUND,
3510            "[%d] Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", i, hr);
3511     }
3512
3513     /* The HAL device can only be enumerated if hardware acceleration is present. */
3514     search.dwSize = sizeof(search);
3515     search.dwFlags = D3DFDS_GUID;
3516     search.guid = IID_IDirect3DHALDevice;
3517     result.dwSize = sizeof(result);
3518
3519     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3520     trace("IDirect3D::FindDevice returned 0x%08x for the HAL device GUID\n", hr);
3521     if (SUCCEEDED(hr))
3522     {
3523         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3524         /* Currently Wine only supports the creation of one Direct3D device
3525          * for a given DirectDraw instance. */
3526         todo_wine
3527         ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
3528            "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3529
3530         if (SUCCEEDED(hr))
3531             IDirect3DDevice_Release(d3dhal);
3532     }
3533     else
3534     {
3535         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3536         ok(FAILED(hr), "Expected IDirectDrawSurface::QueryInterface to fail, got 0x%08x\n", hr);
3537
3538         if (SUCCEEDED(hr))
3539             IDirect3DDevice_Release(d3dhal);
3540     }
3541
3542     /* These GUIDs appear to be always present. */
3543     for (i = 0; i < sizeof(deviceGUIDs)/sizeof(deviceGUIDs[0]); i++)
3544     {
3545         search.dwSize = sizeof(search);
3546         search.dwFlags = D3DFDS_GUID;
3547         search.guid = *deviceGUIDs[i].guid;
3548         result.dwSize = sizeof(result);
3549
3550         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3551
3552         if (deviceGUIDs[i].todo)
3553         {
3554             todo_wine
3555             ok(hr == D3D_OK,
3556                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3557         }
3558         else
3559         {
3560             ok(hr == D3D_OK,
3561                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3562         }
3563     }
3564
3565     /* Curiously the color model criteria seem to be ignored. */
3566     search.dwSize = sizeof(search);
3567     search.dwFlags = D3DFDS_COLORMODEL;
3568     search.dcmColorModel = 0xdeadbeef;
3569     result.dwSize = sizeof(result);
3570
3571     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3572     todo_wine
3573     ok(hr == D3D_OK,
3574        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3575 }
3576
3577 static void BackBuffer3DCreateSurfaceTest(void)
3578 {
3579     DDSURFACEDESC ddsd;
3580     DDSURFACEDESC created_ddsd;
3581     DDSURFACEDESC2 ddsd2;
3582     IDirectDrawSurface *surf;
3583     IDirectDrawSurface4 *surf4;
3584     IDirectDrawSurface7 *surf7;
3585     HRESULT hr;
3586     IDirectDraw2 *dd2;
3587     IDirectDraw4 *dd4;
3588     IDirectDraw7 *dd7;
3589     DDCAPS ddcaps;
3590     IDirect3DDevice *d3dhal;
3591
3592     const DWORD caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3593     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3594
3595     memset(&ddcaps, 0, sizeof(ddcaps));
3596     ddcaps.dwSize = sizeof(DDCAPS);
3597     hr = IDirectDraw_GetCaps(DirectDraw1, &ddcaps, NULL);
3598     ok(SUCCEEDED(hr), "DirectDraw_GetCaps failed: 0x%08x\n", hr);
3599     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3600     {
3601         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3602         return ;
3603     }
3604
3605     memset(&ddsd, 0, sizeof(ddsd));
3606     ddsd.dwSize = sizeof(ddsd);
3607     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3608     ddsd.dwWidth = 64;
3609     ddsd.dwHeight = 64;
3610     ddsd.ddsCaps.dwCaps = caps;
3611     memset(&ddsd2, 0, sizeof(ddsd2));
3612     ddsd2.dwSize = sizeof(ddsd2);
3613     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3614     ddsd2.dwWidth = 64;
3615     ddsd2.dwHeight = 64;
3616     ddsd2.ddsCaps.dwCaps = caps;
3617     memset(&created_ddsd, 0, sizeof(created_ddsd));
3618     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3619
3620     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
3621     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3622     if (surf != NULL)
3623     {
3624         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3625         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3626         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3627            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3628            expected_caps);
3629
3630         hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3631         /* Currently Wine only supports the creation of one Direct3D device
3632            for a given DirectDraw instance. It has been created already
3633            in D3D1_createObjects() - IID_IDirect3DRGBDevice */
3634         todo_wine ok(SUCCEEDED(hr), "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3635
3636         if (SUCCEEDED(hr))
3637             IDirect3DDevice_Release(d3dhal);
3638
3639         IDirectDrawSurface_Release(surf);
3640     }
3641
3642     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw2, (void **) &dd2);
3643     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3644
3645     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3646     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3647        DDERR_INVALIDCAPS, hr);
3648
3649     IDirectDraw2_Release(dd2);
3650
3651     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void **) &dd4);
3652     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3653
3654     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3655     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3656        DDERR_INVALIDCAPS, hr);
3657
3658     IDirectDraw4_Release(dd4);
3659
3660     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw7, (void **) &dd7);
3661     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3662
3663     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3664     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3665        DDERR_INVALIDCAPS, hr);
3666
3667     IDirectDraw7_Release(dd7);
3668 }
3669
3670 static void BackBuffer3DAttachmentTest(void)
3671 {
3672     HRESULT hr;
3673     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3674     DDSURFACEDESC ddsd;
3675     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3676
3677     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3678     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3679
3680     /* Perform attachment tests on a back-buffer */
3681     memset(&ddsd, 0, sizeof(ddsd));
3682     ddsd.dwSize = sizeof(ddsd);
3683     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3684     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3685     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3686     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3687     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface2, NULL);
3688     ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3689
3690     if (surface2 != NULL)
3691     {
3692         /* Try a single primary and a two back buffers */
3693         memset(&ddsd, 0, sizeof(ddsd));
3694         ddsd.dwSize = sizeof(ddsd);
3695         ddsd.dwFlags = DDSD_CAPS;
3696         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3697         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface1, NULL);
3698         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3699
3700         memset(&ddsd, 0, sizeof(ddsd));
3701         ddsd.dwSize = sizeof(ddsd);
3702         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3703         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3704         ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3705         ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3706         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface3, NULL);
3707         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3708
3709         /* This one has a different size */
3710         memset(&ddsd, 0, sizeof(ddsd));
3711         ddsd.dwSize = sizeof(ddsd);
3712         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3713         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3714         ddsd.dwWidth = 128;
3715         ddsd.dwHeight = 128;
3716         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface4, NULL);
3717         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3718
3719         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3720         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3721            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3722         if(SUCCEEDED(hr))
3723         {
3724             /* Try the reverse without detaching first */
3725             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3726             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3727             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3728             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3729         }
3730         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3731         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3732            "Attaching a front buffer to a back buffer returned %08x\n", hr);
3733         if(SUCCEEDED(hr))
3734         {
3735             /* Try to detach reversed */
3736             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3737             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3738             /* Now the proper detach */
3739             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3740             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3741         }
3742         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3743         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3744            "Attaching a back buffer to another back buffer returned %08x\n", hr);
3745         if(SUCCEEDED(hr))
3746         {
3747             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
3748             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3749         }
3750         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
3751         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
3752         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
3753         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
3754
3755         IDirectDrawSurface_Release(surface4);
3756         IDirectDrawSurface_Release(surface3);
3757         IDirectDrawSurface_Release(surface2);
3758         IDirectDrawSurface_Release(surface1);
3759     }
3760
3761     hr =IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
3762     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3763
3764     DestroyWindow(window);
3765 }
3766
3767 static void test_window_style(void)
3768 {
3769     LONG style, exstyle, tmp;
3770     RECT fullscreen_rect, r;
3771     IDirectDraw7 *ddraw7;
3772     HWND window;
3773     HRESULT hr;
3774     ULONG ref;
3775
3776     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3777     if (FAILED(hr))
3778     {
3779         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3780         return;
3781     }
3782
3783     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
3784             0, 0, 100, 100, 0, 0, 0, 0);
3785
3786     style = GetWindowLongA(window, GWL_STYLE);
3787     exstyle = GetWindowLongA(window, GWL_EXSTYLE);
3788     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
3789
3790     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3791     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3792     if (FAILED(hr))
3793     {
3794         IDirectDraw7_Release(ddraw7);
3795         DestroyWindow(window);
3796         return;
3797     }
3798
3799     tmp = GetWindowLongA(window, GWL_STYLE);
3800     todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
3801     tmp = GetWindowLongA(window, GWL_EXSTYLE);
3802     todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
3803
3804     GetWindowRect(window, &r);
3805     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3806             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3807             r.left, r.top, r.right, r.bottom);
3808     GetClientRect(window, &r);
3809     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3810
3811     ref = IDirectDraw7_Release(ddraw7);
3812     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3813
3814     DestroyWindow(window);
3815 }
3816
3817 static void test_redundant_mode_set(void)
3818 {
3819     DDSURFACEDESC2 surface_desc = {0};
3820     IDirectDraw7 *ddraw7;
3821     HWND window;
3822     HRESULT hr;
3823     RECT r, s;
3824     ULONG ref;
3825
3826     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3827     if (FAILED(hr))
3828     {
3829         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3830         return;
3831     }
3832
3833     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
3834             0, 0, 100, 100, 0, 0, 0, 0);
3835
3836     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3837     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3838     if (FAILED(hr))
3839     {
3840         IDirectDraw7_Release(ddraw7);
3841         DestroyWindow(window);
3842         return;
3843     }
3844
3845     surface_desc.dwSize = sizeof(surface_desc);
3846     hr = IDirectDraw7_GetDisplayMode(ddraw7, &surface_desc);
3847     ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
3848
3849     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
3850             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3851     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3852
3853     GetWindowRect(window, &r);
3854     r.right /= 2;
3855     r.bottom /= 2;
3856     SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
3857     GetWindowRect(window, &s);
3858     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3859             r.left, r.top, r.right, r.bottom,
3860             s.left, s.top, s.right, s.bottom);
3861
3862     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
3863             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3864     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3865
3866     GetWindowRect(window, &s);
3867     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3868             r.left, r.top, r.right, r.bottom,
3869             s.left, s.top, s.right, s.bottom);
3870
3871     ref = IDirectDraw7_Release(ddraw7);
3872     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3873
3874     DestroyWindow(window);
3875 }
3876
3877 static SIZE screen_size;
3878
3879 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3880 {
3881     if (message == WM_SIZE)
3882     {
3883         screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
3884         screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
3885     }
3886
3887     return test_proc(hwnd, message, wparam, lparam);
3888 }
3889
3890 static void test_coop_level_mode_set(void)
3891 {
3892     IDirectDrawSurface7 *primary;
3893     RECT fullscreen_rect, r, s;
3894     IDirectDraw7 *ddraw7;
3895     DDSURFACEDESC2 ddsd;
3896     WNDCLASSA wc = {0};
3897     HWND window;
3898     HRESULT hr;
3899     ULONG ref;
3900
3901     static const UINT exclusive_messages[] =
3902     {
3903         WM_WINDOWPOSCHANGING,
3904         WM_WINDOWPOSCHANGED,
3905         WM_SIZE,
3906         WM_DISPLAYCHANGE,
3907         0,
3908     };
3909
3910     static const UINT normal_messages[] =
3911     {
3912         WM_DISPLAYCHANGE,
3913         0,
3914     };
3915
3916     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3917     if (FAILED(hr))
3918     {
3919         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3920         return;
3921     }
3922
3923     wc.lpfnWndProc = mode_set_proc;
3924     wc.lpszClassName = "d3d7_test_wndproc_wc";
3925     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3926
3927     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
3928             0, 0, 100, 100, 0, 0, 0, 0);
3929
3930     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
3931     SetRect(&s, 0, 0, 640, 480);
3932
3933     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3934     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3935     if (FAILED(hr))
3936     {
3937         IDirectDraw7_Release(ddraw7);
3938         goto done;
3939     }
3940
3941     GetWindowRect(window, &r);
3942     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3943             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3944             r.left, r.top, r.right, r.bottom);
3945
3946     memset(&ddsd, 0, sizeof(ddsd));
3947     ddsd.dwSize = sizeof(ddsd);
3948     ddsd.dwFlags = DDSD_CAPS;
3949     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3950
3951     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3952     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3953     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3954     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3955     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3956             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3957     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3958             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3959
3960     GetWindowRect(window, &r);
3961     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3962             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3963             r.left, r.top, r.right, r.bottom);
3964
3965     expect_messages = exclusive_messages;
3966     screen_size.cx = 0;
3967     screen_size.cy = 0;
3968
3969     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
3970     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3971
3972     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3973     expect_messages = NULL;
3974     ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
3975             "Expected screen size %ux%u, got %ux%u.\n",
3976             s.right, s.bottom, screen_size.cx, screen_size.cy);
3977
3978     GetWindowRect(window, &r);
3979     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3980             s.left, s.top, s.right, s.bottom,
3981             r.left, r.top, r.right, r.bottom);
3982
3983     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3984     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3985     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3986             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3987     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3988             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3989     IDirectDrawSurface7_Release(primary);
3990
3991     memset(&ddsd, 0, sizeof(ddsd));
3992     ddsd.dwSize = sizeof(ddsd);
3993     ddsd.dwFlags = DDSD_CAPS;
3994     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3995
3996     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3997     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3998     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3999     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4000     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4001             s.right - s.left, ddsd.dwWidth);
4002     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4003             s.bottom - s.top, ddsd.dwHeight);
4004
4005     GetWindowRect(window, &r);
4006     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4007             s.left, s.top, s.right, s.bottom,
4008             r.left, r.top, r.right, r.bottom);
4009
4010     expect_messages = exclusive_messages;
4011     screen_size.cx = 0;
4012     screen_size.cy = 0;
4013
4014     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4015     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4016
4017     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4018     expect_messages = NULL;
4019     ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
4020             "Expected screen size %ux%u, got %ux%u.\n",
4021             fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
4022
4023     GetWindowRect(window, &r);
4024     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4025             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4026             r.left, r.top, r.right, r.bottom);
4027
4028     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4029     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4030     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4031             s.right - s.left, ddsd.dwWidth);
4032     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4033             s.bottom - s.top, ddsd.dwHeight);
4034     IDirectDrawSurface7_Release(primary);
4035
4036     memset(&ddsd, 0, sizeof(ddsd));
4037     ddsd.dwSize = sizeof(ddsd);
4038     ddsd.dwFlags = DDSD_CAPS;
4039     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4040
4041     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4042     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4043     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4044     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4045     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4046             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4047     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4048             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4049
4050     GetWindowRect(window, &r);
4051     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4052             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4053             r.left, r.top, r.right, r.bottom);
4054
4055     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4056     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4057
4058     GetWindowRect(window, &r);
4059     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4060             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4061             r.left, r.top, r.right, r.bottom);
4062
4063     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4064     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4065     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4066             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4067     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4068             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4069     IDirectDrawSurface7_Release(primary);
4070
4071     memset(&ddsd, 0, sizeof(ddsd));
4072     ddsd.dwSize = sizeof(ddsd);
4073     ddsd.dwFlags = DDSD_CAPS;
4074     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4075
4076     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4077     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4078     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4079     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4080     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4081             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4082     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4083             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4084
4085     GetWindowRect(window, &r);
4086     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4087             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4088             r.left, r.top, r.right, r.bottom);
4089
4090     expect_messages = normal_messages;
4091     screen_size.cx = 0;
4092     screen_size.cy = 0;
4093
4094     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4095     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4096
4097     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4098     expect_messages = NULL;
4099     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4100
4101     GetWindowRect(window, &r);
4102     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4103             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4104             r.left, r.top, r.right, r.bottom);
4105
4106     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4107     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4108     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4109             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4110     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4111             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4112     IDirectDrawSurface7_Release(primary);
4113
4114     memset(&ddsd, 0, sizeof(ddsd));
4115     ddsd.dwSize = sizeof(ddsd);
4116     ddsd.dwFlags = DDSD_CAPS;
4117     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4118
4119     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4120     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4121     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4122     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4123     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4124             s.right - s.left, ddsd.dwWidth);
4125     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4126             s.bottom - s.top, ddsd.dwHeight);
4127
4128     GetWindowRect(window, &r);
4129     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4130             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4131             r.left, r.top, r.right, r.bottom);
4132
4133     expect_messages = normal_messages;
4134     screen_size.cx = 0;
4135     screen_size.cy = 0;
4136
4137     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4138     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4139
4140     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4141     expect_messages = NULL;
4142     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4143
4144     GetWindowRect(window, &r);
4145     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4146             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4147             r.left, r.top, r.right, r.bottom);
4148
4149     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4150     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4151     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4152             s.right - s.left, ddsd.dwWidth);
4153     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4154             s.bottom - s.top, ddsd.dwHeight);
4155     IDirectDrawSurface7_Release(primary);
4156
4157     memset(&ddsd, 0, sizeof(ddsd));
4158     ddsd.dwSize = sizeof(ddsd);
4159     ddsd.dwFlags = DDSD_CAPS;
4160     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4161
4162     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4163     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4164     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4165     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4166     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4167             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4168     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4169             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4170
4171     GetWindowRect(window, &r);
4172     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4173             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4174             r.left, r.top, r.right, r.bottom);
4175
4176     /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
4177      * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
4178      * not DDSCL_FULLSCREEN. */
4179     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
4180     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4181
4182     GetWindowRect(window, &r);
4183     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4184             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4185             r.left, r.top, r.right, r.bottom);
4186
4187     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4188     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4189     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4190             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4191     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4192             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4193     IDirectDrawSurface7_Release(primary);
4194
4195     memset(&ddsd, 0, sizeof(ddsd));
4196     ddsd.dwSize = sizeof(ddsd);
4197     ddsd.dwFlags = DDSD_CAPS;
4198     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4199
4200     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4201     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4202     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4203     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4204     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4205             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4206     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4207             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4208
4209     GetWindowRect(window, &r);
4210     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4211             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4212             r.left, r.top, r.right, r.bottom);
4213
4214     expect_messages = normal_messages;
4215     screen_size.cx = 0;
4216     screen_size.cy = 0;
4217
4218     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4219     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4220
4221     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4222     expect_messages = NULL;
4223     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4224
4225     GetWindowRect(window, &r);
4226     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4227             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4228             r.left, r.top, r.right, r.bottom);
4229
4230     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4231     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4232     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4233             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4234     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4235             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4236     IDirectDrawSurface7_Release(primary);
4237
4238     memset(&ddsd, 0, sizeof(ddsd));
4239     ddsd.dwSize = sizeof(ddsd);
4240     ddsd.dwFlags = DDSD_CAPS;
4241     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4242
4243     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4244     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4245     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4246     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4247     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4248             s.right - s.left, ddsd.dwWidth);
4249     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4250             s.bottom - s.top, ddsd.dwHeight);
4251
4252     GetWindowRect(window, &r);
4253     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4254             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4255             r.left, r.top, r.right, r.bottom);
4256
4257     expect_messages = normal_messages;
4258     screen_size.cx = 0;
4259     screen_size.cy = 0;
4260
4261     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4262     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4263
4264     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4265     expect_messages = NULL;
4266     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4267
4268     GetWindowRect(window, &r);
4269     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4270             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4271             r.left, r.top, r.right, r.bottom);
4272
4273     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4274     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4275     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4276             s.right - s.left, ddsd.dwWidth);
4277     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4278             s.bottom - s.top, ddsd.dwHeight);
4279     IDirectDrawSurface7_Release(primary);
4280
4281     memset(&ddsd, 0, sizeof(ddsd));
4282     ddsd.dwSize = sizeof(ddsd);
4283     ddsd.dwFlags = DDSD_CAPS;
4284     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4285
4286     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4287     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4288     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4289     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4290     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4291             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4292     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4293             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4294     IDirectDrawSurface7_Release(primary);
4295
4296     GetWindowRect(window, &r);
4297     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4298             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4299             r.left, r.top, r.right, r.bottom);
4300
4301     ref = IDirectDraw7_Release(ddraw7);
4302     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4303
4304     GetWindowRect(window, &r);
4305     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4306             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4307             r.left, r.top, r.right, r.bottom);
4308
4309 done:
4310     expect_messages = NULL;
4311     DestroyWindow(window);
4312     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
4313 }
4314
4315 static void dump_format(const DDPIXELFORMAT *fmt)
4316 {
4317     trace("dwFlags %08x, FourCC %08x, dwZBufferBitDepth %u, stencil %08x\n", fmt->dwFlags, fmt->dwFourCC,
4318           U1(*fmt).dwZBufferBitDepth, U2(*fmt).dwStencilBitDepth);
4319     trace("dwZBitMask %08x, dwStencilBitMask %08x, dwRGBZBitMask %08x\n", U3(*fmt).dwZBitMask,
4320           U4(*fmt).dwStencilBitMask, U5(*fmt).dwRGBZBitMask);
4321 }
4322
4323 static HRESULT WINAPI enum_z_fmt_cb(DDPIXELFORMAT *fmt, void *ctx)
4324 {
4325     static const DDPIXELFORMAT formats[] =
4326     {
4327         {
4328             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4329             {16}, {0}, {0x0000ffff}, {0x00000000}, {0x00000000}
4330         },
4331         {
4332             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4333             {32}, {0}, {0xffffff00}, {0x00000000}, {0x00000000}
4334         },
4335         {
4336             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
4337             {32}, {8}, {0xffffff00}, {0x000000ff}, {0x00000000}
4338         },
4339         {
4340             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4341             {32}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4342         },
4343         {
4344             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
4345             {32}, {8}, {0x00ffffff}, {0xff000000}, {0x00000000}
4346         },
4347         {
4348             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4349             {24}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4350         },
4351         {
4352             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4353             {32}, {0}, {0xffffffff}, {0x00000000}, {0x00000000}
4354         },
4355     };
4356     unsigned int *count = ctx, i, expected_pitch;
4357     DDSURFACEDESC2 ddsd;
4358     IDirectDrawSurface7 *surface;
4359     HRESULT hr;
4360     (*count)++;
4361
4362     memset(&ddsd, 0, sizeof(ddsd));
4363     ddsd.dwSize = sizeof(ddsd);
4364     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4365     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4366     U4(ddsd).ddpfPixelFormat = *fmt;
4367     ddsd.dwWidth = 1024;
4368     ddsd.dwHeight = 1024;
4369     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface, NULL);
4370     ok(SUCCEEDED(hr), "IDirectDraw7_CreateSurface failed, hr %#x.\n", hr);
4371     memset(&ddsd, 0, sizeof(ddsd));
4372     ddsd.dwSize = sizeof(ddsd);
4373     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4374     ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc failed, hr %#x.\n", hr);
4375     IDirectDrawSurface7_Release(surface);
4376
4377     ok(ddsd.dwFlags & DDSD_PIXELFORMAT, "DDSD_PIXELFORMAT is not set\n");
4378     ok(!(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH), "DDSD_ZBUFFERBITDEPTH is set\n");
4379
4380     /* 24 bit unpadded depth buffers are actually padded(Geforce 9600, Win7,
4381      * Radeon 9000M WinXP) */
4382     if (U1(*fmt).dwZBufferBitDepth == 24) expected_pitch = ddsd.dwWidth * 4;
4383     else expected_pitch = ddsd.dwWidth * U1(*fmt).dwZBufferBitDepth / 8;
4384
4385     /* Some formats(16 bit depth without stencil) return pitch 0
4386      *
4387      * The Radeon X1600 Catalyst 10.2 Windows XP driver returns an otherwise sane
4388      * pitch with an extra 128 bytes, regardless of the format and width */
4389     if (U1(ddsd).lPitch != 0 && U1(ddsd).lPitch != expected_pitch
4390             && !broken(U1(ddsd).lPitch == expected_pitch + 128))
4391     {
4392         ok(0, "Z buffer pitch is %u, expected %u\n", U1(ddsd).lPitch, expected_pitch);
4393         dump_format(fmt);
4394     }
4395
4396     for (i = 0; i < (sizeof(formats)/sizeof(*formats)); i++)
4397     {
4398         if (memcmp(&formats[i], fmt, fmt->dwSize) == 0) return DDENUMRET_OK;
4399     }
4400
4401     ok(0, "Unexpected Z format enumerated\n");
4402     dump_format(fmt);
4403
4404     return DDENUMRET_OK;
4405 }
4406
4407 static void z_format_test(void)
4408 {
4409     unsigned int count = 0;
4410     HRESULT hr;
4411
4412     hr = IDirect3D7_EnumZBufferFormats(lpD3D, &IID_IDirect3DHALDevice, enum_z_fmt_cb, &count);
4413     if (hr == DDERR_NOZBUFFERHW)
4414     {
4415         skip("Z buffers not supported, skipping Z buffer format test\n");
4416         return;
4417     }
4418
4419     ok(SUCCEEDED(hr), "IDirect3D7_EnumZBufferFormats failed, hr %#x.\n", hr);
4420     ok(count, "Expected at least one supported Z Buffer format\n");
4421 }
4422
4423 static void test_initialize(void)
4424 {
4425     IDirectDraw7 *ddraw7;
4426     IDirectDraw4 *ddraw4;
4427     IDirectDraw2 *ddraw2;
4428     IDirectDraw *ddraw1;
4429     IDirect3D *d3d1;
4430     HRESULT hr;
4431
4432     /* IDirectDraw */
4433     if (FAILED(hr = DirectDrawCreate(NULL, &ddraw1, NULL)))
4434     {
4435         skip("Failed to create IDirectDraw object (%#x), skipping tests.\n", hr);
4436         return;
4437     }
4438
4439     hr = IDirectDraw_Initialize(ddraw1, NULL);
4440     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4441     IDirectDraw_Release(ddraw1);
4442
4443     CoInitialize(NULL);
4444     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw1);
4445     ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
4446     hr = IDirectDraw_Initialize(ddraw1, NULL);
4447     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4448     hr = IDirectDraw_Initialize(ddraw1, NULL);
4449     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4450     IDirectDraw_Release(ddraw1);
4451     CoUninitialize();
4452
4453     hr = DirectDrawCreate(NULL, &ddraw1, NULL);
4454     ok(SUCCEEDED(hr), "Failed to create IDirectDraw object, hr %#x.\n", hr);
4455
4456     /* IDirectDraw2 */
4457     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2)))
4458     {
4459         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4460         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4461         IDirectDraw2_Release(ddraw2);
4462
4463         CoInitialize(NULL);
4464         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw2);
4465         ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
4466         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4467         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4468         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4469         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4470         IDirectDraw2_Release(ddraw2);
4471         CoUninitialize();
4472     }
4473     else skip("Failed to query IDirectDraw2 interface, skipping tests.\n");
4474
4475     /* IDirectDraw4 */
4476     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4)))
4477     {
4478         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4479         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4480         IDirectDraw4_Release(ddraw4);
4481
4482         CoInitialize(NULL);
4483         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw4);
4484         ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
4485         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4486         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4487         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4488         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4489         IDirectDraw4_Release(ddraw4);
4490         CoUninitialize();
4491     }
4492     else skip("Failed to query IDirectDraw4 interface, skipping tests.\n");
4493
4494     /* IDirect3D */
4495     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D, (void **)&d3d1)))
4496     {
4497         IDirectDraw *ddraw;
4498
4499         hr = IDirect3D_Initialize(d3d1, NULL);
4500         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4501         IDirect3D_Release(d3d1);
4502
4503         if (0) /* This crashes on the W2KPROSP4 testbot. */
4504         {
4505             CoInitialize(NULL);
4506             hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d1);
4507             ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
4508             CoUninitialize();
4509         }
4510
4511         CoInitialize(NULL);
4512         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
4513         ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
4514         hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d1);
4515         ok(SUCCEEDED(hr), "Failed to query IDirect3D interface, hr %#x.\n", hr);
4516         IDirectDraw_Release(ddraw);
4517         /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
4518         hr = IDirect3D_Initialize(d3d1, NULL);
4519         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4520         hr = IDirectDraw_Initialize(ddraw, NULL);
4521         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4522         hr = IDirectDraw_Initialize(ddraw, NULL);
4523         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4524         IDirect3D_Release(d3d1);
4525         CoUninitialize();
4526     }
4527     else skip("Failed to query IDirect3D interface, skipping tests.\n");
4528
4529     IDirectDraw_Release(ddraw1);
4530
4531     /* IDirectDraw7 */
4532     if (FAILED(hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL)))
4533     {
4534         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4535         return;
4536     }
4537     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4538     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4539     IDirectDraw7_Release(ddraw7);
4540
4541     CoInitialize(NULL);
4542     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw7);
4543     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
4544     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4545     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4546     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4547     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4548     IDirectDraw7_Release(ddraw7);
4549     CoUninitialize();
4550 }
4551
4552 static void test_coop_level_surf_create(void)
4553 {
4554     IDirectDrawSurface7 *surface7;
4555     IDirectDrawSurface4 *surface4;
4556     IDirectDrawSurface *surface1;
4557     IDirectDraw7 *ddraw7;
4558     IDirectDraw4 *ddraw4;
4559     IDirectDraw2 *ddraw2;
4560     IDirectDraw *ddraw1;
4561     DDSURFACEDESC2 ddsd2;
4562     DDSURFACEDESC ddsd;
4563     HRESULT hr;
4564
4565     /* IDirectDraw */
4566     if (FAILED(hr = DirectDrawCreate(NULL, &ddraw1, NULL)))
4567     {
4568         skip("Failed to create IDirectDraw object (%#x), skipping tests.\n", hr);
4569         return;
4570     }
4571
4572     memset(&ddsd, 0, sizeof(ddsd));
4573     ddsd.dwSize = sizeof(ddsd);
4574     ddsd.dwFlags = DDSD_CAPS;
4575     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4576     hr = IDirectDraw_CreateSurface(ddraw1, &ddsd, &surface1, NULL);
4577     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4578
4579     /* IDirectDraw2 */
4580     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2)))
4581     {
4582         memset(&ddsd, 0, sizeof(ddsd));
4583         ddsd.dwSize = sizeof(ddsd);
4584         ddsd.dwFlags = DDSD_CAPS;
4585         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4586         hr = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &surface1, NULL);
4587         ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4588
4589         IDirectDraw2_Release(ddraw2);
4590     }
4591     else skip("Failed to query IDirectDraw2 interface, skipping tests.\n");
4592
4593     /* IDirectDraw4 */
4594     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4)))
4595     {
4596         memset(&ddsd2, 0, sizeof(ddsd2));
4597         ddsd2.dwSize = sizeof(ddsd2);
4598         ddsd2.dwFlags = DDSD_CAPS;
4599         ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4600         hr = IDirectDraw4_CreateSurface(ddraw4, &ddsd2, &surface4, NULL);
4601         ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4602
4603         IDirectDraw4_Release(ddraw4);
4604     }
4605     else skip("Failed to query IDirectDraw4 interface, skipping tests.\n");
4606
4607     IDirectDraw_Release(ddraw1);
4608
4609     /* IDirectDraw7 */
4610     if (FAILED(hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL)))
4611     {
4612         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4613         return;
4614     }
4615
4616     memset(&ddsd2, 0, sizeof(ddsd2));
4617     ddsd2.dwSize = sizeof(ddsd2);
4618     ddsd2.dwFlags = DDSD_CAPS;
4619     ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4620     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd2, &surface7, NULL);
4621     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4622
4623     IDirectDraw7_Release(ddraw7);
4624 }
4625
4626 static void test_get_caps1(void)
4627 {
4628     D3DDEVICEDESC hw_caps, hel_caps;
4629     HRESULT hr;
4630     unsigned int i;
4631
4632     memset(&hw_caps, 0, sizeof(hw_caps));
4633     hw_caps.dwSize = sizeof(hw_caps);
4634     hw_caps.dwFlags = 0xdeadbeef;
4635     memset(&hel_caps, 0, sizeof(hel_caps));
4636     hel_caps.dwSize = sizeof(hel_caps);
4637     hel_caps.dwFlags = 0xdeadc0de;
4638
4639     /* NULL pointers */
4640     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, NULL);
4641     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hel caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4642     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4643     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, NULL, &hel_caps);
4644     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hw caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4645     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4646
4647     /* Successful call: Both are modified */
4648     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4649     ok(hr == D3D_OK, "GetCaps with correct size returned hr %#x, expected D3D_OK.\n", hr);
4650     ok(hw_caps.dwFlags != 0xdeadbeef, "hw_caps.dwFlags was not modified: %#x.\n", hw_caps.dwFlags);
4651     ok(hel_caps.dwFlags != 0xdeadc0de, "hel_caps.dwFlags was not modified: %#x.\n", hel_caps.dwFlags);
4652
4653     memset(&hw_caps, 0, sizeof(hw_caps));
4654     hw_caps.dwSize = sizeof(hw_caps);
4655     hw_caps.dwFlags = 0xdeadbeef;
4656     memset(&hel_caps, 0, sizeof(hel_caps));
4657     /* Keep dwSize at 0 */
4658     hel_caps.dwFlags = 0xdeadc0de;
4659
4660     /* If one is invalid the call fails */
4661     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4662     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hel_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4663     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4664     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4665     hel_caps.dwSize = sizeof(hel_caps);
4666     hw_caps.dwSize = sizeof(hw_caps) + 1;
4667     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4668     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hw_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4669     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4670     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4671
4672     for (i = 0; i < 1024; i++)
4673     {
4674         memset(&hw_caps, 0xfe, sizeof(hw_caps));
4675         memset(&hel_caps, 0xfe, sizeof(hel_caps));
4676         hw_caps.dwSize = hel_caps.dwSize = i;
4677         hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4678         switch (i)
4679         {
4680             /* D3DDEVICEDESCSIZE in old sdk versions */
4681             case FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth): /* 172, DirectX 3, IDirect3DDevice1 */
4682                 ok(hw_caps.dwMinTextureWidth == 0xfefefefe, "hw_caps.dwMinTextureWidth was modified: %#x.\n",
4683                         hw_caps.dwMinTextureWidth);
4684                 ok(hel_caps.dwMinTextureWidth == 0xfefefefe, "hel_caps.dwMinTextureWidth was modified: %#x.\n",
4685                         hel_caps.dwMinTextureWidth);
4686                 /* drop through */
4687             case FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat): /* 204, DirectX 5, IDirect3DDevice2 */
4688                 ok(hw_caps.dwMaxTextureRepeat == 0xfefefefe, "hw_caps.dwMaxTextureRepeat was modified: %#x.\n",
4689                         hw_caps.dwMaxTextureRepeat);
4690                 ok(hel_caps.dwMaxTextureRepeat == 0xfefefefe, "hel_caps.dwMaxTextureRepeat was modified: %#x.\n",
4691                         hel_caps.dwMaxTextureRepeat);
4692                 /* drop through */
4693             case sizeof(D3DDEVICEDESC): /* 252, DirectX 6, IDirect3DDevice3 */
4694                 ok(hr == D3D_OK, "GetCaps with size %u returned hr %#x, expected D3D_OK.\n", i, hr);
4695                 break;
4696
4697             default:
4698                 ok(hr == DDERR_INVALIDPARAMS,
4699                         "GetCaps with size %u returned hr %#x, expected DDERR_INVALIDPARAMS.\n", i, hr);
4700                 break;
4701         }
4702     }
4703
4704     /* Different valid sizes are OK */
4705     hw_caps.dwSize = 172;
4706     hel_caps.dwSize = sizeof(D3DDEVICEDESC);
4707     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4708     ok(hr == D3D_OK, "GetCaps with different sizes returned hr %#x, expected D3D_OK.\n", hr);
4709 }
4710
4711 static void test_get_caps7(void)
4712 {
4713     HRESULT hr;
4714     D3DDEVICEDESC7 desc;
4715
4716     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, NULL);
4717     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7::GetCaps(NULL) returned hr %#x, expected INVALIDPARAMS.\n", hr);
4718
4719     memset(&desc, 0, sizeof(desc));
4720     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &desc);
4721     ok(hr == D3D_OK, "IDirect3DDevice7::GetCaps(non-NULL) returned hr %#x, expected D3D_OK.\n", hr);
4722
4723     /* There's no dwSize in D3DDEVICEDESC7 */
4724 }
4725
4726 struct d3d2_test_context
4727 {
4728     IDirectDraw *ddraw;
4729     IDirect3D2 *d3d;
4730     IDirectDrawSurface *surface;
4731     IDirect3DDevice2 *device;
4732     IDirect3DViewport2 *viewport;
4733 };
4734
4735 static void d3d2_release_objects(struct d3d2_test_context *context)
4736 {
4737     LONG ref;
4738     HRESULT hr;
4739
4740     if (context->viewport)
4741     {
4742         hr = IDirect3DDevice2_DeleteViewport(context->device, context->viewport);
4743         ok(hr == D3D_OK, "DeleteViewport returned %08x.\n", hr);
4744         ref = IDirect3DViewport2_Release(context->viewport);
4745         ok(ref == 0, "Viewport has reference count %d, expected 0.\n", ref);
4746     }
4747     if (context->device)
4748     {
4749         ref = IDirect3DDevice2_Release(context->device);
4750         ok(ref == 0, "Device has reference count %d, expected 0.\n", ref);
4751     }
4752     if (context->surface)
4753     {
4754         ref = IDirectDrawSurface_Release(context->surface);
4755         ok(ref == 0, "Surface has reference count %d, expected 0.\n", ref);
4756     }
4757     if (context->d3d)
4758     {
4759         ref = IDirect3D2_Release(context->d3d);
4760         ok(ref == 1, "IDirect3D2 has reference count %d, expected 1.\n", ref);
4761     }
4762     if (context->ddraw)
4763     {
4764         ref = IDirectDraw_Release(context->ddraw);
4765         ok(ref == 0, "DDraw has reference count %d, expected 0.\n", ref);
4766     }
4767 }
4768
4769 static BOOL d3d2_create_objects(struct d3d2_test_context *context)
4770 {
4771     HRESULT hr;
4772     DDSURFACEDESC ddsd;
4773     D3DVIEWPORT vp_data;
4774
4775     memset(context, 0, sizeof(*context));
4776
4777     hr = DirectDrawCreate(NULL, &context->ddraw, NULL);
4778     ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate failed: %08x.\n", hr);
4779     if (!context->ddraw) goto error;
4780
4781     hr = IDirectDraw_SetCooperativeLevel(context->ddraw, NULL, DDSCL_NORMAL);
4782     ok(hr == DD_OK, "SetCooperativeLevel failed: %08x.\n", hr);
4783     if (FAILED(hr)) goto error;
4784
4785     hr = IDirectDraw_QueryInterface(context->ddraw, &IID_IDirect3D2, (void**) &context->d3d);
4786     ok(hr == DD_OK || hr == E_NOINTERFACE, "QueryInterface failed: %08x.\n", hr);
4787     if (!context->d3d) goto error;
4788
4789     memset(&ddsd, 0, sizeof(ddsd));
4790     ddsd.dwSize = sizeof(ddsd);
4791     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4792     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4793     ddsd.dwWidth = 256;
4794     ddsd.dwHeight = 256;
4795     IDirectDraw_CreateSurface(context->ddraw, &ddsd, &context->surface, NULL);
4796     if (!context->surface)
4797     {
4798         skip("DDSCAPS_3DDEVICE surface not available.\n");
4799         goto error;
4800     }
4801
4802     hr = IDirect3D2_CreateDevice(context->d3d, &IID_IDirect3DHALDevice, context->surface, &context->device);
4803     ok(hr == D3D_OK  || hr == E_OUTOFMEMORY || hr == E_NOINTERFACE, "CreateDevice failed: %08x.\n", hr);
4804     if (!context->device) goto error;
4805
4806     hr = IDirect3D2_CreateViewport(context->d3d, &context->viewport, NULL);
4807     ok(hr == D3D_OK, "CreateViewport failed: %08x.\n", hr);
4808     if (!context->viewport) goto error;
4809
4810     hr = IDirect3DDevice2_AddViewport(context->device, context->viewport);
4811     ok(hr == D3D_OK, "AddViewport returned %08x.\n", hr);
4812     vp_data.dwSize = sizeof(vp_data);
4813     vp_data.dwX = 0;
4814     vp_data.dwY = 0;
4815     vp_data.dwWidth = 256;
4816     vp_data.dwHeight = 256;
4817     vp_data.dvScaleX = 1;
4818     vp_data.dvScaleY = 1;
4819     vp_data.dvMaxX = 256;
4820     vp_data.dvMaxY = 256;
4821     vp_data.dvMinZ = 0;
4822     vp_data.dvMaxZ = 1;
4823     hr = IDirect3DViewport2_SetViewport(context->viewport, &vp_data);
4824     ok(hr == D3D_OK, "SetViewport returned %08x.\n", hr);
4825
4826     return TRUE;
4827
4828 error:
4829     d3d2_release_objects(context);
4830     return FALSE;
4831 }
4832
4833 static void test_get_caps2(const struct d3d2_test_context *context)
4834 {
4835     D3DDEVICEDESC hw_caps, hel_caps;
4836     HRESULT hr;
4837     unsigned int i;
4838
4839     memset(&hw_caps, 0, sizeof(hw_caps));
4840     hw_caps.dwSize = sizeof(hw_caps);
4841     hw_caps.dwFlags = 0xdeadbeef;
4842     memset(&hel_caps, 0, sizeof(hel_caps));
4843     hel_caps.dwSize = sizeof(hel_caps);
4844     hel_caps.dwFlags = 0xdeadc0de;
4845
4846     /* NULL pointers */
4847     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, NULL);
4848     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hel caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4849     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4850     hr = IDirect3DDevice2_GetCaps(context->device, NULL, &hel_caps);
4851     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hw caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4852     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4853
4854     /* Successful call: Both are modified */
4855     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4856     ok(hr == D3D_OK, "GetCaps with correct size returned hr %#x, expected D3D_OK.\n", hr);
4857     ok(hw_caps.dwFlags != 0xdeadbeef, "hw_caps.dwFlags was not modified: %#x.\n", hw_caps.dwFlags);
4858     ok(hel_caps.dwFlags != 0xdeadc0de, "hel_caps.dwFlags was not modified: %#x.\n", hel_caps.dwFlags);
4859
4860     memset(&hw_caps, 0, sizeof(hw_caps));
4861     hw_caps.dwSize = sizeof(hw_caps);
4862     hw_caps.dwFlags = 0xdeadbeef;
4863     memset(&hel_caps, 0, sizeof(hel_caps));
4864     /* Keep dwSize at 0 */
4865     hel_caps.dwFlags = 0xdeadc0de;
4866
4867     /* If one is invalid the call fails */
4868     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4869     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hel_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4870     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4871     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4872     hel_caps.dwSize = sizeof(hel_caps);
4873     hw_caps.dwSize = sizeof(hw_caps) + 1;
4874     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4875     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hw_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4876     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4877     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4878
4879     for (i = 0; i < 1024; i++)
4880     {
4881         memset(&hw_caps, 0xfe, sizeof(hw_caps));
4882         memset(&hel_caps, 0xfe, sizeof(hel_caps));
4883         hw_caps.dwSize = hel_caps.dwSize = i;
4884         hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4885         switch (i)
4886         {
4887             /* D3DDEVICEDESCSIZE in old sdk versions */
4888             case FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth): /* 172, DirectX 3, IDirect3DDevice1 */
4889                 ok(hw_caps.dwMinTextureWidth == 0xfefefefe, "dwMinTextureWidth was modified: %#x.\n",
4890                         hw_caps.dwMinTextureWidth);
4891                 ok(hel_caps.dwMinTextureWidth == 0xfefefefe, "dwMinTextureWidth was modified: %#x.\n",
4892                         hel_caps.dwMinTextureWidth);
4893                 /* drop through */
4894             case FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat): /* 204, DirectX 5, IDirect3DDevice2 */
4895                 ok(hw_caps.dwMaxTextureRepeat == 0xfefefefe, "dwMaxTextureRepeat was modified: %#x.\n",
4896                         hw_caps.dwMaxTextureRepeat);
4897                 ok(hel_caps.dwMaxTextureRepeat == 0xfefefefe, "dwMaxTextureRepeat was modified: %#x.\n",
4898                         hel_caps.dwMaxTextureRepeat);
4899                 /* drop through */
4900             case sizeof(D3DDEVICEDESC): /* 252, DirectX 6, IDirect3DDevice3 */
4901                 ok(hr == D3D_OK, "GetCaps with size %u returned hr %#x, expected D3D_OK.\n", i, hr);
4902                 break;
4903
4904             default:
4905                 ok(hr == DDERR_INVALIDPARAMS,
4906                         "GetCaps with size %u returned hr %#x, expected DDERR_INVALIDPARAMS.\n", i, hr);
4907                 break;
4908         }
4909     }
4910
4911     /* Different valid sizes are OK */
4912     hw_caps.dwSize = 172;
4913     hel_caps.dwSize = sizeof(D3DDEVICEDESC);
4914     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4915     ok(hr == D3D_OK, "GetCaps with different sizes returned hr %#x, expected D3D_OK.\n", hr);
4916 }
4917
4918 START_TEST(d3d)
4919 {
4920     struct d3d2_test_context d3d2_context;
4921     void (* const d3d2_tests[])(const struct d3d2_test_context *) =
4922     {
4923         test_get_caps2
4924     };
4925     unsigned int i;
4926
4927     init_function_pointers();
4928     if(!pDirectDrawCreateEx) {
4929         win_skip("function DirectDrawCreateEx not available\n");
4930         return;
4931     }
4932
4933     if(!CreateDirect3D()) {
4934         skip("Skipping d3d7 tests\n");
4935     } else {
4936         LightTest();
4937         StateTest();
4938         SceneTest();
4939         LimitTest();
4940         D3D7EnumTest();
4941         D3D7EnumLifetimeTest();
4942         SetMaterialTest();
4943         ComputeSphereVisibility();
4944         CapsTest();
4945         VertexBufferDescTest();
4946         D3D7_OldRenderStateTest();
4947         DeviceLoadTest();
4948         SetRenderTargetTest();
4949         VertexBufferLockRest();
4950         z_format_test();
4951         test_get_caps7();
4952         ReleaseDirect3D();
4953     }
4954
4955     for (i = 0; i < (sizeof(d3d2_tests) / sizeof(*d3d2_tests)); i++)
4956     {
4957         if (!d3d2_create_objects(&d3d2_context))
4958         {
4959             ok(!i, "Unexpected d3d2 initialization failure.\n");
4960             skip("Skipping d3d2 tests.\n");
4961             break;
4962         }
4963         d3d2_tests[i](&d3d2_context);
4964         d3d2_release_objects(&d3d2_context);
4965     }
4966
4967     if (!D3D1_createObjects()) {
4968         skip("Skipping d3d1 tests\n");
4969     } else {
4970         Direct3D1Test();
4971         TextureLoadTest();
4972         ViewportTest();
4973         FindDevice();
4974         BackBuffer3DCreateSurfaceTest();
4975         BackBuffer3DAttachmentTest();
4976         test_get_caps1();
4977         D3D1_releaseObjects();
4978     }
4979
4980     test_wndproc();
4981     test_window_style();
4982     test_redundant_mode_set();
4983     test_coop_level_mode_set();
4984     test_initialize();
4985     test_coop_level_surf_create();
4986 }