d3drm: Implement IDirect3DRMMesh_AddGroup.
[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 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
3143  * interface. This prevents subsequent SetCooperativeLevel() calls on a
3144  * different window from failing with DDERR_HWNDALREADYSET. */
3145 static void fix_wndproc(HWND window, LONG_PTR proc)
3146 {
3147     IDirectDraw7 *ddraw7;
3148     HRESULT hr;
3149
3150     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3151     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 object, hr %#x.\n", hr);
3152     if (FAILED(hr)) return;
3153
3154     SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
3155     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3156     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3157     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3158     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3159
3160     IDirectDraw7_Release(ddraw7);
3161 }
3162
3163 static void test_wndproc(void)
3164 {
3165     LONG_PTR proc, ddraw_proc;
3166     IDirectDraw7 *ddraw7;
3167     WNDCLASSA wc = {0};
3168     HWND window;
3169     HRESULT hr;
3170     ULONG ref;
3171
3172     static const UINT messages[] =
3173     {
3174         WM_WINDOWPOSCHANGING,
3175         WM_MOVE,
3176         WM_SIZE,
3177         WM_WINDOWPOSCHANGING,
3178         WM_ACTIVATE,
3179         WM_SETFOCUS,
3180         0,
3181     };
3182
3183     /* DDSCL_EXCLUSIVE replaces the window's window proc. */
3184     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3185     if (FAILED(hr))
3186     {
3187         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3188         return;
3189     }
3190
3191     wc.lpfnWndProc = test_proc;
3192     wc.lpszClassName = "d3d7_test_wndproc_wc";
3193     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3194
3195     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test",
3196             WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3197
3198     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3199     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3200             (LONG_PTR)test_proc, proc);
3201
3202     expect_messages = messages;
3203
3204     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3205     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3206     if (FAILED(hr))
3207     {
3208         IDirectDraw7_Release(ddraw7);
3209         goto done;
3210     }
3211
3212     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3213     expect_messages = NULL;
3214
3215     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3216     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3217             (LONG_PTR)test_proc, proc);
3218
3219     ref = IDirectDraw7_Release(ddraw7);
3220     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3221
3222     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3223     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3224             (LONG_PTR)test_proc, proc);
3225
3226     /* DDSCL_NORMAL doesn't. */
3227     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3228     if (FAILED(hr))
3229     {
3230         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3231         return;
3232     }
3233
3234     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3235     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3236             (LONG_PTR)test_proc, proc);
3237
3238     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3239     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3240     if (FAILED(hr))
3241     {
3242         IDirectDraw7_Release(ddraw7);
3243         goto done;
3244     }
3245
3246     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3247     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3248             (LONG_PTR)test_proc, proc);
3249
3250     ref = IDirectDraw7_Release(ddraw7);
3251     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3252
3253     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3254     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3255             (LONG_PTR)test_proc, proc);
3256
3257     /* The original window proc is only restored by ddraw if the current
3258      * window proc matches the one ddraw set. This also affects switching
3259      * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
3260     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3261     if (FAILED(hr))
3262     {
3263         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3264         return;
3265     }
3266
3267     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3268     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3269             (LONG_PTR)test_proc, proc);
3270
3271     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3272     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3273     if (FAILED(hr))
3274     {
3275         IDirectDraw7_Release(ddraw7);
3276         goto done;
3277     }
3278
3279     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3280     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3281             (LONG_PTR)test_proc, proc);
3282     ddraw_proc = proc;
3283
3284     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3285     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3286     if (FAILED(hr))
3287     {
3288         IDirectDraw7_Release(ddraw7);
3289         goto done;
3290     }
3291
3292     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3293     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3294             (LONG_PTR)test_proc, proc);
3295
3296     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3297     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3298     if (FAILED(hr))
3299     {
3300         IDirectDraw7_Release(ddraw7);
3301         goto done;
3302     }
3303
3304     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3305     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3306             (LONG_PTR)test_proc, proc);
3307
3308     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3309     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3310     if (FAILED(hr))
3311     {
3312         IDirectDraw7_Release(ddraw7);
3313         goto done;
3314     }
3315
3316     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3317     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3318             (LONG_PTR)DefWindowProcA, proc);
3319
3320     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3321     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3322     if (FAILED(hr))
3323     {
3324         IDirectDraw7_Release(ddraw7);
3325         goto done;
3326     }
3327
3328     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
3329     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3330             (LONG_PTR)DefWindowProcA, proc);
3331
3332     ref = IDirectDraw7_Release(ddraw7);
3333     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3334
3335     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3336     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3337             (LONG_PTR)test_proc, proc);
3338
3339     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3340     if (FAILED(hr))
3341     {
3342         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3343         return;
3344     }
3345
3346     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3347     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3348             (LONG_PTR)test_proc, proc);
3349
3350     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3351     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3352     if (FAILED(hr))
3353     {
3354         IDirectDraw7_Release(ddraw7);
3355         goto done;
3356     }
3357
3358     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3359     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3360             (LONG_PTR)test_proc, proc);
3361
3362     ref = IDirectDraw7_Release(ddraw7);
3363     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3364
3365     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3366     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3367             (LONG_PTR)DefWindowProcA, proc);
3368
3369 done:
3370     fix_wndproc(window, (LONG_PTR)test_proc);
3371     expect_messages = NULL;
3372     DestroyWindow(window);
3373     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
3374 }
3375
3376 static void VertexBufferLockRest(void)
3377 {
3378     D3DVERTEXBUFFERDESC desc;
3379     IDirect3DVertexBuffer7 *buffer;
3380     HRESULT hr;
3381     unsigned int i;
3382     void *data;
3383     const struct
3384     {
3385         DWORD flags;
3386         const char *debug_string;
3387         HRESULT result;
3388     }
3389     test_data[] =
3390     {
3391         {0,                                         "(none)",                                       D3D_OK },
3392         {DDLOCK_WAIT,                               "DDLOCK_WAIT",                                  D3D_OK },
3393         {DDLOCK_EVENT,                              "DDLOCK_EVENT",                                 D3D_OK },
3394         {DDLOCK_READONLY,                           "DDLOCK_READONLY",                              D3D_OK },
3395         {DDLOCK_WRITEONLY,                          "DDLOCK_WRITEONLY",                             D3D_OK },
3396         {DDLOCK_NOSYSLOCK,                          "DDLOCK_NOSYSLOCK",                             D3D_OK },
3397         {DDLOCK_NOOVERWRITE,                        "DDLOCK_NOOVERWRITE",                           D3D_OK },
3398         {DDLOCK_DISCARDCONTENTS,                    "DDLOCK_DISCARDCONTENTS",                       D3D_OK },
3399
3400         {DDLOCK_READONLY | DDLOCK_WRITEONLY,        "DDLOCK_READONLY | DDLOCK_WRITEONLY",           D3D_OK },
3401         {DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS,  "DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS",     D3D_OK },
3402         {0xdeadbeef,                                "0xdeadbeef",                                   D3D_OK },
3403     };
3404
3405     memset(&desc, 0 , sizeof(desc));
3406     desc.dwSize = sizeof(desc);
3407     desc.dwCaps = 0;
3408     desc.dwFVF = D3DFVF_XYZ;
3409     desc.dwNumVertices = 64;
3410     hr = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &buffer, 0);
3411     ok(hr == D3D_OK, "IDirect3D7_CreateVertexBuffer failed, 0x%08x\n", hr);
3412
3413     for(i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
3414     {
3415         hr = IDirect3DVertexBuffer7_Lock(buffer, test_data[i].flags, &data, NULL);
3416         ok(hr == test_data[i].result, "Lock flags %s returned 0x%08x, expected 0x%08x\n",
3417             test_data[i].debug_string, hr, test_data[i].result);
3418         if(SUCCEEDED(hr))
3419         {
3420             ok(data != NULL, "The data pointer returned by Lock is NULL\n");
3421             hr = IDirect3DVertexBuffer7_Unlock(buffer);
3422             ok(hr == D3D_OK, "IDirect3DVertexBuffer7_Unlock failed, 0x%08x\n", hr);
3423         }
3424     }
3425
3426     IDirect3DVertexBuffer7_Release(buffer);
3427 }
3428
3429 static void FindDevice(void)
3430 {
3431     static const struct
3432     {
3433         const GUID *guid;
3434         int todo;
3435     } deviceGUIDs[] =
3436     {
3437         {&IID_IDirect3DRampDevice, 1},
3438         {&IID_IDirect3DRGBDevice},
3439     };
3440
3441     static const GUID *nonexistent_deviceGUIDs[] = {&IID_IDirect3DMMXDevice,
3442                                                     &IID_IDirect3DRefDevice,
3443                                                     &IID_IDirect3DTnLHalDevice,
3444                                                     &IID_IDirect3DNullDevice};
3445
3446     D3DFINDDEVICESEARCH search = {0};
3447     D3DFINDDEVICERESULT result = {0};
3448     IDirect3DDevice *d3dhal;
3449     HRESULT hr;
3450     int i;
3451
3452     /* Test invalid parameters. */
3453     hr = IDirect3D_FindDevice(Direct3D1, NULL, NULL);
3454     ok(hr == DDERR_INVALIDPARAMS,
3455        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3456
3457     hr = IDirect3D_FindDevice(Direct3D1, NULL, &result);
3458     ok(hr == DDERR_INVALIDPARAMS,
3459        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3460
3461     hr = IDirect3D_FindDevice(Direct3D1, &search, NULL);
3462     ok(hr == DDERR_INVALIDPARAMS,
3463        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3464
3465     search.dwSize = 0;
3466     result.dwSize = 0;
3467
3468     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3469     ok(hr == DDERR_INVALIDPARAMS,
3470        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3471
3472     search.dwSize = sizeof(search) + 1;
3473     result.dwSize = sizeof(result) + 1;
3474
3475     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3476     ok(hr == DDERR_INVALIDPARAMS,
3477        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3478
3479     /* Specifying no flags is permitted. */
3480     search.dwSize = sizeof(search);
3481     search.dwFlags = 0;
3482     result.dwSize = sizeof(result);
3483
3484     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3485     ok(hr == D3D_OK,
3486        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3487
3488     /* Try an arbitrary non-device GUID. */
3489     search.dwSize = sizeof(search);
3490     search.dwFlags = D3DFDS_GUID;
3491     search.guid = IID_IDirect3D;
3492     result.dwSize = sizeof(result);
3493
3494     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3495     ok(hr == DDERR_NOTFOUND,
3496        "Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", hr);
3497
3498     /* These GUIDs appear to be never present. */
3499     for (i = 0; i < sizeof(nonexistent_deviceGUIDs)/sizeof(nonexistent_deviceGUIDs[0]); i++)
3500     {
3501         search.dwSize = sizeof(search);
3502         search.dwFlags = D3DFDS_GUID;
3503         search.guid = *nonexistent_deviceGUIDs[i];
3504         result.dwSize = sizeof(result);
3505
3506         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3507         ok(hr == DDERR_NOTFOUND,
3508            "[%d] Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", i, hr);
3509     }
3510
3511     /* The HAL device can only be enumerated if hardware acceleration is present. */
3512     search.dwSize = sizeof(search);
3513     search.dwFlags = D3DFDS_GUID;
3514     search.guid = IID_IDirect3DHALDevice;
3515     result.dwSize = sizeof(result);
3516
3517     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3518     trace("IDirect3D::FindDevice returned 0x%08x for the HAL device GUID\n", hr);
3519     if (SUCCEEDED(hr))
3520     {
3521         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3522         /* Currently Wine only supports the creation of one Direct3D device
3523          * for a given DirectDraw instance. */
3524         ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
3525            "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3526
3527         if (SUCCEEDED(hr))
3528             IDirect3DDevice_Release(d3dhal);
3529     }
3530     else
3531     {
3532         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3533         ok(FAILED(hr), "Expected IDirectDrawSurface::QueryInterface to fail, got 0x%08x\n", hr);
3534
3535         if (SUCCEEDED(hr))
3536             IDirect3DDevice_Release(d3dhal);
3537     }
3538
3539     /* These GUIDs appear to be always present. */
3540     for (i = 0; i < sizeof(deviceGUIDs)/sizeof(deviceGUIDs[0]); i++)
3541     {
3542         search.dwSize = sizeof(search);
3543         search.dwFlags = D3DFDS_GUID;
3544         search.guid = *deviceGUIDs[i].guid;
3545         result.dwSize = sizeof(result);
3546
3547         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3548
3549         if (deviceGUIDs[i].todo)
3550         {
3551             todo_wine
3552             ok(hr == D3D_OK,
3553                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3554         }
3555         else
3556         {
3557             ok(hr == D3D_OK,
3558                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3559         }
3560     }
3561
3562     /* Curiously the color model criteria seem to be ignored. */
3563     search.dwSize = sizeof(search);
3564     search.dwFlags = D3DFDS_COLORMODEL;
3565     search.dcmColorModel = 0xdeadbeef;
3566     result.dwSize = sizeof(result);
3567
3568     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3569     todo_wine
3570     ok(hr == D3D_OK,
3571        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3572 }
3573
3574 static void BackBuffer3DCreateSurfaceTest(void)
3575 {
3576     DDSURFACEDESC ddsd;
3577     DDSURFACEDESC created_ddsd;
3578     DDSURFACEDESC2 ddsd2;
3579     IDirectDrawSurface *surf;
3580     IDirectDrawSurface4 *surf4;
3581     IDirectDrawSurface7 *surf7;
3582     HRESULT hr;
3583     IDirectDraw2 *dd2;
3584     IDirectDraw4 *dd4;
3585     IDirectDraw7 *dd7;
3586     DDCAPS ddcaps;
3587     IDirect3DDevice *d3dhal;
3588
3589     const DWORD caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3590     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3591
3592     memset(&ddcaps, 0, sizeof(ddcaps));
3593     ddcaps.dwSize = sizeof(DDCAPS);
3594     hr = IDirectDraw_GetCaps(DirectDraw1, &ddcaps, NULL);
3595     ok(SUCCEEDED(hr), "DirectDraw_GetCaps failed: 0x%08x\n", hr);
3596     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3597     {
3598         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3599         return ;
3600     }
3601
3602     memset(&ddsd, 0, sizeof(ddsd));
3603     ddsd.dwSize = sizeof(ddsd);
3604     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3605     ddsd.dwWidth = 64;
3606     ddsd.dwHeight = 64;
3607     ddsd.ddsCaps.dwCaps = caps;
3608     memset(&ddsd2, 0, sizeof(ddsd2));
3609     ddsd2.dwSize = sizeof(ddsd2);
3610     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3611     ddsd2.dwWidth = 64;
3612     ddsd2.dwHeight = 64;
3613     ddsd2.ddsCaps.dwCaps = caps;
3614     memset(&created_ddsd, 0, sizeof(created_ddsd));
3615     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3616
3617     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
3618     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3619     if (surf != NULL)
3620     {
3621         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3622         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3623         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3624            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3625            expected_caps);
3626
3627         hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3628         /* Currently Wine only supports the creation of one Direct3D device
3629            for a given DirectDraw instance. It has been created already
3630            in D3D1_createObjects() - IID_IDirect3DRGBDevice */
3631         todo_wine ok(SUCCEEDED(hr), "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3632
3633         if (SUCCEEDED(hr))
3634             IDirect3DDevice_Release(d3dhal);
3635
3636         IDirectDrawSurface_Release(surf);
3637     }
3638
3639     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw2, (void **) &dd2);
3640     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3641
3642     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3643     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3644        DDERR_INVALIDCAPS, hr);
3645
3646     IDirectDraw2_Release(dd2);
3647
3648     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void **) &dd4);
3649     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3650
3651     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3652     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3653        DDERR_INVALIDCAPS, hr);
3654
3655     IDirectDraw4_Release(dd4);
3656
3657     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw7, (void **) &dd7);
3658     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3659
3660     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3661     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3662        DDERR_INVALIDCAPS, hr);
3663
3664     IDirectDraw7_Release(dd7);
3665 }
3666
3667 static void BackBuffer3DAttachmentTest(void)
3668 {
3669     HRESULT hr;
3670     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3671     DDSURFACEDESC ddsd;
3672     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3673
3674     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3675     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3676
3677     /* Perform attachment tests on a back-buffer */
3678     memset(&ddsd, 0, sizeof(ddsd));
3679     ddsd.dwSize = sizeof(ddsd);
3680     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3681     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3682     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3683     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3684     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface2, NULL);
3685     ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3686
3687     if (surface2 != NULL)
3688     {
3689         /* Try a single primary and a two back buffers */
3690         memset(&ddsd, 0, sizeof(ddsd));
3691         ddsd.dwSize = sizeof(ddsd);
3692         ddsd.dwFlags = DDSD_CAPS;
3693         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3694         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface1, NULL);
3695         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3696
3697         memset(&ddsd, 0, sizeof(ddsd));
3698         ddsd.dwSize = sizeof(ddsd);
3699         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3700         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3701         ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3702         ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3703         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface3, NULL);
3704         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3705
3706         /* This one has a different size */
3707         memset(&ddsd, 0, sizeof(ddsd));
3708         ddsd.dwSize = sizeof(ddsd);
3709         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3710         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3711         ddsd.dwWidth = 128;
3712         ddsd.dwHeight = 128;
3713         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface4, NULL);
3714         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3715
3716         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3717         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3718            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3719         if(SUCCEEDED(hr))
3720         {
3721             /* Try the reverse without detaching first */
3722             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3723             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3724             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3725             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3726         }
3727         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3728         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3729            "Attaching a front buffer to a back buffer returned %08x\n", hr);
3730         if(SUCCEEDED(hr))
3731         {
3732             /* Try to detach reversed */
3733             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3734             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3735             /* Now the proper detach */
3736             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3737             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3738         }
3739         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3740         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3741            "Attaching a back buffer to another back buffer returned %08x\n", hr);
3742         if(SUCCEEDED(hr))
3743         {
3744             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
3745             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3746         }
3747         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
3748         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
3749         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
3750         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
3751
3752         IDirectDrawSurface_Release(surface4);
3753         IDirectDrawSurface_Release(surface3);
3754         IDirectDrawSurface_Release(surface2);
3755         IDirectDrawSurface_Release(surface1);
3756     }
3757
3758     hr =IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
3759     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3760
3761     DestroyWindow(window);
3762 }
3763
3764 static void test_window_style(void)
3765 {
3766     LONG style, exstyle, tmp;
3767     RECT fullscreen_rect, r;
3768     IDirectDraw7 *ddraw7;
3769     HWND window;
3770     HRESULT hr;
3771     ULONG ref;
3772
3773     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3774     if (FAILED(hr))
3775     {
3776         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3777         return;
3778     }
3779
3780     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
3781             0, 0, 100, 100, 0, 0, 0, 0);
3782
3783     style = GetWindowLongA(window, GWL_STYLE);
3784     exstyle = GetWindowLongA(window, GWL_EXSTYLE);
3785     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
3786
3787     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3788     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3789     if (FAILED(hr))
3790     {
3791         IDirectDraw7_Release(ddraw7);
3792         DestroyWindow(window);
3793         return;
3794     }
3795
3796     tmp = GetWindowLongA(window, GWL_STYLE);
3797     todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
3798     tmp = GetWindowLongA(window, GWL_EXSTYLE);
3799     todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
3800
3801     GetWindowRect(window, &r);
3802     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3803             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3804             r.left, r.top, r.right, r.bottom);
3805     GetClientRect(window, &r);
3806     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3807
3808     ref = IDirectDraw7_Release(ddraw7);
3809     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3810
3811     DestroyWindow(window);
3812 }
3813
3814 static void test_redundant_mode_set(void)
3815 {
3816     DDSURFACEDESC2 surface_desc = {0};
3817     IDirectDraw7 *ddraw7;
3818     HWND window;
3819     HRESULT hr;
3820     RECT r, s;
3821     ULONG ref;
3822
3823     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3824     if (FAILED(hr))
3825     {
3826         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3827         return;
3828     }
3829
3830     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
3831             0, 0, 100, 100, 0, 0, 0, 0);
3832
3833     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3834     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3835     if (FAILED(hr))
3836     {
3837         IDirectDraw7_Release(ddraw7);
3838         DestroyWindow(window);
3839         return;
3840     }
3841
3842     surface_desc.dwSize = sizeof(surface_desc);
3843     hr = IDirectDraw7_GetDisplayMode(ddraw7, &surface_desc);
3844     ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
3845
3846     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
3847             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3848     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3849
3850     GetWindowRect(window, &r);
3851     r.right /= 2;
3852     r.bottom /= 2;
3853     SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
3854     GetWindowRect(window, &s);
3855     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3856             r.left, r.top, r.right, r.bottom,
3857             s.left, s.top, s.right, s.bottom);
3858
3859     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
3860             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3861     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3862
3863     GetWindowRect(window, &s);
3864     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3865             r.left, r.top, r.right, r.bottom,
3866             s.left, s.top, s.right, s.bottom);
3867
3868     ref = IDirectDraw7_Release(ddraw7);
3869     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3870
3871     DestroyWindow(window);
3872 }
3873
3874 static SIZE screen_size;
3875
3876 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3877 {
3878     if (message == WM_SIZE)
3879     {
3880         screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
3881         screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
3882     }
3883
3884     return test_proc(hwnd, message, wparam, lparam);
3885 }
3886
3887 static void test_coop_level_mode_set(void)
3888 {
3889     IDirectDrawSurface7 *primary;
3890     RECT fullscreen_rect, r, s;
3891     IDirectDraw7 *ddraw7;
3892     DDSURFACEDESC2 ddsd;
3893     WNDCLASSA wc = {0};
3894     HWND window;
3895     HRESULT hr;
3896     ULONG ref;
3897
3898     static const UINT exclusive_messages[] =
3899     {
3900         WM_WINDOWPOSCHANGING,
3901         WM_WINDOWPOSCHANGED,
3902         WM_SIZE,
3903         WM_DISPLAYCHANGE,
3904         0,
3905     };
3906
3907     static const UINT normal_messages[] =
3908     {
3909         WM_DISPLAYCHANGE,
3910         0,
3911     };
3912
3913     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3914     if (FAILED(hr))
3915     {
3916         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3917         return;
3918     }
3919
3920     wc.lpfnWndProc = mode_set_proc;
3921     wc.lpszClassName = "d3d7_test_wndproc_wc";
3922     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3923
3924     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
3925             0, 0, 100, 100, 0, 0, 0, 0);
3926
3927     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
3928     SetRect(&s, 0, 0, 640, 480);
3929
3930     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3931     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3932     if (FAILED(hr))
3933     {
3934         IDirectDraw7_Release(ddraw7);
3935         goto done;
3936     }
3937
3938     GetWindowRect(window, &r);
3939     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3940             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3941             r.left, r.top, r.right, r.bottom);
3942
3943     memset(&ddsd, 0, sizeof(ddsd));
3944     ddsd.dwSize = sizeof(ddsd);
3945     ddsd.dwFlags = DDSD_CAPS;
3946     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3947
3948     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3949     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
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
3957     GetWindowRect(window, &r);
3958     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3959             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3960             r.left, r.top, r.right, r.bottom);
3961
3962     expect_messages = exclusive_messages;
3963     screen_size.cx = 0;
3964     screen_size.cy = 0;
3965
3966     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
3967     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3968
3969     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3970     expect_messages = NULL;
3971     ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
3972             "Expected screen size %ux%u, got %ux%u.\n",
3973             s.right, s.bottom, screen_size.cx, screen_size.cy);
3974
3975     GetWindowRect(window, &r);
3976     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3977             s.left, s.top, s.right, s.bottom,
3978             r.left, r.top, r.right, r.bottom);
3979
3980     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3981     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3982     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
3983             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
3984     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
3985             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
3986     IDirectDrawSurface7_Release(primary);
3987
3988     memset(&ddsd, 0, sizeof(ddsd));
3989     ddsd.dwSize = sizeof(ddsd);
3990     ddsd.dwFlags = DDSD_CAPS;
3991     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3992
3993     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
3994     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3995     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3996     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3997     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
3998             s.right - s.left, ddsd.dwWidth);
3999     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4000             s.bottom - s.top, ddsd.dwHeight);
4001
4002     GetWindowRect(window, &r);
4003     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4004             s.left, s.top, s.right, s.bottom,
4005             r.left, r.top, r.right, r.bottom);
4006
4007     expect_messages = exclusive_messages;
4008     screen_size.cx = 0;
4009     screen_size.cy = 0;
4010
4011     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4012     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4013
4014     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4015     expect_messages = NULL;
4016     ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
4017             "Expected screen size %ux%u, got %ux%u.\n",
4018             fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
4019
4020     GetWindowRect(window, &r);
4021     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4022             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4023             r.left, r.top, r.right, r.bottom);
4024
4025     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4026     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4027     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4028             s.right - s.left, ddsd.dwWidth);
4029     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4030             s.bottom - s.top, ddsd.dwHeight);
4031     IDirectDrawSurface7_Release(primary);
4032
4033     memset(&ddsd, 0, sizeof(ddsd));
4034     ddsd.dwSize = sizeof(ddsd);
4035     ddsd.dwFlags = DDSD_CAPS;
4036     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4037
4038     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4039     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4040     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4041     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4042     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4043             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4044     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4045             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4046
4047     GetWindowRect(window, &r);
4048     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4049             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4050             r.left, r.top, r.right, r.bottom);
4051
4052     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4053     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4054
4055     GetWindowRect(window, &r);
4056     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4057             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4058             r.left, r.top, r.right, r.bottom);
4059
4060     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4061     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4062     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4063             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4064     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4065             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4066     IDirectDrawSurface7_Release(primary);
4067
4068     memset(&ddsd, 0, sizeof(ddsd));
4069     ddsd.dwSize = sizeof(ddsd);
4070     ddsd.dwFlags = DDSD_CAPS;
4071     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4072
4073     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4074     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4075     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4076     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4077     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4078             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4079     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4080             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4081
4082     GetWindowRect(window, &r);
4083     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4084             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4085             r.left, r.top, r.right, r.bottom);
4086
4087     expect_messages = normal_messages;
4088     screen_size.cx = 0;
4089     screen_size.cy = 0;
4090
4091     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4092     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4093
4094     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4095     expect_messages = NULL;
4096     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4097
4098     GetWindowRect(window, &r);
4099     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4100             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4101             r.left, r.top, r.right, r.bottom);
4102
4103     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4104     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4105     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4106             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4107     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4108             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4109     IDirectDrawSurface7_Release(primary);
4110
4111     memset(&ddsd, 0, sizeof(ddsd));
4112     ddsd.dwSize = sizeof(ddsd);
4113     ddsd.dwFlags = DDSD_CAPS;
4114     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4115
4116     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4117     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4118     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4119     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4120     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4121             s.right - s.left, ddsd.dwWidth);
4122     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4123             s.bottom - s.top, ddsd.dwHeight);
4124
4125     GetWindowRect(window, &r);
4126     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4127             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4128             r.left, r.top, r.right, r.bottom);
4129
4130     expect_messages = normal_messages;
4131     screen_size.cx = 0;
4132     screen_size.cy = 0;
4133
4134     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4135     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4136
4137     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4138     expect_messages = NULL;
4139     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4140
4141     GetWindowRect(window, &r);
4142     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4143             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4144             r.left, r.top, r.right, r.bottom);
4145
4146     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4147     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4148     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4149             s.right - s.left, ddsd.dwWidth);
4150     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4151             s.bottom - s.top, ddsd.dwHeight);
4152     IDirectDrawSurface7_Release(primary);
4153
4154     memset(&ddsd, 0, sizeof(ddsd));
4155     ddsd.dwSize = sizeof(ddsd);
4156     ddsd.dwFlags = DDSD_CAPS;
4157     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4158
4159     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4160     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4161     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4162     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4163     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4164             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4165     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4166             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4167
4168     GetWindowRect(window, &r);
4169     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4170             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4171             r.left, r.top, r.right, r.bottom);
4172
4173     /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
4174      * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
4175      * not DDSCL_FULLSCREEN. */
4176     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
4177     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4178
4179     GetWindowRect(window, &r);
4180     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4181             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4182             r.left, r.top, r.right, r.bottom);
4183
4184     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4185     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4186     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4187             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4188     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4189             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4190     IDirectDrawSurface7_Release(primary);
4191
4192     memset(&ddsd, 0, sizeof(ddsd));
4193     ddsd.dwSize = sizeof(ddsd);
4194     ddsd.dwFlags = DDSD_CAPS;
4195     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4196
4197     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4198     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4199     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4200     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4201     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4202             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4203     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4204             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4205
4206     GetWindowRect(window, &r);
4207     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4208             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4209             r.left, r.top, r.right, r.bottom);
4210
4211     expect_messages = normal_messages;
4212     screen_size.cx = 0;
4213     screen_size.cy = 0;
4214
4215     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4216     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4217
4218     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4219     expect_messages = NULL;
4220     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4221
4222     GetWindowRect(window, &r);
4223     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4224             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4225             r.left, r.top, r.right, r.bottom);
4226
4227     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4228     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4229     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4230             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4231     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4232             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4233     IDirectDrawSurface7_Release(primary);
4234
4235     memset(&ddsd, 0, sizeof(ddsd));
4236     ddsd.dwSize = sizeof(ddsd);
4237     ddsd.dwFlags = DDSD_CAPS;
4238     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4239
4240     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4241     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4242     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4243     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4244     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4245             s.right - s.left, ddsd.dwWidth);
4246     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4247             s.bottom - s.top, ddsd.dwHeight);
4248
4249     GetWindowRect(window, &r);
4250     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4251             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4252             r.left, r.top, r.right, r.bottom);
4253
4254     expect_messages = normal_messages;
4255     screen_size.cx = 0;
4256     screen_size.cy = 0;
4257
4258     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4259     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4260
4261     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4262     expect_messages = NULL;
4263     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4264
4265     GetWindowRect(window, &r);
4266     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4267             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4268             r.left, r.top, r.right, r.bottom);
4269
4270     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4271     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4272     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
4273             s.right - s.left, ddsd.dwWidth);
4274     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
4275             s.bottom - s.top, ddsd.dwHeight);
4276     IDirectDrawSurface7_Release(primary);
4277
4278     memset(&ddsd, 0, sizeof(ddsd));
4279     ddsd.dwSize = sizeof(ddsd);
4280     ddsd.dwFlags = DDSD_CAPS;
4281     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4282
4283     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd, &primary, NULL);
4284     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4285     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
4286     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4287     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
4288             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
4289     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
4290             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
4291     IDirectDrawSurface7_Release(primary);
4292
4293     GetWindowRect(window, &r);
4294     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4295             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4296             r.left, r.top, r.right, r.bottom);
4297
4298     ref = IDirectDraw7_Release(ddraw7);
4299     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4300
4301     GetWindowRect(window, &r);
4302     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4303             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4304             r.left, r.top, r.right, r.bottom);
4305
4306 done:
4307     expect_messages = NULL;
4308     DestroyWindow(window);
4309     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
4310 }
4311
4312 static void dump_format(const DDPIXELFORMAT *fmt)
4313 {
4314     trace("dwFlags %08x, FourCC %08x, dwZBufferBitDepth %u, stencil %08x\n", fmt->dwFlags, fmt->dwFourCC,
4315           U1(*fmt).dwZBufferBitDepth, U2(*fmt).dwStencilBitDepth);
4316     trace("dwZBitMask %08x, dwStencilBitMask %08x, dwRGBZBitMask %08x\n", U3(*fmt).dwZBitMask,
4317           U4(*fmt).dwStencilBitMask, U5(*fmt).dwRGBZBitMask);
4318 }
4319
4320 static HRESULT WINAPI enum_z_fmt_cb(DDPIXELFORMAT *fmt, void *ctx)
4321 {
4322     static const DDPIXELFORMAT formats[] =
4323     {
4324         {
4325             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4326             {16}, {0}, {0x0000ffff}, {0x00000000}, {0x00000000}
4327         },
4328         {
4329             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4330             {32}, {0}, {0xffffff00}, {0x00000000}, {0x00000000}
4331         },
4332         {
4333             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
4334             {32}, {8}, {0xffffff00}, {0x000000ff}, {0x00000000}
4335         },
4336         {
4337             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4338             {32}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4339         },
4340         {
4341             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
4342             {32}, {8}, {0x00ffffff}, {0xff000000}, {0x00000000}
4343         },
4344         {
4345             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4346             {24}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4347         },
4348         {
4349             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4350             {32}, {0}, {0xffffffff}, {0x00000000}, {0x00000000}
4351         },
4352     };
4353     unsigned int *count = ctx, i, expected_pitch;
4354     DDSURFACEDESC2 ddsd;
4355     IDirectDrawSurface7 *surface;
4356     HRESULT hr;
4357     (*count)++;
4358
4359     memset(&ddsd, 0, sizeof(ddsd));
4360     ddsd.dwSize = sizeof(ddsd);
4361     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4362     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4363     U4(ddsd).ddpfPixelFormat = *fmt;
4364     ddsd.dwWidth = 1024;
4365     ddsd.dwHeight = 1024;
4366     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface, NULL);
4367     ok(SUCCEEDED(hr), "IDirectDraw7_CreateSurface failed, hr %#x.\n", hr);
4368     memset(&ddsd, 0, sizeof(ddsd));
4369     ddsd.dwSize = sizeof(ddsd);
4370     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4371     ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc failed, hr %#x.\n", hr);
4372     IDirectDrawSurface7_Release(surface);
4373
4374     ok(ddsd.dwFlags & DDSD_PIXELFORMAT, "DDSD_PIXELFORMAT is not set\n");
4375     ok(!(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH), "DDSD_ZBUFFERBITDEPTH is set\n");
4376
4377     /* 24 bit unpadded depth buffers are actually padded(Geforce 9600, Win7,
4378      * Radeon 9000M WinXP) */
4379     if (U1(*fmt).dwZBufferBitDepth == 24) expected_pitch = ddsd.dwWidth * 4;
4380     else expected_pitch = ddsd.dwWidth * U1(*fmt).dwZBufferBitDepth / 8;
4381
4382     /* Some formats(16 bit depth without stencil) return pitch 0
4383      *
4384      * The Radeon X1600 Catalyst 10.2 Windows XP driver returns an otherwise sane
4385      * pitch with an extra 128 bytes, regardless of the format and width */
4386     if (U1(ddsd).lPitch != 0 && U1(ddsd).lPitch != expected_pitch
4387             && !broken(U1(ddsd).lPitch == expected_pitch + 128))
4388     {
4389         ok(0, "Z buffer pitch is %u, expected %u\n", U1(ddsd).lPitch, expected_pitch);
4390         dump_format(fmt);
4391     }
4392
4393     for (i = 0; i < (sizeof(formats)/sizeof(*formats)); i++)
4394     {
4395         if (memcmp(&formats[i], fmt, fmt->dwSize) == 0) return DDENUMRET_OK;
4396     }
4397
4398     ok(0, "Unexpected Z format enumerated\n");
4399     dump_format(fmt);
4400
4401     return DDENUMRET_OK;
4402 }
4403
4404 static void z_format_test(void)
4405 {
4406     unsigned int count = 0;
4407     HRESULT hr;
4408
4409     hr = IDirect3D7_EnumZBufferFormats(lpD3D, &IID_IDirect3DHALDevice, enum_z_fmt_cb, &count);
4410     if (hr == DDERR_NOZBUFFERHW)
4411     {
4412         skip("Z buffers not supported, skipping Z buffer format test\n");
4413         return;
4414     }
4415
4416     ok(SUCCEEDED(hr), "IDirect3D7_EnumZBufferFormats failed, hr %#x.\n", hr);
4417     ok(count, "Expected at least one supported Z Buffer format\n");
4418 }
4419
4420 static void test_initialize(void)
4421 {
4422     IDirectDraw7 *ddraw7;
4423     IDirectDraw4 *ddraw4;
4424     IDirectDraw2 *ddraw2;
4425     IDirectDraw *ddraw1;
4426     IDirect3D *d3d1;
4427     HRESULT hr;
4428
4429     /* IDirectDraw */
4430     if (FAILED(hr = DirectDrawCreate(NULL, &ddraw1, NULL)))
4431     {
4432         skip("Failed to create IDirectDraw object (%#x), skipping tests.\n", hr);
4433         return;
4434     }
4435
4436     hr = IDirectDraw_Initialize(ddraw1, NULL);
4437     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4438     IDirectDraw_Release(ddraw1);
4439
4440     CoInitialize(NULL);
4441     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw1);
4442     ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
4443     hr = IDirectDraw_Initialize(ddraw1, NULL);
4444     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4445     hr = IDirectDraw_Initialize(ddraw1, NULL);
4446     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4447     IDirectDraw_Release(ddraw1);
4448     CoUninitialize();
4449
4450     hr = DirectDrawCreate(NULL, &ddraw1, NULL);
4451     ok(SUCCEEDED(hr), "Failed to create IDirectDraw object, hr %#x.\n", hr);
4452
4453     /* IDirectDraw2 */
4454     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2)))
4455     {
4456         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4457         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4458         IDirectDraw2_Release(ddraw2);
4459
4460         CoInitialize(NULL);
4461         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw2);
4462         ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
4463         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4464         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4465         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4466         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4467         IDirectDraw2_Release(ddraw2);
4468         CoUninitialize();
4469     }
4470     else skip("Failed to query IDirectDraw2 interface, skipping tests.\n");
4471
4472     /* IDirectDraw4 */
4473     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4)))
4474     {
4475         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4476         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4477         IDirectDraw4_Release(ddraw4);
4478
4479         CoInitialize(NULL);
4480         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw4);
4481         ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
4482         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4483         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4484         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4485         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4486         IDirectDraw4_Release(ddraw4);
4487         CoUninitialize();
4488     }
4489     else skip("Failed to query IDirectDraw4 interface, skipping tests.\n");
4490
4491     /* IDirect3D */
4492     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D, (void **)&d3d1)))
4493     {
4494         IDirectDraw *ddraw;
4495
4496         hr = IDirect3D_Initialize(d3d1, NULL);
4497         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4498         IDirect3D_Release(d3d1);
4499
4500         if (0) /* This crashes on the W2KPROSP4 testbot. */
4501         {
4502             CoInitialize(NULL);
4503             hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d1);
4504             ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
4505             CoUninitialize();
4506         }
4507
4508         CoInitialize(NULL);
4509         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
4510         ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
4511         hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d1);
4512         ok(SUCCEEDED(hr), "Failed to query IDirect3D interface, hr %#x.\n", hr);
4513         IDirectDraw_Release(ddraw);
4514         /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
4515         hr = IDirect3D_Initialize(d3d1, NULL);
4516         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4517         hr = IDirectDraw_Initialize(ddraw, NULL);
4518         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4519         hr = IDirectDraw_Initialize(ddraw, NULL);
4520         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4521         IDirect3D_Release(d3d1);
4522         CoUninitialize();
4523     }
4524     else skip("Failed to query IDirect3D interface, skipping tests.\n");
4525
4526     IDirectDraw_Release(ddraw1);
4527
4528     /* IDirectDraw7 */
4529     if (FAILED(hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL)))
4530     {
4531         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4532         return;
4533     }
4534     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4535     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4536     IDirectDraw7_Release(ddraw7);
4537
4538     CoInitialize(NULL);
4539     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw7);
4540     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
4541     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4542     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4543     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4544     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4545     IDirectDraw7_Release(ddraw7);
4546     CoUninitialize();
4547 }
4548
4549 static void test_coop_level_surf_create(void)
4550 {
4551     IDirectDrawSurface7 *surface7;
4552     IDirectDrawSurface4 *surface4;
4553     IDirectDrawSurface *surface1;
4554     IDirectDraw7 *ddraw7;
4555     IDirectDraw4 *ddraw4;
4556     IDirectDraw2 *ddraw2;
4557     IDirectDraw *ddraw1;
4558     DDSURFACEDESC2 ddsd2;
4559     DDSURFACEDESC ddsd;
4560     HRESULT hr;
4561
4562     /* IDirectDraw */
4563     if (FAILED(hr = DirectDrawCreate(NULL, &ddraw1, NULL)))
4564     {
4565         skip("Failed to create IDirectDraw object (%#x), skipping tests.\n", hr);
4566         return;
4567     }
4568
4569     memset(&ddsd, 0, sizeof(ddsd));
4570     ddsd.dwSize = sizeof(ddsd);
4571     ddsd.dwFlags = DDSD_CAPS;
4572     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4573     hr = IDirectDraw_CreateSurface(ddraw1, &ddsd, &surface1, NULL);
4574     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4575
4576     /* IDirectDraw2 */
4577     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2)))
4578     {
4579         memset(&ddsd, 0, sizeof(ddsd));
4580         ddsd.dwSize = sizeof(ddsd);
4581         ddsd.dwFlags = DDSD_CAPS;
4582         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4583         hr = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &surface1, NULL);
4584         ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4585
4586         IDirectDraw2_Release(ddraw2);
4587     }
4588     else skip("Failed to query IDirectDraw2 interface, skipping tests.\n");
4589
4590     /* IDirectDraw4 */
4591     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4)))
4592     {
4593         memset(&ddsd2, 0, sizeof(ddsd2));
4594         ddsd2.dwSize = sizeof(ddsd2);
4595         ddsd2.dwFlags = DDSD_CAPS;
4596         ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4597         hr = IDirectDraw4_CreateSurface(ddraw4, &ddsd2, &surface4, NULL);
4598         ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4599
4600         IDirectDraw4_Release(ddraw4);
4601     }
4602     else skip("Failed to query IDirectDraw4 interface, skipping tests.\n");
4603
4604     IDirectDraw_Release(ddraw1);
4605
4606     /* IDirectDraw7 */
4607     if (FAILED(hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL)))
4608     {
4609         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4610         return;
4611     }
4612
4613     memset(&ddsd2, 0, sizeof(ddsd2));
4614     ddsd2.dwSize = sizeof(ddsd2);
4615     ddsd2.dwFlags = DDSD_CAPS;
4616     ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4617     hr = IDirectDraw7_CreateSurface(ddraw7, &ddsd2, &surface7, NULL);
4618     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4619
4620     IDirectDraw7_Release(ddraw7);
4621 }
4622
4623 static void test_get_caps1(void)
4624 {
4625     D3DDEVICEDESC hw_caps, hel_caps;
4626     HRESULT hr;
4627     unsigned int i;
4628
4629     memset(&hw_caps, 0, sizeof(hw_caps));
4630     hw_caps.dwSize = sizeof(hw_caps);
4631     hw_caps.dwFlags = 0xdeadbeef;
4632     memset(&hel_caps, 0, sizeof(hel_caps));
4633     hel_caps.dwSize = sizeof(hel_caps);
4634     hel_caps.dwFlags = 0xdeadc0de;
4635
4636     /* NULL pointers */
4637     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, NULL);
4638     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hel caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4639     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4640     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, NULL, &hel_caps);
4641     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hw caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4642     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4643
4644     /* Successful call: Both are modified */
4645     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4646     ok(hr == D3D_OK, "GetCaps with correct size returned hr %#x, expected D3D_OK.\n", hr);
4647     ok(hw_caps.dwFlags != 0xdeadbeef, "hw_caps.dwFlags was not modified: %#x.\n", hw_caps.dwFlags);
4648     ok(hel_caps.dwFlags != 0xdeadc0de, "hel_caps.dwFlags was not modified: %#x.\n", hel_caps.dwFlags);
4649
4650     memset(&hw_caps, 0, sizeof(hw_caps));
4651     hw_caps.dwSize = sizeof(hw_caps);
4652     hw_caps.dwFlags = 0xdeadbeef;
4653     memset(&hel_caps, 0, sizeof(hel_caps));
4654     /* Keep dwSize at 0 */
4655     hel_caps.dwFlags = 0xdeadc0de;
4656
4657     /* If one is invalid the call fails */
4658     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4659     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hel_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4660     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4661     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4662     hel_caps.dwSize = sizeof(hel_caps);
4663     hw_caps.dwSize = sizeof(hw_caps) + 1;
4664     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4665     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hw_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4666     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4667     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4668
4669     for (i = 0; i < 1024; i++)
4670     {
4671         memset(&hw_caps, 0xfe, sizeof(hw_caps));
4672         memset(&hel_caps, 0xfe, sizeof(hel_caps));
4673         hw_caps.dwSize = hel_caps.dwSize = i;
4674         hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4675         switch (i)
4676         {
4677             /* D3DDEVICEDESCSIZE in old sdk versions */
4678             case FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth): /* 172, DirectX 3, IDirect3DDevice1 */
4679                 ok(hw_caps.dwMinTextureWidth == 0xfefefefe, "hw_caps.dwMinTextureWidth was modified: %#x.\n",
4680                         hw_caps.dwMinTextureWidth);
4681                 ok(hel_caps.dwMinTextureWidth == 0xfefefefe, "hel_caps.dwMinTextureWidth was modified: %#x.\n",
4682                         hel_caps.dwMinTextureWidth);
4683                 /* drop through */
4684             case FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat): /* 204, DirectX 5, IDirect3DDevice2 */
4685                 ok(hw_caps.dwMaxTextureRepeat == 0xfefefefe, "hw_caps.dwMaxTextureRepeat was modified: %#x.\n",
4686                         hw_caps.dwMaxTextureRepeat);
4687                 ok(hel_caps.dwMaxTextureRepeat == 0xfefefefe, "hel_caps.dwMaxTextureRepeat was modified: %#x.\n",
4688                         hel_caps.dwMaxTextureRepeat);
4689                 /* drop through */
4690             case sizeof(D3DDEVICEDESC): /* 252, DirectX 6, IDirect3DDevice3 */
4691                 ok(hr == D3D_OK, "GetCaps with size %u returned hr %#x, expected D3D_OK.\n", i, hr);
4692                 break;
4693
4694             default:
4695                 ok(hr == DDERR_INVALIDPARAMS,
4696                         "GetCaps with size %u returned hr %#x, expected DDERR_INVALIDPARAMS.\n", i, hr);
4697                 break;
4698         }
4699     }
4700
4701     /* Different valid sizes are OK */
4702     hw_caps.dwSize = 172;
4703     hel_caps.dwSize = sizeof(D3DDEVICEDESC);
4704     hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
4705     ok(hr == D3D_OK, "GetCaps with different sizes returned hr %#x, expected D3D_OK.\n", hr);
4706 }
4707
4708 static void test_get_caps7(void)
4709 {
4710     HRESULT hr;
4711     D3DDEVICEDESC7 desc;
4712
4713     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, NULL);
4714     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7::GetCaps(NULL) returned hr %#x, expected INVALIDPARAMS.\n", hr);
4715
4716     memset(&desc, 0, sizeof(desc));
4717     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &desc);
4718     ok(hr == D3D_OK, "IDirect3DDevice7::GetCaps(non-NULL) returned hr %#x, expected D3D_OK.\n", hr);
4719
4720     /* There's no dwSize in D3DDEVICEDESC7 */
4721 }
4722
4723 struct d3d2_test_context
4724 {
4725     IDirectDraw *ddraw;
4726     IDirect3D2 *d3d;
4727     IDirectDrawSurface *surface;
4728     IDirect3DDevice2 *device;
4729     IDirect3DViewport2 *viewport;
4730 };
4731
4732 static void d3d2_release_objects(struct d3d2_test_context *context)
4733 {
4734     LONG ref;
4735     HRESULT hr;
4736
4737     if (context->viewport)
4738     {
4739         hr = IDirect3DDevice2_DeleteViewport(context->device, context->viewport);
4740         ok(hr == D3D_OK, "DeleteViewport returned %08x.\n", hr);
4741         ref = IDirect3DViewport2_Release(context->viewport);
4742         ok(ref == 0, "Viewport has reference count %d, expected 0.\n", ref);
4743     }
4744     if (context->device)
4745     {
4746         ref = IDirect3DDevice2_Release(context->device);
4747         ok(ref == 0, "Device has reference count %d, expected 0.\n", ref);
4748     }
4749     if (context->surface)
4750     {
4751         ref = IDirectDrawSurface_Release(context->surface);
4752         ok(ref == 0, "Surface has reference count %d, expected 0.\n", ref);
4753     }
4754     if (context->d3d)
4755     {
4756         ref = IDirect3D2_Release(context->d3d);
4757         ok(ref == 1, "IDirect3D2 has reference count %d, expected 1.\n", ref);
4758     }
4759     if (context->ddraw)
4760     {
4761         ref = IDirectDraw_Release(context->ddraw);
4762         ok(ref == 0, "DDraw has reference count %d, expected 0.\n", ref);
4763     }
4764 }
4765
4766 static BOOL d3d2_create_objects(struct d3d2_test_context *context)
4767 {
4768     HRESULT hr;
4769     DDSURFACEDESC ddsd;
4770     D3DVIEWPORT vp_data;
4771
4772     memset(context, 0, sizeof(*context));
4773
4774     hr = DirectDrawCreate(NULL, &context->ddraw, NULL);
4775     ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate failed: %08x.\n", hr);
4776     if (!context->ddraw) goto error;
4777
4778     hr = IDirectDraw_SetCooperativeLevel(context->ddraw, NULL, DDSCL_NORMAL);
4779     ok(hr == DD_OK, "SetCooperativeLevel failed: %08x.\n", hr);
4780     if (FAILED(hr)) goto error;
4781
4782     hr = IDirectDraw_QueryInterface(context->ddraw, &IID_IDirect3D2, (void**) &context->d3d);
4783     ok(hr == DD_OK || hr == E_NOINTERFACE, "QueryInterface failed: %08x.\n", hr);
4784     if (!context->d3d) goto error;
4785
4786     memset(&ddsd, 0, sizeof(ddsd));
4787     ddsd.dwSize = sizeof(ddsd);
4788     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4789     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4790     ddsd.dwWidth = 256;
4791     ddsd.dwHeight = 256;
4792     IDirectDraw_CreateSurface(context->ddraw, &ddsd, &context->surface, NULL);
4793     if (!context->surface)
4794     {
4795         skip("DDSCAPS_3DDEVICE surface not available.\n");
4796         goto error;
4797     }
4798
4799     hr = IDirect3D2_CreateDevice(context->d3d, &IID_IDirect3DHALDevice, context->surface, &context->device);
4800     ok(hr == D3D_OK  || hr == E_OUTOFMEMORY || hr == E_NOINTERFACE, "CreateDevice failed: %08x.\n", hr);
4801     if (!context->device) goto error;
4802
4803     hr = IDirect3D2_CreateViewport(context->d3d, &context->viewport, NULL);
4804     ok(hr == D3D_OK, "CreateViewport failed: %08x.\n", hr);
4805     if (!context->viewport) goto error;
4806
4807     hr = IDirect3DDevice2_AddViewport(context->device, context->viewport);
4808     ok(hr == D3D_OK, "AddViewport returned %08x.\n", hr);
4809     vp_data.dwSize = sizeof(vp_data);
4810     vp_data.dwX = 0;
4811     vp_data.dwY = 0;
4812     vp_data.dwWidth = 256;
4813     vp_data.dwHeight = 256;
4814     vp_data.dvScaleX = 1;
4815     vp_data.dvScaleY = 1;
4816     vp_data.dvMaxX = 256;
4817     vp_data.dvMaxY = 256;
4818     vp_data.dvMinZ = 0;
4819     vp_data.dvMaxZ = 1;
4820     hr = IDirect3DViewport2_SetViewport(context->viewport, &vp_data);
4821     ok(hr == D3D_OK, "SetViewport returned %08x.\n", hr);
4822
4823     return TRUE;
4824
4825 error:
4826     d3d2_release_objects(context);
4827     return FALSE;
4828 }
4829
4830 static void test_get_caps2(const struct d3d2_test_context *context)
4831 {
4832     D3DDEVICEDESC hw_caps, hel_caps;
4833     HRESULT hr;
4834     unsigned int i;
4835
4836     memset(&hw_caps, 0, sizeof(hw_caps));
4837     hw_caps.dwSize = sizeof(hw_caps);
4838     hw_caps.dwFlags = 0xdeadbeef;
4839     memset(&hel_caps, 0, sizeof(hel_caps));
4840     hel_caps.dwSize = sizeof(hel_caps);
4841     hel_caps.dwFlags = 0xdeadc0de;
4842
4843     /* NULL pointers */
4844     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, NULL);
4845     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hel caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4846     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4847     hr = IDirect3DDevice2_GetCaps(context->device, NULL, &hel_caps);
4848     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hw caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
4849     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4850
4851     /* Successful call: Both are modified */
4852     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4853     ok(hr == D3D_OK, "GetCaps with correct size returned hr %#x, expected D3D_OK.\n", hr);
4854     ok(hw_caps.dwFlags != 0xdeadbeef, "hw_caps.dwFlags was not modified: %#x.\n", hw_caps.dwFlags);
4855     ok(hel_caps.dwFlags != 0xdeadc0de, "hel_caps.dwFlags was not modified: %#x.\n", hel_caps.dwFlags);
4856
4857     memset(&hw_caps, 0, sizeof(hw_caps));
4858     hw_caps.dwSize = sizeof(hw_caps);
4859     hw_caps.dwFlags = 0xdeadbeef;
4860     memset(&hel_caps, 0, sizeof(hel_caps));
4861     /* Keep dwSize at 0 */
4862     hel_caps.dwFlags = 0xdeadc0de;
4863
4864     /* If one is invalid the call fails */
4865     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4866     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hel_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4867     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4868     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4869     hel_caps.dwSize = sizeof(hel_caps);
4870     hw_caps.dwSize = sizeof(hw_caps) + 1;
4871     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4872     ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hw_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
4873     ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
4874     ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
4875
4876     for (i = 0; i < 1024; i++)
4877     {
4878         memset(&hw_caps, 0xfe, sizeof(hw_caps));
4879         memset(&hel_caps, 0xfe, sizeof(hel_caps));
4880         hw_caps.dwSize = hel_caps.dwSize = i;
4881         hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4882         switch (i)
4883         {
4884             /* D3DDEVICEDESCSIZE in old sdk versions */
4885             case FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth): /* 172, DirectX 3, IDirect3DDevice1 */
4886                 ok(hw_caps.dwMinTextureWidth == 0xfefefefe, "dwMinTextureWidth was modified: %#x.\n",
4887                         hw_caps.dwMinTextureWidth);
4888                 ok(hel_caps.dwMinTextureWidth == 0xfefefefe, "dwMinTextureWidth was modified: %#x.\n",
4889                         hel_caps.dwMinTextureWidth);
4890                 /* drop through */
4891             case FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat): /* 204, DirectX 5, IDirect3DDevice2 */
4892                 ok(hw_caps.dwMaxTextureRepeat == 0xfefefefe, "dwMaxTextureRepeat was modified: %#x.\n",
4893                         hw_caps.dwMaxTextureRepeat);
4894                 ok(hel_caps.dwMaxTextureRepeat == 0xfefefefe, "dwMaxTextureRepeat was modified: %#x.\n",
4895                         hel_caps.dwMaxTextureRepeat);
4896                 /* drop through */
4897             case sizeof(D3DDEVICEDESC): /* 252, DirectX 6, IDirect3DDevice3 */
4898                 ok(hr == D3D_OK, "GetCaps with size %u returned hr %#x, expected D3D_OK.\n", i, hr);
4899                 break;
4900
4901             default:
4902                 ok(hr == DDERR_INVALIDPARAMS,
4903                         "GetCaps with size %u returned hr %#x, expected DDERR_INVALIDPARAMS.\n", i, hr);
4904                 break;
4905         }
4906     }
4907
4908     /* Different valid sizes are OK */
4909     hw_caps.dwSize = 172;
4910     hel_caps.dwSize = sizeof(D3DDEVICEDESC);
4911     hr = IDirect3DDevice2_GetCaps(context->device, &hw_caps, &hel_caps);
4912     ok(hr == D3D_OK, "GetCaps with different sizes returned hr %#x, expected D3D_OK.\n", hr);
4913 }
4914
4915 START_TEST(d3d)
4916 {
4917     struct d3d2_test_context d3d2_context;
4918     void (* const d3d2_tests[])(const struct d3d2_test_context *) =
4919     {
4920         test_get_caps2
4921     };
4922     unsigned int i;
4923
4924     init_function_pointers();
4925     if(!pDirectDrawCreateEx) {
4926         win_skip("function DirectDrawCreateEx not available\n");
4927         return;
4928     }
4929
4930     if(!CreateDirect3D()) {
4931         skip("Skipping d3d7 tests\n");
4932     } else {
4933         LightTest();
4934         StateTest();
4935         SceneTest();
4936         LimitTest();
4937         D3D7EnumTest();
4938         D3D7EnumLifetimeTest();
4939         SetMaterialTest();
4940         ComputeSphereVisibility();
4941         CapsTest();
4942         VertexBufferDescTest();
4943         D3D7_OldRenderStateTest();
4944         DeviceLoadTest();
4945         SetRenderTargetTest();
4946         VertexBufferLockRest();
4947         z_format_test();
4948         test_get_caps7();
4949         ReleaseDirect3D();
4950     }
4951
4952     for (i = 0; i < (sizeof(d3d2_tests) / sizeof(*d3d2_tests)); i++)
4953     {
4954         if (!d3d2_create_objects(&d3d2_context))
4955         {
4956             ok(!i, "Unexpected d3d2 initialization failure.\n");
4957             skip("Skipping d3d2 tests.\n");
4958             break;
4959         }
4960         d3d2_tests[i](&d3d2_context);
4961         d3d2_release_objects(&d3d2_context);
4962     }
4963
4964     if (!D3D1_createObjects()) {
4965         skip("Skipping d3d1 tests\n");
4966     } else {
4967         Direct3D1Test();
4968         TextureLoadTest();
4969         ViewportTest();
4970         FindDevice();
4971         BackBuffer3DCreateSurfaceTest();
4972         BackBuffer3DAttachmentTest();
4973         test_get_caps1();
4974         D3D1_releaseObjects();
4975     }
4976
4977     test_wndproc();
4978     test_window_style();
4979     test_redundant_mode_set();
4980     test_coop_level_mode_set();
4981     test_initialize();
4982     test_coop_level_surf_create();
4983 }