ddraw/tests: Move test_wndproc() to ddraw7.c.
[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 different 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 different 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(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2853     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2854
2855     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2856     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2857     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2858     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2859
2860     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2861     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2862     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2863     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2864
2865     U1(center[0]).x=0.0;
2866     U2(center[0]).y=0.0;
2867     U3(center[0]).z=0.05;
2868
2869     radius[0]=0.04;
2870
2871     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2872     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2873
2874     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2875
2876     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2877     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2878
2879     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2880     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2881     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2882     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2883
2884     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2885
2886     U1(center[0]).x=0.0;
2887     U2(center[0]).y=0.0;
2888     U3(center[0]).z=0.5;
2889
2890     radius[0]=0.5;
2891
2892     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2893
2894     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2895     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2896
2897     U1(center[0]).x=0.0;
2898     U2(center[0]).y=0.0;
2899     U3(center[0]).z=0.0;
2900
2901     radius[0]=0.0;
2902
2903     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2904
2905     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2906     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2907
2908     U1(center[0]).x=-1.0;
2909     U2(center[0]).y=-1.0;
2910     U3(center[0]).z=0.50;
2911
2912     radius[0]=0.25;
2913
2914     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2915
2916     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2917     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
2918
2919     U1(center[0]).x=-20.0;
2920     U2(center[0]).y=0.0;
2921     U3(center[0]).z=0.50;
2922
2923     radius[0]=3.0;
2924
2925     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2926
2927     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2928     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2929
2930     U1(center[0]).x=20.0;
2931     U2(center[0]).y=0.0;
2932     U3(center[0]).z=0.50;
2933
2934     radius[0]=3.0f;
2935
2936     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2937
2938     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2939     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
2940
2941     U1(center[0]).x=0.0;
2942     U2(center[0]).y=-20.0;
2943     U3(center[0]).z=0.50;
2944
2945     radius[0]=3.0;
2946
2947     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2948
2949     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2950     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
2951
2952     U1(center[0]).x=0.0;
2953     U2(center[0]).y=20.0;
2954     U3(center[0]).z=0.5;
2955
2956     radius[0]=3.0;
2957
2958     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2959
2960     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2961     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
2962
2963     U1(center[0]).x=0.0;
2964     U2(center[0]).y=0.0;
2965     U3(center[0]).z=-20;
2966
2967     radius[0]=3.0;
2968
2969     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2970
2971     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2972     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
2973
2974     U1(center[0]).x=0.0;
2975     U2(center[0]).y=0.0;
2976     U3(center[0]).z=20.0;
2977
2978     radius[0]=3.0;
2979
2980     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2981
2982     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2983     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
2984 }
2985
2986 static void SetRenderTargetTest(void)
2987 {
2988     HRESULT hr;
2989     IDirectDrawSurface7 *newrt, *failrt, *oldrt, *temprt;
2990     D3DVIEWPORT7 vp;
2991     DDSURFACEDESC2 ddsd, ddsd2;
2992     DWORD stateblock;
2993     ULONG refcount;
2994
2995     memset(&ddsd, 0, sizeof(ddsd));
2996     ddsd.dwSize = sizeof(ddsd);
2997     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2998     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
2999     ddsd.dwWidth = 64;
3000     ddsd.dwHeight = 64;
3001
3002     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
3003     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3004     if(FAILED(hr))
3005     {
3006         skip("Skipping SetRenderTarget test\n");
3007         return;
3008     }
3009
3010     memset(&ddsd2, 0, sizeof(ddsd2));
3011     ddsd2.dwSize = sizeof(ddsd2);
3012     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3013     ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER;
3014     ddsd2.dwWidth = 64;
3015     ddsd2.dwHeight = 64;
3016     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
3017     U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3018     U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3019     U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3020
3021     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd2, &failrt, NULL);
3022     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3023
3024     memset(&vp, 0, sizeof(vp));
3025     vp.dwX = 10;
3026     vp.dwY = 10;
3027     vp.dwWidth = 246;
3028     vp.dwHeight = 246;
3029     vp.dvMinZ = 0.25;
3030     vp.dvMaxZ = 0.75;
3031     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3032     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3033
3034     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3035     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3036
3037     refcount = getRefcount((IUnknown*) oldrt);
3038     ok(refcount == 3, "Refcount should be 3, returned is %d\n", refcount);
3039
3040     refcount = getRefcount((IUnknown*) failrt);
3041     ok(refcount == 1, "Refcount should be 1, returned is %d\n", refcount);
3042
3043     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, failrt, 0);
3044     ok(hr != D3D_OK, "IDirect3DDevice7_SetRenderTarget succeeded\n");
3045
3046     refcount = getRefcount((IUnknown*) oldrt);
3047     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3048
3049     refcount = getRefcount((IUnknown*) failrt);
3050     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3051
3052     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &temprt);
3053     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3054     ok(failrt == temprt, "Wrong iface returned\n");
3055
3056     refcount = getRefcount((IUnknown*) failrt);
3057     ok(refcount == 3, "Refcount should be 3, returned is %d\n", refcount);
3058
3059     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3060     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3061
3062     refcount = getRefcount((IUnknown*) failrt);
3063     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3064
3065     memset(&vp, 0xff, sizeof(vp));
3066     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3067     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3068     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3069     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3070     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3071     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3072     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.25\n", vp.dvMinZ);
3073     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.75\n", vp.dvMaxZ);
3074
3075     memset(&vp, 0, sizeof(vp));
3076     vp.dwX = 0;
3077     vp.dwY = 0;
3078     vp.dwWidth = 64;
3079     vp.dwHeight = 64;
3080     vp.dvMinZ = 0.0;
3081     vp.dvMaxZ = 1.0;
3082     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3083     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3084
3085     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3086     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3087     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3088     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3089
3090     /* Check this twice, before and after ending the stateblock */
3091     memset(&vp, 0xff, sizeof(vp));
3092     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3093     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3094     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3095     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3096     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3097     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3098     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3099     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3100
3101     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3102     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3103
3104     memset(&vp, 0xff, sizeof(vp));
3105     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3106     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3107     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3108     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3109     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3110     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3111     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3112     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3113
3114     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3115     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3116
3117     memset(&vp, 0, sizeof(vp));
3118     vp.dwX = 0;
3119     vp.dwY = 0;
3120     vp.dwWidth = 256;
3121     vp.dwHeight = 256;
3122     vp.dvMinZ = 0.0;
3123     vp.dvMaxZ = 0.0;
3124     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3125     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3126
3127     IDirectDrawSurface7_Release(oldrt);
3128     IDirectDrawSurface7_Release(newrt);
3129     IDirectDrawSurface7_Release(failrt);
3130     IDirectDrawSurface7_Release(failrt);
3131 }
3132
3133 static const UINT *expect_messages;
3134
3135 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3136 {
3137     if (expect_messages && message == *expect_messages) ++expect_messages;
3138
3139     return DefWindowProcA(hwnd, message, wparam, lparam);
3140 }
3141
3142 static void VertexBufferLockRest(void)
3143 {
3144     D3DVERTEXBUFFERDESC desc;
3145     IDirect3DVertexBuffer7 *buffer;
3146     HRESULT hr;
3147     unsigned int i;
3148     void *data;
3149     const struct
3150     {
3151         DWORD flags;
3152         const char *debug_string;
3153         HRESULT result;
3154     }
3155     test_data[] =
3156     {
3157         {0,                                         "(none)",                                       D3D_OK },
3158         {DDLOCK_WAIT,                               "DDLOCK_WAIT",                                  D3D_OK },
3159         {DDLOCK_EVENT,                              "DDLOCK_EVENT",                                 D3D_OK },
3160         {DDLOCK_READONLY,                           "DDLOCK_READONLY",                              D3D_OK },
3161         {DDLOCK_WRITEONLY,                          "DDLOCK_WRITEONLY",                             D3D_OK },
3162         {DDLOCK_NOSYSLOCK,                          "DDLOCK_NOSYSLOCK",                             D3D_OK },
3163         {DDLOCK_NOOVERWRITE,                        "DDLOCK_NOOVERWRITE",                           D3D_OK },
3164         {DDLOCK_DISCARDCONTENTS,                    "DDLOCK_DISCARDCONTENTS",                       D3D_OK },
3165
3166         {DDLOCK_READONLY | DDLOCK_WRITEONLY,        "DDLOCK_READONLY | DDLOCK_WRITEONLY",           D3D_OK },
3167         {DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS,  "DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS",     D3D_OK },
3168         {0xdeadbeef,                                "0xdeadbeef",                                   D3D_OK },
3169     };
3170
3171     memset(&desc, 0 , sizeof(desc));
3172     desc.dwSize = sizeof(desc);
3173     desc.dwCaps = 0;
3174     desc.dwFVF = D3DFVF_XYZ;
3175     desc.dwNumVertices = 64;
3176     hr = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &buffer, 0);
3177     ok(hr == D3D_OK, "IDirect3D7_CreateVertexBuffer failed, 0x%08x\n", hr);
3178
3179     for(i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
3180     {
3181         hr = IDirect3DVertexBuffer7_Lock(buffer, test_data[i].flags, &data, NULL);
3182         ok(hr == test_data[i].result, "Lock flags %s returned 0x%08x, expected 0x%08x\n",
3183             test_data[i].debug_string, hr, test_data[i].result);
3184         if(SUCCEEDED(hr))
3185         {
3186             ok(data != NULL, "The data pointer returned by Lock is NULL\n");
3187             hr = IDirect3DVertexBuffer7_Unlock(buffer);
3188             ok(hr == D3D_OK, "IDirect3DVertexBuffer7_Unlock failed, 0x%08x\n", hr);
3189         }
3190     }
3191
3192     IDirect3DVertexBuffer7_Release(buffer);
3193 }
3194
3195 static void FindDevice(void)
3196 {
3197     static const struct
3198     {
3199         const GUID *guid;
3200         int todo;
3201     } deviceGUIDs[] =
3202     {
3203         {&IID_IDirect3DRampDevice, 1},
3204         {&IID_IDirect3DRGBDevice},
3205     };
3206
3207     static const GUID *nonexistent_deviceGUIDs[] = {&IID_IDirect3DMMXDevice,
3208                                                     &IID_IDirect3DRefDevice,
3209                                                     &IID_IDirect3DTnLHalDevice,
3210                                                     &IID_IDirect3DNullDevice};
3211
3212     D3DFINDDEVICESEARCH search = {0};
3213     D3DFINDDEVICERESULT result = {0};
3214     IDirect3DDevice *d3dhal;
3215     HRESULT hr;
3216     int i;
3217
3218     /* Test invalid parameters. */
3219     hr = IDirect3D_FindDevice(Direct3D1, NULL, NULL);
3220     ok(hr == DDERR_INVALIDPARAMS,
3221        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3222
3223     hr = IDirect3D_FindDevice(Direct3D1, NULL, &result);
3224     ok(hr == DDERR_INVALIDPARAMS,
3225        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3226
3227     hr = IDirect3D_FindDevice(Direct3D1, &search, NULL);
3228     ok(hr == DDERR_INVALIDPARAMS,
3229        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3230
3231     search.dwSize = 0;
3232     result.dwSize = 0;
3233
3234     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3235     ok(hr == DDERR_INVALIDPARAMS,
3236        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3237
3238     search.dwSize = sizeof(search) + 1;
3239     result.dwSize = sizeof(result) + 1;
3240
3241     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3242     ok(hr == DDERR_INVALIDPARAMS,
3243        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3244
3245     /* Specifying no flags is permitted. */
3246     search.dwSize = sizeof(search);
3247     search.dwFlags = 0;
3248     result.dwSize = sizeof(result);
3249
3250     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3251     ok(hr == D3D_OK,
3252        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3253
3254     /* Try an arbitrary non-device GUID. */
3255     search.dwSize = sizeof(search);
3256     search.dwFlags = D3DFDS_GUID;
3257     search.guid = IID_IDirect3D;
3258     result.dwSize = sizeof(result);
3259
3260     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3261     ok(hr == DDERR_NOTFOUND,
3262        "Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", hr);
3263
3264     /* These GUIDs appear to be never present. */
3265     for (i = 0; i < sizeof(nonexistent_deviceGUIDs)/sizeof(nonexistent_deviceGUIDs[0]); i++)
3266     {
3267         search.dwSize = sizeof(search);
3268         search.dwFlags = D3DFDS_GUID;
3269         search.guid = *nonexistent_deviceGUIDs[i];
3270         result.dwSize = sizeof(result);
3271
3272         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3273         ok(hr == DDERR_NOTFOUND,
3274            "[%d] Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", i, hr);
3275     }
3276
3277     /* The HAL device can only be enumerated if hardware acceleration is present. */
3278     search.dwSize = sizeof(search);
3279     search.dwFlags = D3DFDS_GUID;
3280     search.guid = IID_IDirect3DHALDevice;
3281     result.dwSize = sizeof(result);
3282
3283     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3284     trace("IDirect3D::FindDevice returned 0x%08x for the HAL device GUID\n", hr);
3285     if (SUCCEEDED(hr))
3286     {
3287         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3288         /* Currently Wine only supports the creation of one Direct3D device
3289          * for a given DirectDraw instance. */
3290         ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
3291            "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3292
3293         if (SUCCEEDED(hr))
3294             IDirect3DDevice_Release(d3dhal);
3295     }
3296     else
3297     {
3298         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3299         ok(FAILED(hr), "Expected IDirectDrawSurface::QueryInterface to fail, got 0x%08x\n", hr);
3300
3301         if (SUCCEEDED(hr))
3302             IDirect3DDevice_Release(d3dhal);
3303     }
3304
3305     /* These GUIDs appear to be always present. */
3306     for (i = 0; i < sizeof(deviceGUIDs)/sizeof(deviceGUIDs[0]); i++)
3307     {
3308         search.dwSize = sizeof(search);
3309         search.dwFlags = D3DFDS_GUID;
3310         search.guid = *deviceGUIDs[i].guid;
3311         result.dwSize = sizeof(result);
3312
3313         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3314
3315         if (deviceGUIDs[i].todo)
3316         {
3317             todo_wine
3318             ok(hr == D3D_OK,
3319                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3320         }
3321         else
3322         {
3323             ok(hr == D3D_OK,
3324                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3325         }
3326     }
3327
3328     /* Curiously the color model criteria seem to be ignored. */
3329     search.dwSize = sizeof(search);
3330     search.dwFlags = D3DFDS_COLORMODEL;
3331     search.dcmColorModel = 0xdeadbeef;
3332     result.dwSize = sizeof(result);
3333
3334     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3335     todo_wine
3336     ok(hr == D3D_OK,
3337        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3338 }
3339
3340 static void BackBuffer3DCreateSurfaceTest(void)
3341 {
3342     DDSURFACEDESC ddsd;
3343     DDSURFACEDESC created_ddsd;
3344     DDSURFACEDESC2 ddsd2;
3345     IDirectDrawSurface *surf;
3346     IDirectDrawSurface4 *surf4;
3347     IDirectDrawSurface7 *surf7;
3348     HRESULT hr;
3349     IDirectDraw2 *dd2;
3350     IDirectDraw4 *dd4;
3351     IDirectDraw7 *dd7;
3352     DDCAPS ddcaps;
3353     IDirect3DDevice *d3dhal;
3354
3355     const DWORD caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3356     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3357
3358     memset(&ddcaps, 0, sizeof(ddcaps));
3359     ddcaps.dwSize = sizeof(DDCAPS);
3360     hr = IDirectDraw_GetCaps(DirectDraw1, &ddcaps, NULL);
3361     ok(SUCCEEDED(hr), "DirectDraw_GetCaps failed: 0x%08x\n", hr);
3362     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3363     {
3364         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3365         return ;
3366     }
3367
3368     memset(&ddsd, 0, sizeof(ddsd));
3369     ddsd.dwSize = sizeof(ddsd);
3370     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3371     ddsd.dwWidth = 64;
3372     ddsd.dwHeight = 64;
3373     ddsd.ddsCaps.dwCaps = caps;
3374     memset(&ddsd2, 0, sizeof(ddsd2));
3375     ddsd2.dwSize = sizeof(ddsd2);
3376     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3377     ddsd2.dwWidth = 64;
3378     ddsd2.dwHeight = 64;
3379     ddsd2.ddsCaps.dwCaps = caps;
3380     memset(&created_ddsd, 0, sizeof(created_ddsd));
3381     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3382
3383     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
3384     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3385     if (surf != NULL)
3386     {
3387         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3388         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3389         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3390            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3391            expected_caps);
3392
3393         hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3394         /* Currently Wine only supports the creation of one Direct3D device
3395            for a given DirectDraw instance. It has been created already
3396            in D3D1_createObjects() - IID_IDirect3DRGBDevice */
3397         todo_wine ok(SUCCEEDED(hr), "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3398
3399         if (SUCCEEDED(hr))
3400             IDirect3DDevice_Release(d3dhal);
3401
3402         IDirectDrawSurface_Release(surf);
3403     }
3404
3405     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw2, (void **) &dd2);
3406     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3407
3408     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3409     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3410        DDERR_INVALIDCAPS, hr);
3411
3412     IDirectDraw2_Release(dd2);
3413
3414     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void **) &dd4);
3415     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3416
3417     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3418     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3419        DDERR_INVALIDCAPS, hr);
3420
3421     IDirectDraw4_Release(dd4);
3422
3423     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw7, (void **) &dd7);
3424     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3425
3426     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3427     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3428        DDERR_INVALIDCAPS, hr);
3429
3430     IDirectDraw7_Release(dd7);
3431 }
3432
3433 static void BackBuffer3DAttachmentTest(void)
3434 {
3435     HRESULT hr;
3436     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3437     DDSURFACEDESC ddsd;
3438     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3439
3440     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3441     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3442
3443     /* Perform attachment tests on a back-buffer */
3444     memset(&ddsd, 0, sizeof(ddsd));
3445     ddsd.dwSize = sizeof(ddsd);
3446     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3447     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3448     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3449     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3450     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface2, NULL);
3451     ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3452
3453     if (surface2 != NULL)
3454     {
3455         /* Try a single primary and a two back buffers */
3456         memset(&ddsd, 0, sizeof(ddsd));
3457         ddsd.dwSize = sizeof(ddsd);
3458         ddsd.dwFlags = DDSD_CAPS;
3459         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3460         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface1, NULL);
3461         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3462
3463         memset(&ddsd, 0, sizeof(ddsd));
3464         ddsd.dwSize = sizeof(ddsd);
3465         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3466         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3467         ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3468         ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3469         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface3, NULL);
3470         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3471
3472         /* This one has a different size */
3473         memset(&ddsd, 0, sizeof(ddsd));
3474         ddsd.dwSize = sizeof(ddsd);
3475         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3476         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3477         ddsd.dwWidth = 128;
3478         ddsd.dwHeight = 128;
3479         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface4, NULL);
3480         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3481
3482         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3483         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3484            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3485         if(SUCCEEDED(hr))
3486         {
3487             /* Try the reverse without detaching first */
3488             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3489             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3490             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3491             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3492         }
3493         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3494         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3495            "Attaching a front buffer to a back buffer returned %08x\n", hr);
3496         if(SUCCEEDED(hr))
3497         {
3498             /* Try to detach reversed */
3499             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3500             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3501             /* Now the proper detach */
3502             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3503             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3504         }
3505         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3506         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3507            "Attaching a back buffer to another back buffer returned %08x\n", hr);
3508         if(SUCCEEDED(hr))
3509         {
3510             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
3511             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3512         }
3513         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
3514         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
3515         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
3516         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
3517
3518         IDirectDrawSurface_Release(surface4);
3519         IDirectDrawSurface_Release(surface3);
3520         IDirectDrawSurface_Release(surface2);
3521         IDirectDrawSurface_Release(surface1);
3522     }
3523
3524     hr =IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
3525     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3526
3527     DestroyWindow(window);
3528 }
3529
3530 static void test_window_style(void)
3531 {
3532     LONG style, exstyle, tmp;
3533     RECT fullscreen_rect, r;
3534     IDirectDraw7 *ddraw7;
3535     HWND window;
3536     HRESULT hr;
3537     ULONG ref;
3538
3539     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3540     if (FAILED(hr))
3541     {
3542         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3543         return;
3544     }
3545
3546     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
3547             0, 0, 100, 100, 0, 0, 0, 0);
3548
3549     style = GetWindowLongA(window, GWL_STYLE);
3550     exstyle = GetWindowLongA(window, GWL_EXSTYLE);
3551     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
3552
3553     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3554     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3555     if (FAILED(hr))
3556     {
3557         IDirectDraw7_Release(ddraw7);
3558         DestroyWindow(window);
3559         return;
3560     }
3561
3562     tmp = GetWindowLongA(window, GWL_STYLE);
3563     todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
3564     tmp = GetWindowLongA(window, GWL_EXSTYLE);
3565     todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
3566
3567     GetWindowRect(window, &r);
3568     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3569             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3570             r.left, r.top, r.right, r.bottom);
3571     GetClientRect(window, &r);
3572     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3573
3574     ref = IDirectDraw7_Release(ddraw7);
3575     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3576
3577     DestroyWindow(window);
3578 }
3579
3580 static void test_redundant_mode_set(void)
3581 {
3582     DDSURFACEDESC2 surface_desc = {0};
3583     IDirectDraw7 *ddraw7;
3584     HWND window;
3585     HRESULT hr;
3586     RECT r, s;
3587     ULONG ref;
3588
3589     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3590     if (FAILED(hr))
3591     {
3592         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3593         return;
3594     }
3595
3596     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
3597             0, 0, 100, 100, 0, 0, 0, 0);
3598
3599     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3600     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3601     if (FAILED(hr))
3602     {
3603         IDirectDraw7_Release(ddraw7);
3604         DestroyWindow(window);
3605         return;
3606     }
3607
3608     surface_desc.dwSize = sizeof(surface_desc);
3609     hr = IDirectDraw7_GetDisplayMode(ddraw7, &surface_desc);
3610     ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
3611
3612     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
3613             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3614     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3615
3616     GetWindowRect(window, &r);
3617     r.right /= 2;
3618     r.bottom /= 2;
3619     SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
3620     GetWindowRect(window, &s);
3621     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3622             r.left, r.top, r.right, r.bottom,
3623             s.left, s.top, s.right, s.bottom);
3624
3625     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
3626             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3627     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3628
3629     GetWindowRect(window, &s);
3630     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3631             r.left, r.top, r.right, r.bottom,
3632             s.left, s.top, s.right, s.bottom);
3633
3634     ref = IDirectDraw7_Release(ddraw7);
3635     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3636
3637     DestroyWindow(window);
3638 }
3639
3640 static SIZE screen_size;
3641
3642 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3643 {
3644     if (message == WM_SIZE)
3645     {
3646         screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
3647         screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
3648     }
3649
3650     return test_proc(hwnd, message, wparam, lparam);
3651 }
3652
3653 static void test_coop_level_mode_set(void)
3654 {
3655     IDirectDrawSurface7 *primary;
3656     RECT fullscreen_rect, r, s;
3657     IDirectDraw7 *ddraw7;
3658     DDSURFACEDESC2 ddsd;
3659     WNDCLASSA wc = {0};
3660     HWND window;
3661     HRESULT hr;
3662     ULONG ref;
3663
3664     static const UINT exclusive_messages[] =
3665     {
3666         WM_WINDOWPOSCHANGING,
3667         WM_WINDOWPOSCHANGED,
3668         WM_SIZE,
3669         WM_DISPLAYCHANGE,
3670         0,
3671     };
3672
3673     static const UINT normal_messages[] =
3674     {
3675         WM_DISPLAYCHANGE,
3676         0,
3677     };
3678
3679     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3680     if (FAILED(hr))
3681     {
3682         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3683         return;
3684     }
3685
3686     wc.lpfnWndProc = mode_set_proc;
3687     wc.lpszClassName = "d3d7_test_wndproc_wc";
3688     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3689
3690     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
3691             0, 0, 100, 100, 0, 0, 0, 0);
3692
3693     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
3694     SetRect(&s, 0, 0, 640, 480);
3695
3696     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3697     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3698     if (FAILED(hr))
3699     {
3700         IDirectDraw7_Release(ddraw7);
3701         goto done;
3702     }
3703
3704     GetWindowRect(window, &r);
3705     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3706             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3707             r.left, r.top, r.right, r.bottom);
3708
3709     memset(&ddsd, 0, sizeof(ddsd));
3710     ddsd.dwSize = sizeof(ddsd);
3711     ddsd.dwFlags = DDSD_CAPS;
3712     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3713
3714     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3715     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3716     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3717     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3718     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3719             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3720     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3721             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3722
3723     GetWindowRect(window, &r);
3724     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3725             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3726             r.left, r.top, r.right, r.bottom);
3727
3728     expect_messages = exclusive_messages;
3729     screen_size.cx = 0;
3730     screen_size.cy = 0;
3731
3732     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
3733     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3734
3735     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3736     expect_messages = NULL;
3737     ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
3738             "Expected screen size %ux%u, got %ux%u.\n",
3739             s.right, s.bottom, screen_size.cx, screen_size.cy);
3740
3741     GetWindowRect(window, &r);
3742     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3743             s.left, s.top, s.right, s.bottom,
3744             r.left, r.top, r.right, r.bottom);
3745
3746     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3747     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3748     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3749             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3750     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3751             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3752     IDirectDrawSurface7_Release(primary);
3753
3754     memset(&ddsd, 0, sizeof(ddsd));
3755     ddsd.dwSize = sizeof(ddsd);
3756     ddsd.dwFlags = DDSD_CAPS;
3757     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3758
3759     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3760     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3761     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3762     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3763     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
3764             s.right - s.left, ddsd.dwWidth);
3765     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
3766             s.bottom - s.top, ddsd.dwHeight);
3767
3768     GetWindowRect(window, &r);
3769     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3770             s.left, s.top, s.right, s.bottom,
3771             r.left, r.top, r.right, r.bottom);
3772
3773     expect_messages = exclusive_messages;
3774     screen_size.cx = 0;
3775     screen_size.cy = 0;
3776
3777     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
3778     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3779
3780     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3781     expect_messages = NULL;
3782     ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
3783             "Expected screen size %ux%u, got %ux%u.\n",
3784             fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
3785
3786     GetWindowRect(window, &r);
3787     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3788             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3789             r.left, r.top, r.right, r.bottom);
3790
3791     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3792     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3793     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
3794             s.right - s.left, ddsd.dwWidth);
3795     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
3796             s.bottom - s.top, ddsd.dwHeight);
3797     IDirectDrawSurface7_Release(primary);
3798
3799     memset(&ddsd, 0, sizeof(ddsd));
3800     ddsd.dwSize = sizeof(ddsd);
3801     ddsd.dwFlags = DDSD_CAPS;
3802     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3803
3804     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3805     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3806     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3807     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3808     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3809             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3810     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3811             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3812
3813     GetWindowRect(window, &r);
3814     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3815             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3816             r.left, r.top, r.right, r.bottom);
3817
3818     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3819     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3820
3821     GetWindowRect(window, &r);
3822     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3823             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3824             r.left, r.top, r.right, r.bottom);
3825
3826     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3827     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3828     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3829             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3830     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3831             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3832     IDirectDrawSurface7_Release(primary);
3833
3834     memset(&ddsd, 0, sizeof(ddsd));
3835     ddsd.dwSize = sizeof(ddsd);
3836     ddsd.dwFlags = DDSD_CAPS;
3837     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3838
3839     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3840     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3841     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3842     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3843     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3844             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3845     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3846             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3847
3848     GetWindowRect(window, &r);
3849     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3850             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3851             r.left, r.top, r.right, r.bottom);
3852
3853     expect_messages = normal_messages;
3854     screen_size.cx = 0;
3855     screen_size.cy = 0;
3856
3857     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
3858     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3859
3860     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3861     expect_messages = NULL;
3862     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3863
3864     GetWindowRect(window, &r);
3865     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3866             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3867             r.left, r.top, r.right, r.bottom);
3868
3869     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3870     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3871     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3872             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3873     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3874             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3875     IDirectDrawSurface7_Release(primary);
3876
3877     memset(&ddsd, 0, sizeof(ddsd));
3878     ddsd.dwSize = sizeof(ddsd);
3879     ddsd.dwFlags = DDSD_CAPS;
3880     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3881
3882     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3883     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3884     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3885     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3886     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
3887             s.right - s.left, ddsd.dwWidth);
3888     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
3889             s.bottom - s.top, ddsd.dwHeight);
3890
3891     GetWindowRect(window, &r);
3892     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3893             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3894             r.left, r.top, r.right, r.bottom);
3895
3896     expect_messages = normal_messages;
3897     screen_size.cx = 0;
3898     screen_size.cy = 0;
3899
3900     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
3901     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3902
3903     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3904     expect_messages = NULL;
3905     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3906
3907     GetWindowRect(window, &r);
3908     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3909             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3910             r.left, r.top, r.right, r.bottom);
3911
3912     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3913     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3914     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
3915             s.right - s.left, ddsd.dwWidth);
3916     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
3917             s.bottom - s.top, ddsd.dwHeight);
3918     IDirectDrawSurface7_Release(primary);
3919
3920     memset(&ddsd, 0, sizeof(ddsd));
3921     ddsd.dwSize = sizeof(ddsd);
3922     ddsd.dwFlags = DDSD_CAPS;
3923     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3924
3925     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3926     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3927     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3928     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3929     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3930             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3931     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3932             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3933
3934     GetWindowRect(window, &r);
3935     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3936             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3937             r.left, r.top, r.right, r.bottom);
3938
3939     /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3940      * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3941      * not DDSCL_FULLSCREEN. */
3942     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3943     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3944
3945     GetWindowRect(window, &r);
3946     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3947             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3948             r.left, r.top, r.right, r.bottom);
3949
3950     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3951     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3952     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3953             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3954     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3955             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3956     IDirectDrawSurface7_Release(primary);
3957
3958     memset(&ddsd, 0, sizeof(ddsd));
3959     ddsd.dwSize = sizeof(ddsd);
3960     ddsd.dwFlags = DDSD_CAPS;
3961     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3962
3963     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3964     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3965     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3966     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3967     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3968             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3969     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3970             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3971
3972     GetWindowRect(window, &r);
3973     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3974             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3975             r.left, r.top, r.right, r.bottom);
3976
3977     expect_messages = normal_messages;
3978     screen_size.cx = 0;
3979     screen_size.cy = 0;
3980
3981     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
3982     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3983
3984     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3985     expect_messages = NULL;
3986     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3987
3988     GetWindowRect(window, &r);
3989     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3990             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3991             r.left, r.top, r.right, r.bottom);
3992
3993     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3994     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3995     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3996             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3997     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3998             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3999     IDirectDrawSurface7_Release(primary);
4000
4001     memset(&ddsd, 0, sizeof(ddsd));
4002     ddsd.dwSize = sizeof(ddsd);
4003     ddsd.dwFlags = DDSD_CAPS;
4004     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4005
4006     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4007     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4008     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4009     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4010     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4011             s.right - s.left, ddsd.dwWidth);
4012     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4013             s.bottom - s.top, ddsd.dwHeight);
4014
4015     GetWindowRect(window, &r);
4016     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4017             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4018             r.left, r.top, r.right, r.bottom);
4019
4020     expect_messages = normal_messages;
4021     screen_size.cx = 0;
4022     screen_size.cy = 0;
4023
4024     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4025     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4026
4027     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4028     expect_messages = NULL;
4029     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4030
4031     GetWindowRect(window, &r);
4032     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4033             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4034             r.left, r.top, r.right, r.bottom);
4035
4036     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4037     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4038     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4039             s.right - s.left, ddsd.dwWidth);
4040     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4041             s.bottom - s.top, ddsd.dwHeight);
4042     IDirectDrawSurface7_Release(primary);
4043
4044     memset(&ddsd, 0, sizeof(ddsd));
4045     ddsd.dwSize = sizeof(ddsd);
4046     ddsd.dwFlags = DDSD_CAPS;
4047     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4048
4049     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4050     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4051     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4052     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4053     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4054             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4055     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4056             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4057     IDirectDrawSurface7_Release(primary);
4058
4059     GetWindowRect(window, &r);
4060     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4061             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4062             r.left, r.top, r.right, r.bottom);
4063
4064     ref = IDirectDraw7_Release(ddraw7);
4065     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4066
4067     GetWindowRect(window, &r);
4068     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4069             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4070             r.left, r.top, r.right, r.bottom);
4071
4072 done:
4073     expect_messages = NULL;
4074     DestroyWindow(window);
4075     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
4076 }
4077
4078 static void dump_format(const DDPIXELFORMAT *fmt)
4079 {
4080     trace("dwFlags %08x, FourCC %08x, dwZBufferBitDepth %u, stencil %08x\n", fmt->dwFlags, fmt->dwFourCC,
4081           U1(*fmt).dwZBufferBitDepth, U2(*fmt).dwStencilBitDepth);
4082     trace("dwZBitMask %08x, dwStencilBitMask %08x, dwRGBZBitMask %08x\n", U3(*fmt).dwZBitMask,
4083           U4(*fmt).dwStencilBitMask, U5(*fmt).dwRGBZBitMask);
4084 }
4085
4086 static HRESULT WINAPI enum_z_fmt_cb(DDPIXELFORMAT *fmt, void *ctx)
4087 {
4088     static const DDPIXELFORMAT formats[] =
4089     {
4090         {
4091             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4092             {16}, {0}, {0x0000ffff}, {0x00000000}, {0x00000000}
4093         },
4094         {
4095             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4096             {32}, {0}, {0xffffff00}, {0x00000000}, {0x00000000}
4097         },
4098         {
4099             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
4100             {32}, {8}, {0xffffff00}, {0x000000ff}, {0x00000000}
4101         },
4102         {
4103             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4104             {32}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4105         },
4106         {
4107             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
4108             {32}, {8}, {0x00ffffff}, {0xff000000}, {0x00000000}
4109         },
4110         {
4111             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4112             {24}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4113         },
4114         {
4115             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4116             {32}, {0}, {0xffffffff}, {0x00000000}, {0x00000000}
4117         },
4118     };
4119     unsigned int *count = ctx, i, expected_pitch;
4120     DDSURFACEDESC2 ddsd;
4121     IDirectDrawSurface7 *surface;
4122     HRESULT hr;
4123     (*count)++;
4124
4125     memset(&ddsd, 0, sizeof(ddsd));
4126     ddsd.dwSize = sizeof(ddsd);
4127     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4128     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4129     U4(ddsd).ddpfPixelFormat = *fmt;
4130     ddsd.dwWidth = 1024;
4131     ddsd.dwHeight = 1024;
4132     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface, NULL);
4133     ok(SUCCEEDED(hr), "IDirectDraw7_CreateSurface failed, hr %#x.\n", hr);
4134     memset(&ddsd, 0, sizeof(ddsd));
4135     ddsd.dwSize = sizeof(ddsd);
4136     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4137     ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc failed, hr %#x.\n", hr);
4138     IDirectDrawSurface7_Release(surface);
4139
4140     ok(ddsd.dwFlags & DDSD_PIXELFORMAT, "DDSD_PIXELFORMAT is not set\n");
4141     ok(!(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH), "DDSD_ZBUFFERBITDEPTH is set\n");
4142
4143     /* 24 bit unpadded depth buffers are actually padded(Geforce 9600, Win7,
4144      * Radeon 9000M WinXP) */
4145     if (U1(*fmt).dwZBufferBitDepth == 24) expected_pitch = ddsd.dwWidth * 4;
4146     else expected_pitch = ddsd.dwWidth * U1(*fmt).dwZBufferBitDepth / 8;
4147
4148     /* Some formats(16 bit depth without stencil) return pitch 0
4149      *
4150      * The Radeon X1600 Catalyst 10.2 Windows XP driver returns an otherwise sane
4151      * pitch with an extra 128 bytes, regardless of the format and width */
4152     if (U1(ddsd).lPitch != 0 && U1(ddsd).lPitch != expected_pitch
4153             && !broken(U1(ddsd).lPitch == expected_pitch + 128))
4154     {
4155         ok(0, "Z buffer pitch is %u, expected %u\n", U1(ddsd).lPitch, expected_pitch);
4156         dump_format(fmt);
4157     }
4158
4159     for (i = 0; i < (sizeof(formats)/sizeof(*formats)); i++)
4160     {
4161         if (memcmp(&formats[i], fmt, fmt->dwSize) == 0) return DDENUMRET_OK;
4162     }
4163
4164     ok(0, "Unexpected Z format enumerated\n");
4165     dump_format(fmt);
4166
4167     return DDENUMRET_OK;
4168 }
4169
4170 static void z_format_test(void)
4171 {
4172     unsigned int count = 0;
4173     HRESULT hr;
4174
4175     hr = IDirect3D7_EnumZBufferFormats(lpD3D, &IID_IDirect3DHALDevice, enum_z_fmt_cb, &count);
4176     if (hr == DDERR_NOZBUFFERHW)
4177     {
4178         skip("Z buffers not supported, skipping Z buffer format test\n");
4179         return;
4180     }
4181
4182     ok(SUCCEEDED(hr), "IDirect3D7_EnumZBufferFormats failed, hr %#x.\n", hr);
4183     ok(count, "Expected at least one supported Z Buffer format\n");
4184 }
4185
4186 static void test_initialize(void)
4187 {
4188     IDirectDraw7 *ddraw7;
4189     IDirectDraw4 *ddraw4;
4190     IDirectDraw2 *ddraw2;
4191     IDirectDraw *ddraw1;
4192     IDirect3D *d3d1;
4193     HRESULT hr;
4194
4195     /* IDirectDraw */
4196     if (FAILED(hr = DirectDrawCreate(NULL, &ddraw1, NULL)))
4197     {
4198         skip("Failed to create IDirectDraw object (%#x), skipping tests.\n", hr);
4199         return;
4200     }
4201
4202     hr = IDirectDraw_Initialize(ddraw1, NULL);
4203     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4204     IDirectDraw_Release(ddraw1);
4205
4206     CoInitialize(NULL);
4207     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw1);
4208     ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
4209     hr = IDirectDraw_Initialize(ddraw1, NULL);
4210     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4211     hr = IDirectDraw_Initialize(ddraw1, NULL);
4212     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4213     IDirectDraw_Release(ddraw1);
4214     CoUninitialize();
4215
4216     hr = DirectDrawCreate(NULL, &ddraw1, NULL);
4217     ok(SUCCEEDED(hr), "Failed to create IDirectDraw object, hr %#x.\n", hr);
4218
4219     /* IDirectDraw2 */
4220     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2)))
4221     {
4222         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4223         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4224         IDirectDraw2_Release(ddraw2);
4225
4226         CoInitialize(NULL);
4227         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw2);
4228         ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
4229         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4230         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4231         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4232         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4233         IDirectDraw2_Release(ddraw2);
4234         CoUninitialize();
4235     }
4236     else skip("Failed to query IDirectDraw2 interface, skipping tests.\n");
4237
4238     /* IDirectDraw4 */
4239     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4)))
4240     {
4241         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4242         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4243         IDirectDraw4_Release(ddraw4);
4244
4245         CoInitialize(NULL);
4246         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw4);
4247         ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
4248         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4249         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4250         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4251         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4252         IDirectDraw4_Release(ddraw4);
4253         CoUninitialize();
4254     }
4255     else skip("Failed to query IDirectDraw4 interface, skipping tests.\n");
4256
4257     /* IDirect3D */
4258     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D, (void **)&d3d1)))
4259     {
4260         IDirectDraw *ddraw;
4261
4262         hr = IDirect3D_Initialize(d3d1, NULL);
4263         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4264         IDirect3D_Release(d3d1);
4265
4266         if (0) /* This crashes on the W2KPROSP4 testbot. */
4267         {
4268             CoInitialize(NULL);
4269             hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d1);
4270             ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
4271             CoUninitialize();
4272         }
4273
4274         CoInitialize(NULL);
4275         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
4276         ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
4277         hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d1);
4278         ok(SUCCEEDED(hr), "Failed to query IDirect3D interface, hr %#x.\n", hr);
4279         IDirectDraw_Release(ddraw);
4280         /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
4281         hr = IDirect3D_Initialize(d3d1, NULL);
4282         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4283         hr = IDirectDraw_Initialize(ddraw, NULL);
4284         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4285         hr = IDirectDraw_Initialize(ddraw, NULL);
4286         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4287         IDirect3D_Release(d3d1);
4288         CoUninitialize();
4289     }
4290     else skip("Failed to query IDirect3D interface, skipping tests.\n");
4291
4292     IDirectDraw_Release(ddraw1);
4293
4294     /* IDirectDraw7 */
4295     if (FAILED(hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL)))
4296     {
4297         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4298         return;
4299     }
4300     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4301     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4302     IDirectDraw7_Release(ddraw7);
4303
4304     CoInitialize(NULL);
4305     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw7);
4306     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
4307     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4308     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4309     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4310     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4311     IDirectDraw7_Release(ddraw7);
4312     CoUninitialize();
4313 }
4314
4315 static void test_coop_level_surf_create(void)
4316 {
4317     IDirectDrawSurface7 *surface7;
4318     IDirectDrawSurface4 *surface4;
4319     IDirectDrawSurface *surface1;
4320     IDirectDraw7 *ddraw7;
4321     IDirectDraw4 *ddraw4;
4322     IDirectDraw2 *ddraw2;
4323     IDirectDraw *ddraw1;
4324     DDSURFACEDESC2 ddsd2;
4325     DDSURFACEDESC ddsd;
4326     HRESULT hr;
4327
4328     /* IDirectDraw */
4329     if (FAILED(hr = DirectDrawCreate(NULL, &ddraw1, NULL)))
4330     {
4331         skip("Failed to create IDirectDraw object (%#x), skipping tests.\n", hr);
4332         return;
4333     }
4334
4335     memset(&ddsd, 0, sizeof(ddsd));
4336     ddsd.dwSize = sizeof(ddsd);
4337     ddsd.dwFlags = DDSD_CAPS;
4338     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4339     hr = IDirectDraw_CreateSurface(ddraw1, &ddsd, &surface1, NULL);
4340     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4341
4342     /* IDirectDraw2 */
4343     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2)))
4344     {
4345         memset(&ddsd, 0, sizeof(ddsd));
4346         ddsd.dwSize = sizeof(ddsd);
4347         ddsd.dwFlags = DDSD_CAPS;
4348         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4349         hr = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &surface1, NULL);
4350         ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4351
4352         IDirectDraw2_Release(ddraw2);
4353     }
4354     else skip("Failed to query IDirectDraw2 interface, skipping tests.\n");
4355
4356     /* IDirectDraw4 */
4357     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4)))
4358     {
4359         memset(&ddsd2, 0, sizeof(ddsd2));
4360         ddsd2.dwSize = sizeof(ddsd2);
4361         ddsd2.dwFlags = DDSD_CAPS;
4362         ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4363         hr = IDirectDraw4_CreateSurface(ddraw4, &ddsd2, &surface4, NULL);
4364         ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4365
4366         IDirectDraw4_Release(ddraw4);
4367     }
4368     else skip("Failed to query IDirectDraw4 interface, skipping tests.\n");
4369
4370     IDirectDraw_Release(ddraw1);
4371
4372     /* IDirectDraw7 */
4373     if (FAILED(hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL)))
4374     {
4375         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4376         return;
4377     }
4378
4379     memset(&ddsd2, 0, sizeof(ddsd2));
4380     ddsd2.dwSize = sizeof(ddsd2);
4381     ddsd2.dwFlags = DDSD_CAPS;
4382     ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4383     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd2, &surface7, NULL);
4384     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4385
4386     IDirectDraw7_Release(ddraw7);
4387 }
4388
4389 static void test_get_caps1(void)
4390 {
4391     D3DDEVICEDESC hw_caps, hel_caps;
4392     HRESULT hr;
4393     unsigned int i;
4394
4395     memset(&hw_caps, 0, sizeof(hw_caps));
4396     hw_caps.dwSize = sizeof(hw_caps);
4397     hw_caps.dwFlags = 0xdeadbeef;
4398     memset(&hel_caps, 0, sizeof(hel_caps));
4399     hel_caps.dwSize = sizeof(hel_caps);
4400     hel_caps.dwFlags = 0xdeadc0de;
4401
4402     /* NULL pointers */
4403     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, NULL);
4404     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hel caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4405     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4406     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, NULL, &hel_caps);
4407     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hw caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4408     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4409
4410     /* Successful call: Both are modified */
4411     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4412     ok(hr == D3D_OK, "GetCaps with correct size returned hr %#x, expected D3D_OK.\n", hr);
4413     ok(hw_caps.dwFlags != 0xdeadbeef, "hw_caps.dwFlags was not modified: %#x.\n", hw_caps.dwFlags);
4414     ok(hel_caps.dwFlags != 0xdeadc0de, "hel_caps.dwFlags was not modified: %#x.\n", hel_caps.dwFlags);
4415
4416     memset(&hw_caps, 0, sizeof(hw_caps));
4417     hw_caps.dwSize = sizeof(hw_caps);
4418     hw_caps.dwFlags = 0xdeadbeef;
4419     memset(&hel_caps, 0, sizeof(hel_caps));
4420     /* Keep dwSize at 0 */
4421     hel_caps.dwFlags = 0xdeadc0de;
4422
4423     /* If one is invalid the call fails */
4424     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4425     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hel_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4426     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4427     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4428     hel_caps.dwSize = sizeof(hel_caps);
4429     hw_caps.dwSize = sizeof(hw_caps) + 1;
4430     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4431     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hw_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4432     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4433     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4434
4435     for (i = 0; i < 1024; i++)
4436     {
4437         memset(&hw_caps, 0xfe, sizeof(hw_caps));
4438         memset(&hel_caps, 0xfe, sizeof(hel_caps));
4439         hw_caps.dwSize = hel_caps.dwSize = i;
4440         hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4441         switch (i)
4442         {
4443             /* D3DDEVICEDESCSIZE in old sdk versions */
4444             case FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth): /* 172, DirectX 3, IDirect3DDevice1 */
4445                 ok(hw_caps.dwMinTextureWidth == 0xfefefefe, "hw_caps.dwMinTextureWidth was modified: %#x.\n",
4446                         hw_caps.dwMinTextureWidth);
4447                 ok(hel_caps.dwMinTextureWidth == 0xfefefefe, "hel_caps.dwMinTextureWidth was modified: %#x.\n",
4448                         hel_caps.dwMinTextureWidth);
4449                 /* drop through */
4450             case FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat): /* 204, DirectX 5, IDirect3DDevice2 */
4451                 ok(hw_caps.dwMaxTextureRepeat == 0xfefefefe, "hw_caps.dwMaxTextureRepeat was modified: %#x.\n",
4452                         hw_caps.dwMaxTextureRepeat);
4453                 ok(hel_caps.dwMaxTextureRepeat == 0xfefefefe, "hel_caps.dwMaxTextureRepeat was modified: %#x.\n",
4454                         hel_caps.dwMaxTextureRepeat);
4455                 /* drop through */
4456             case sizeof(D3DDEVICEDESC): /* 252, DirectX 6, IDirect3DDevice3 */
4457                 ok(hr == D3D_OK, "GetCaps with size %u returned hr %#x, expected D3D_OK.\n", i, hr);
4458                 break;
4459
4460             default:
4461                 ok(hr == DDERR_INVALIDPARAMS,
4462                         "GetCaps with size %u returned hr %#x, expected DDERR_INVALIDPARAMS.\n", i, hr);
4463                 break;
4464         }
4465     }
4466
4467     /* Different valid sizes are OK */
4468     hw_caps.dwSize = 172;
4469     hel_caps.dwSize = sizeof(D3DDEVICEDESC);
4470     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4471     ok(hr == D3D_OK, "GetCaps with different sizes returned hr %#x, expected D3D_OK.\n", hr);
4472 }
4473
4474 static void test_get_caps7(void)
4475 {
4476     HRESULT hr;
4477     D3DDEVICEDESC7 desc;
4478
4479     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, NULL);
4480     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7::GetCaps(NULL) returned hr %#x, expected INVALIDPARAMS.\n", hr);
4481
4482     memset(&desc, 0, sizeof(desc));
4483     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &desc);
4484     ok(hr == D3D_OK, "IDirect3DDevice7::GetCaps(non-NULL) returned hr %#x, expected D3D_OK.\n", hr);
4485
4486     /* There's no dwSize in D3DDEVICEDESC7 */
4487 }
4488
4489 struct d3d2_test_context
4490 {
4491     IDirectDraw *ddraw;
4492     IDirect3D2 *d3d;
4493     IDirectDrawSurface *surface;
4494     IDirect3DDevice2 *device;
4495     IDirect3DViewport2 *viewport;
4496 };
4497
4498 static void d3d2_release_objects(struct d3d2_test_context *context)
4499 {
4500     LONG ref;
4501     HRESULT hr;
4502
4503     if (context->viewport)
4504     {
4505         hr = IDirect3DDevice2_DeleteViewport(context->device, context->viewport);
4506         ok(hr == D3D_OK, "DeleteViewport returned %08x.\n", hr);
4507         ref = IDirect3DViewport2_Release(context->viewport);
4508         ok(ref == 0, "Viewport has reference count %d, expected 0.\n", ref);
4509     }
4510     if (context->device)
4511     {
4512         ref = IDirect3DDevice2_Release(context->device);
4513         ok(ref == 0, "Device has reference count %d, expected 0.\n", ref);
4514     }
4515     if (context->surface)
4516     {
4517         ref = IDirectDrawSurface_Release(context->surface);
4518         ok(ref == 0, "Surface has reference count %d, expected 0.\n", ref);
4519     }
4520     if (context->d3d)
4521     {
4522         ref = IDirect3D2_Release(context->d3d);
4523         ok(ref == 1, "IDirect3D2 has reference count %d, expected 1.\n", ref);
4524     }
4525     if (context->ddraw)
4526     {
4527         ref = IDirectDraw_Release(context->ddraw);
4528         ok(ref == 0, "DDraw has reference count %d, expected 0.\n", ref);
4529     }
4530 }
4531
4532 static BOOL d3d2_create_objects(struct d3d2_test_context *context)
4533 {
4534     HRESULT hr;
4535     DDSURFACEDESC ddsd;
4536     D3DVIEWPORT vp_data;
4537
4538     memset(context, 0, sizeof(*context));
4539
4540     hr = DirectDrawCreate(NULL, &context->ddraw, NULL);
4541     ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate failed: %08x.\n", hr);
4542     if (!context->ddraw) goto error;
4543
4544     hr = IDirectDraw_SetCooperativeLevel(context->ddraw, NULL, DDSCL_NORMAL);
4545     ok(hr == DD_OK, "SetCooperativeLevel failed: %08x.\n", hr);
4546     if (FAILED(hr)) goto error;
4547
4548     hr = IDirectDraw_QueryInterface(context->ddraw, &IID_IDirect3D2, (void**) &context->d3d);
4549     ok(hr == DD_OK || hr == E_NOINTERFACE, "QueryInterface failed: %08x.\n", hr);
4550     if (!context->d3d) goto error;
4551
4552     memset(&ddsd, 0, sizeof(ddsd));
4553     ddsd.dwSize = sizeof(ddsd);
4554     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4555     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4556     ddsd.dwWidth = 256;
4557     ddsd.dwHeight = 256;
4558     IDirectDraw_CreateSurface(context->ddraw, &ddsd, &context->surface, NULL);
4559     if (!context->surface)
4560     {
4561         skip("DDSCAPS_3DDEVICE surface not available.\n");
4562         goto error;
4563     }
4564
4565     hr = IDirect3D2_CreateDevice(context->d3d, &IID_IDirect3DHALDevice, context->surface, &context->device);
4566     ok(hr == D3D_OK  || hr == E_OUTOFMEMORY || hr == E_NOINTERFACE, "CreateDevice failed: %08x.\n", hr);
4567     if (!context->device) goto error;
4568
4569     hr = IDirect3D2_CreateViewport(context->d3d, &context->viewport, NULL);
4570     ok(hr == D3D_OK, "CreateViewport failed: %08x.\n", hr);
4571     if (!context->viewport) goto error;
4572
4573     hr = IDirect3DDevice2_AddViewport(context->device, context->viewport);
4574     ok(hr == D3D_OK, "AddViewport returned %08x.\n", hr);
4575     vp_data.dwSize = sizeof(vp_data);
4576     vp_data.dwX = 0;
4577     vp_data.dwY = 0;
4578     vp_data.dwWidth = 256;
4579     vp_data.dwHeight = 256;
4580     vp_data.dvScaleX = 1;
4581     vp_data.dvScaleY = 1;
4582     vp_data.dvMaxX = 256;
4583     vp_data.dvMaxY = 256;
4584     vp_data.dvMinZ = 0;
4585     vp_data.dvMaxZ = 1;
4586     hr = IDirect3DViewport2_SetViewport(context->viewport, &vp_data);
4587     ok(hr == D3D_OK, "SetViewport returned %08x.\n", hr);
4588
4589     return TRUE;
4590
4591 error:
4592     d3d2_release_objects(context);
4593     return FALSE;
4594 }
4595
4596 static void test_get_caps2(const struct d3d2_test_context *context)
4597 {
4598     D3DDEVICEDESC hw_caps, hel_caps;
4599     HRESULT hr;
4600     unsigned int i;
4601
4602     memset(&hw_caps, 0, sizeof(hw_caps));
4603     hw_caps.dwSize = sizeof(hw_caps);
4604     hw_caps.dwFlags = 0xdeadbeef;
4605     memset(&hel_caps, 0, sizeof(hel_caps));
4606     hel_caps.dwSize = sizeof(hel_caps);
4607     hel_caps.dwFlags = 0xdeadc0de;
4608
4609     /* NULL pointers */
4610     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, NULL);
4611     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hel caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4612     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4613     hr = IDirect3DDevice2_GetCaps(context->device, NULL, &hel_caps);
4614     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hw caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4615     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4616
4617     /* Successful call: Both are modified */
4618     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4619     ok(hr == D3D_OK, "GetCaps with correct size returned hr %#x, expected D3D_OK.\n", hr);
4620     ok(hw_caps.dwFlags != 0xdeadbeef, "hw_caps.dwFlags was not modified: %#x.\n", hw_caps.dwFlags);
4621     ok(hel_caps.dwFlags != 0xdeadc0de, "hel_caps.dwFlags was not modified: %#x.\n", hel_caps.dwFlags);
4622
4623     memset(&hw_caps, 0, sizeof(hw_caps));
4624     hw_caps.dwSize = sizeof(hw_caps);
4625     hw_caps.dwFlags = 0xdeadbeef;
4626     memset(&hel_caps, 0, sizeof(hel_caps));
4627     /* Keep dwSize at 0 */
4628     hel_caps.dwFlags = 0xdeadc0de;
4629
4630     /* If one is invalid the call fails */
4631     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4632     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hel_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4633     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4634     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4635     hel_caps.dwSize = sizeof(hel_caps);
4636     hw_caps.dwSize = sizeof(hw_caps) + 1;
4637     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4638     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hw_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4639     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4640     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4641
4642     for (i = 0; i < 1024; i++)
4643     {
4644         memset(&hw_caps, 0xfe, sizeof(hw_caps));
4645         memset(&hel_caps, 0xfe, sizeof(hel_caps));
4646         hw_caps.dwSize = hel_caps.dwSize = i;
4647         hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4648         switch (i)
4649         {
4650             /* D3DDEVICEDESCSIZE in old sdk versions */
4651             case FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth): /* 172, DirectX 3, IDirect3DDevice1 */
4652                 ok(hw_caps.dwMinTextureWidth == 0xfefefefe, "dwMinTextureWidth was modified: %#x.\n",
4653                         hw_caps.dwMinTextureWidth);
4654                 ok(hel_caps.dwMinTextureWidth == 0xfefefefe, "dwMinTextureWidth was modified: %#x.\n",
4655                         hel_caps.dwMinTextureWidth);
4656                 /* drop through */
4657             case FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat): /* 204, DirectX 5, IDirect3DDevice2 */
4658                 ok(hw_caps.dwMaxTextureRepeat == 0xfefefefe, "dwMaxTextureRepeat was modified: %#x.\n",
4659                         hw_caps.dwMaxTextureRepeat);
4660                 ok(hel_caps.dwMaxTextureRepeat == 0xfefefefe, "dwMaxTextureRepeat was modified: %#x.\n",
4661                         hel_caps.dwMaxTextureRepeat);
4662                 /* drop through */
4663             case sizeof(D3DDEVICEDESC): /* 252, DirectX 6, IDirect3DDevice3 */
4664                 ok(hr == D3D_OK, "GetCaps with size %u returned hr %#x, expected D3D_OK.\n", i, hr);
4665                 break;
4666
4667             default:
4668                 ok(hr == DDERR_INVALIDPARAMS,
4669                         "GetCaps with size %u returned hr %#x, expected DDERR_INVALIDPARAMS.\n", i, hr);
4670                 break;
4671         }
4672     }
4673
4674     /* Different valid sizes are OK */
4675     hw_caps.dwSize = 172;
4676     hel_caps.dwSize = sizeof(D3DDEVICEDESC);
4677     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4678     ok(hr == D3D_OK, "GetCaps with different sizes returned hr %#x, expected D3D_OK.\n", hr);
4679 }
4680
4681 START_TEST(d3d)
4682 {
4683     struct d3d2_test_context d3d2_context;
4684     void (* const d3d2_tests[])(const struct d3d2_test_context *) =
4685     {
4686         test_get_caps2
4687     };
4688     unsigned int i;
4689
4690     init_function_pointers();
4691     if(!pDirectDrawCreateEx) {
4692         win_skip("function DirectDrawCreateEx not available\n");
4693         return;
4694     }
4695
4696     if(!CreateDirect3D()) {
4697         skip("Skipping d3d7 tests\n");
4698     } else {
4699         LightTest();
4700         StateTest();
4701         SceneTest();
4702         LimitTest();
4703         D3D7EnumTest();
4704         D3D7EnumLifetimeTest();
4705         SetMaterialTest();
4706         ComputeSphereVisibility();
4707         CapsTest();
4708         VertexBufferDescTest();
4709         D3D7_OldRenderStateTest();
4710         DeviceLoadTest();
4711         SetRenderTargetTest();
4712         VertexBufferLockRest();
4713         z_format_test();
4714         test_get_caps7();
4715         ReleaseDirect3D();
4716     }
4717
4718     for (i = 0; i < (sizeof(d3d2_tests) / sizeof(*d3d2_tests)); i++)
4719     {
4720         if (!d3d2_create_objects(&d3d2_context))
4721         {
4722             ok(!i, "Unexpected d3d2 initialization failure.\n");
4723             skip("Skipping d3d2 tests.\n");
4724             break;
4725         }
4726         d3d2_tests[i](&d3d2_context);
4727         d3d2_release_objects(&d3d2_context);
4728     }
4729
4730     if (!D3D1_createObjects()) {
4731         skip("Skipping d3d1 tests\n");
4732     } else {
4733         Direct3D1Test();
4734         TextureLoadTest();
4735         ViewportTest();
4736         FindDevice();
4737         BackBuffer3DCreateSurfaceTest();
4738         BackBuffer3DAttachmentTest();
4739         test_get_caps1();
4740         D3D1_releaseObjects();
4741     }
4742
4743     test_window_style();
4744     test_redundant_mode_set();
4745     test_coop_level_mode_set();
4746     test_initialize();
4747     test_coop_level_surf_create();
4748 }