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