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