tests: Remove unneeded assert.h includes.
[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     else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
809     {
810         trace("HAL Device %d\n", ver);
811     }
812     else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
813     {
814         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
815            "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
816         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
817            "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
818         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
819            "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
820         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
821            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
822
823         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
824            "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
825         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
826            "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
827         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
828            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
829         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
830            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
831     }
832     else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
833     {
834         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
835            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
836         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
837            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
838         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
839            "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
840         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
841            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
842
843         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
844            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
845         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
846            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
847         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
848            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
849         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
850            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
851     }
852     else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
853     {
854         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
855            "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
856         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
857            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
858         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
859            "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
860         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
861            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
862
863         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
864            "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
865         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
866            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
867         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
868            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
869         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
870            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
871     }
872     else
873     {
874         ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
875         if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
876         else trace("hal line does NOT have pow2 set\n");
877         if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
878         else trace("hal tri does NOT have pow2 set\n");
879         if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
880         else trace("hel line does NOT have pow2 set\n");
881         if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
882         else trace("hel tri does NOT have pow2 set\n");
883     }
884     return DDENUMRET_OK;
885 }
886
887 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
888 {
889     D3D7ETest *d3d7et = Context;
890     if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
891         d3d7et->rgb++;
892     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
893         d3d7et->hal++;
894     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
895         d3d7et->tnlhal++;
896     else
897         d3d7et->unk++;
898
899     d3d7et->total++;
900
901     return DDENUMRET_OK;
902 }
903
904 static HRESULT WINAPI enumDevicesCancelTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
905 {
906     D3D7ECancelTest *d3d7et = Context;
907
908     d3d7et->total++;
909
910     return d3d7et->desired_ret;
911 }
912
913 static HRESULT WINAPI enumDevicesLifetimeTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
914 {
915     D3D7ELifetimeTest *ctx = Context;
916
917     if (ctx->count == MAX_ENUMERATION_COUNT)
918     {
919         ok(0, "Enumerated too many devices for context in callback\n");
920         return DDENUMRET_CANCEL;
921     }
922
923     ctx->callback_description_ptrs[ctx->count] = DeviceDescription;
924     strcpy(ctx->callback_description_strings[ctx->count], DeviceDescription);
925     ctx->callback_name_ptrs[ctx->count] = DeviceName;
926     strcpy(ctx->callback_name_strings[ctx->count], DeviceName);
927
928     ctx->count++;
929     return DDENUMRET_OK;
930 }
931
932 /*  Check the deviceGUID of devices enumerated by
933     IDirect3D7_EnumDevices. */
934 static void D3D7EnumTest(void)
935 {
936     HRESULT hr;
937     D3D7ETest d3d7et;
938     D3D7ECancelTest d3d7_cancel_test;
939
940     hr = IDirect3D7_EnumDevices(lpD3D, NULL, NULL);
941     ok(hr == DDERR_INVALIDPARAMS, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
942
943     memset(&d3d7et, 0, sizeof(d3d7et));
944     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et);
945     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
946
947     /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
948     ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
949
950     /* We make two additional assumptions. */
951     ok(d3d7et.rgb, "No RGB Device enumerated.\n");
952
953     if(d3d7et.tnlhal)
954         ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
955
956     d3d7_cancel_test.desired_ret = DDENUMRET_CANCEL;
957     d3d7_cancel_test.total = 0;
958     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesCancelTest7, &d3d7_cancel_test);
959     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
960
961     ok(d3d7_cancel_test.total == 1, "Enumerated a total of %u devices\n",
962        d3d7_cancel_test.total);
963
964     /* An enumeration callback can return any value besides DDENUMRET_OK to stop enumeration. */
965     d3d7_cancel_test.desired_ret = E_INVALIDARG;
966     d3d7_cancel_test.total = 0;
967     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesCancelTest7, &d3d7_cancel_test);
968     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
969
970     ok(d3d7_cancel_test.total == 1, "Enumerated a total of %u devices\n",
971        d3d7_cancel_test.total);
972 }
973
974 static void D3D7EnumLifetimeTest(void)
975 {
976     D3D7ELifetimeTest ctx, ctx2;
977     HRESULT hr;
978     unsigned int i;
979
980     ctx.count = 0;
981     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesLifetimeTest7, &ctx);
982     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
983
984     /* The enumeration strings remain valid even after IDirect3D7_EnumDevices finishes. */
985     for (i = 0; i < ctx.count; i++)
986     {
987         ok(!strcmp(ctx.callback_description_ptrs[i], ctx.callback_description_strings[i]),
988            "Got '%s' and '%s'\n", ctx.callback_description_ptrs[i], ctx.callback_description_strings[i]);
989         ok(!strcmp(ctx.callback_name_ptrs[i], ctx.callback_name_strings[i]),
990            "Got '%s' and '%s'\n", ctx.callback_name_ptrs[i], ctx.callback_name_strings[i]);
991     }
992
993     ctx2.count = 0;
994     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesLifetimeTest7, &ctx2);
995     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
996
997     /* The enumeration strings and their order are identical across enumerations. */
998     ok(ctx.count == ctx2.count, "Enumerated %u and %u devices\n", ctx.count, ctx2.count);
999     if (ctx.count == ctx2.count)
1000     {
1001         for (i = 0; i < ctx.count; i++)
1002         {
1003             ok(ctx.callback_description_ptrs[i] == ctx2.callback_description_ptrs[i],
1004                "Unequal description pointers %p and %p\n", ctx.callback_description_ptrs[i], ctx2.callback_description_ptrs[i]);
1005             ok(!strcmp(ctx.callback_description_strings[i], ctx2.callback_description_strings[i]),
1006                "Got '%s' and '%s'\n", ctx.callback_description_strings[i], ctx2.callback_description_strings[i]);
1007             ok(ctx.callback_name_ptrs[i] == ctx2.callback_name_ptrs[i],
1008                "Unequal name pointers %p and %p\n", ctx.callback_name_ptrs[i], ctx2.callback_name_ptrs[i]);
1009             ok(!strcmp(ctx.callback_name_strings[i], ctx2.callback_name_strings[i]),
1010                "Got '%s' and '%s'\n", ctx.callback_name_strings[i], ctx2.callback_name_strings[i]);
1011         }
1012     }
1013
1014     /* Try altering the contents of the enumeration strings. */
1015     for (i = 0; i < ctx2.count; i++)
1016     {
1017         strcpy(ctx2.callback_description_ptrs[i], "Fake Description");
1018         strcpy(ctx2.callback_name_ptrs[i], "Fake Device");
1019     }
1020
1021     ctx2.count = 0;
1022     hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesLifetimeTest7, &ctx2);
1023     ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr);
1024
1025     /* The original contents of the enumeration strings are not restored. */
1026     ok(ctx.count == ctx2.count, "Enumerated %u and %u devices\n", ctx.count, ctx2.count);
1027     if (ctx.count == ctx2.count)
1028     {
1029         for (i = 0; i < ctx.count; i++)
1030         {
1031             ok(ctx.callback_description_ptrs[i] == ctx2.callback_description_ptrs[i],
1032                "Unequal description pointers %p and %p\n", ctx.callback_description_ptrs[i], ctx2.callback_description_ptrs[i]);
1033             ok(strcmp(ctx.callback_description_strings[i], ctx2.callback_description_strings[i]) != 0,
1034                "Got '%s' and '%s'\n", ctx.callback_description_strings[i], ctx2.callback_description_strings[i]);
1035             ok(ctx.callback_name_ptrs[i] == ctx2.callback_name_ptrs[i],
1036                "Unequal name pointers %p and %p\n", ctx.callback_name_ptrs[i], ctx2.callback_name_ptrs[i]);
1037             ok(strcmp(ctx.callback_name_strings[i], ctx2.callback_name_strings[i]) != 0,
1038                "Got '%s' and '%s'\n", ctx.callback_name_strings[i], ctx2.callback_name_strings[i]);
1039         }
1040     }
1041 }
1042
1043 static void CapsTest(void)
1044 {
1045     IDirect3D3 *d3d3;
1046     IDirect3D3 *d3d2;
1047     IDirectDraw *dd1;
1048     HRESULT hr;
1049     UINT ver;
1050
1051     hr = DirectDrawCreate(NULL, &dd1, NULL);
1052     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
1053     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
1054     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
1055
1056     hr = IDirect3D3_EnumDevices(d3d3, NULL, NULL);
1057     ok(hr == DDERR_INVALIDPARAMS, "IDirect3D3_EnumDevices returned 0x%08x\n", hr);
1058
1059     ver = 3;
1060     IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
1061
1062     IDirect3D3_Release(d3d3);
1063     IDirectDraw_Release(dd1);
1064
1065     hr = DirectDrawCreate(NULL, &dd1, NULL);
1066     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
1067     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
1068     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
1069
1070     hr = IDirect3D2_EnumDevices(d3d2, NULL, NULL);
1071     ok(hr == DDERR_INVALIDPARAMS, "IDirect3D2_EnumDevices returned 0x%08x\n", hr);
1072
1073     ver = 2;
1074     IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
1075
1076     IDirect3D2_Release(d3d2);
1077     IDirectDraw_Release(dd1);
1078 }
1079
1080 struct v_in {
1081     float x, y, z;
1082 };
1083 struct v_out {
1084     float x, y, z, rhw;
1085 };
1086
1087 static BOOL D3D1_createObjects(void)
1088 {
1089     HRESULT hr;
1090     DDSURFACEDESC ddsd;
1091     D3DEXECUTEBUFFERDESC desc;
1092     D3DVIEWPORT vp_data;
1093
1094     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
1095     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
1096     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
1097     if (!DirectDraw1) {
1098         return FALSE;
1099     }
1100
1101     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
1102     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
1103
1104     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
1105     if (hr == E_NOINTERFACE) return FALSE;
1106     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
1107     if (!Direct3D1) {
1108         return FALSE;
1109     }
1110
1111     memset(&ddsd, 0, sizeof(ddsd));
1112     ddsd.dwSize = sizeof(ddsd);
1113     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1114     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1115     ddsd.dwWidth = 256;
1116     ddsd.dwHeight = 256;
1117     IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
1118     if (!Surface1) {
1119         skip("DDSCAPS_3DDEVICE surface not available\n");
1120         return FALSE;
1121     }
1122
1123     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
1124     ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
1125     if(!Direct3DDevice1) {
1126         return FALSE;
1127     }
1128
1129     memset(&desc, 0, sizeof(desc));
1130     desc.dwSize = sizeof(desc);
1131     desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1132     desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
1133     desc.dwBufferSize = 128;
1134     desc.lpData = NULL;
1135     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
1136     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
1137     if(!ExecuteBuffer) {
1138         return FALSE;
1139     }
1140
1141     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
1142     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
1143     if(!Viewport) {
1144         return FALSE;
1145     }
1146
1147     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
1148     ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
1149
1150     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
1151     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1152     vp_data.dwSize = sizeof(vp_data);
1153     vp_data.dwX = 0;
1154     vp_data.dwY = 0;
1155     vp_data.dwWidth = 256;
1156     vp_data.dwHeight = 256;
1157     vp_data.dvScaleX = 1;
1158     vp_data.dvScaleY = 1;
1159     vp_data.dvMaxX = 256;
1160     vp_data.dvMaxY = 256;
1161     vp_data.dvMinZ = 0;
1162     vp_data.dvMaxZ = 1;
1163     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1164     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1165
1166     hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1167     ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1168     if (!Light)
1169         return FALSE;
1170
1171     return TRUE;
1172 }
1173
1174 static void D3D1_releaseObjects(void)
1175 {
1176     if (Light) IDirect3DLight_Release(Light);
1177     if (Viewport) IDirect3DViewport_Release(Viewport);
1178     if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1179     if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1180     if (Surface1) IDirectDrawSurface_Release(Surface1);
1181     if (Direct3D1) IDirect3D_Release(Direct3D1);
1182     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1183 }
1184
1185 static void ViewportTest(void)
1186 {
1187     HRESULT hr;
1188     LPDIRECT3DVIEWPORT2 Viewport2;
1189     D3DVIEWPORT vp1_data, ret_vp1_data;
1190     D3DVIEWPORT2 vp2_data, ret_vp2_data;
1191     float infinity;
1192
1193     *(DWORD*)&infinity = 0x7f800000;
1194
1195     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
1196     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1197
1198     hr = IDirect3DViewport_QueryInterface(Viewport, &IID_IDirect3DViewport2, (void**) &Viewport2);
1199     ok(hr==D3D_OK, "QueryInterface returned: %x\n", hr);
1200
1201     vp1_data.dwSize = sizeof(vp1_data);
1202     vp1_data.dwX = 0;
1203     vp1_data.dwY = 1;
1204     vp1_data.dwWidth = 256;
1205     vp1_data.dwHeight = 257;
1206     vp1_data.dvMaxX = 0;
1207     vp1_data.dvMaxY = 0;
1208     vp1_data.dvScaleX = 0;
1209     vp1_data.dvScaleY = 0;
1210     vp1_data.dvMinZ = 0.25;
1211     vp1_data.dvMaxZ = 0.75;
1212
1213     vp2_data.dwSize = sizeof(vp2_data);
1214     vp2_data.dwX = 2;
1215     vp2_data.dwY = 3;
1216     vp2_data.dwWidth = 258;
1217     vp2_data.dwHeight = 259;
1218     vp2_data.dvClipX = 0;
1219     vp2_data.dvClipY = 0;
1220     vp2_data.dvClipWidth = 0;
1221     vp2_data.dvClipHeight = 0;
1222     vp2_data.dvMinZ = 0.1;
1223     vp2_data.dvMaxZ = 0.9;
1224
1225     hr = IDirect3DViewport2_SetViewport(Viewport2, &vp1_data);
1226     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport returned %08x\n", hr);
1227
1228     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1229     ret_vp1_data.dwSize = sizeof(vp1_data);
1230
1231     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1232     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1233
1234     ok(ret_vp1_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp1_data.dwX);
1235     ok(ret_vp1_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp1_data.dwY);
1236     ok(ret_vp1_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp1_data.dwWidth);
1237     ok(ret_vp1_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp1_data.dwHeight);
1238     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1239     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1240     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1241     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1242     ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1243     ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1244
1245     hr = IDirect3DViewport2_SetViewport2(Viewport2, &vp2_data);
1246     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport2 returned %08x\n", hr);
1247
1248     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1249     ret_vp2_data.dwSize = sizeof(vp2_data);
1250
1251     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1252     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1253
1254     ok(ret_vp2_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp2_data.dwX);
1255     ok(ret_vp2_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp2_data.dwY);
1256     ok(ret_vp2_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp2_data.dwWidth);
1257     ok(ret_vp2_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp2_data.dwHeight);
1258     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1259     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1260     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1261         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1262     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1263         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1264     ok(ret_vp2_data.dvMinZ == vp2_data.dvMinZ, "dvMinZ is %f, expected %f\n", ret_vp2_data.dvMinZ, vp2_data.dvMinZ);
1265     ok(ret_vp2_data.dvMaxZ == vp2_data.dvMaxZ, "dvMaxZ is %f, expected %f\n", ret_vp2_data.dvMaxZ, vp2_data.dvMaxZ);
1266
1267     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1268     ret_vp1_data.dwSize = sizeof(vp1_data);
1269
1270     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1271     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1272
1273     ok(ret_vp1_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp2_data.dwX);
1274     ok(ret_vp1_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp2_data.dwY);
1275     ok(ret_vp1_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp2_data.dwWidth);
1276     ok(ret_vp1_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp2_data.dwHeight);
1277     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1278     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1279     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1280     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1281     todo_wine ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1282     todo_wine ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1283
1284     hr = IDirect3DViewport2_SetViewport2(Viewport2, &vp2_data);
1285     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport2 returned %08x\n", hr);
1286
1287     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1288     ret_vp2_data.dwSize = sizeof(vp2_data);
1289
1290     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1291     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1292
1293     ok(ret_vp2_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp2_data.dwX);
1294     ok(ret_vp2_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp2_data.dwY);
1295     ok(ret_vp2_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp2_data.dwWidth);
1296     ok(ret_vp2_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp2_data.dwHeight);
1297     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1298     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1299     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1300         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1301     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1302         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1303     ok(ret_vp2_data.dvMinZ == vp2_data.dvMinZ, "dvMinZ is %f, expected %f\n", ret_vp2_data.dvMinZ, vp2_data.dvMinZ);
1304     ok(ret_vp2_data.dvMaxZ == vp2_data.dvMaxZ, "dvMaxZ is %f, expected %f\n", ret_vp2_data.dvMaxZ, vp2_data.dvMaxZ);
1305
1306     hr = IDirect3DViewport2_SetViewport(Viewport2, &vp1_data);
1307     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport returned %08x\n", hr);
1308
1309     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1310     ret_vp1_data.dwSize = sizeof(vp1_data);
1311
1312     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1313     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1314
1315     ok(ret_vp1_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp1_data.dwX);
1316     ok(ret_vp1_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp1_data.dwY);
1317     ok(ret_vp1_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp1_data.dwWidth);
1318     ok(ret_vp1_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp1_data.dwHeight);
1319     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1320     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1321     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1322     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1323     ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1324     ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1325
1326     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1327     ret_vp2_data.dwSize = sizeof(vp2_data);
1328
1329     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1330     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1331
1332     ok(ret_vp2_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp1_data.dwX);
1333     ok(ret_vp2_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp1_data.dwY);
1334     ok(ret_vp2_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp1_data.dwWidth);
1335     ok(ret_vp2_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp1_data.dwHeight);
1336     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1337     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1338     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1339         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1340     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1341         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1342     ok(ret_vp2_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp2_data.dvMinZ);
1343     ok(ret_vp2_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp2_data.dvMaxZ);
1344
1345     IDirect3DViewport2_Release(Viewport2);
1346
1347     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1348     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1349 }
1350
1351 #define SET_VP_DATA(vp_data) \
1352     vp_data.dwSize = sizeof(vp_data); \
1353     vp_data.dwX = 0; \
1354     vp_data.dwY = 0; \
1355     vp_data.dwWidth = 256; \
1356     vp_data.dwHeight = 256; \
1357     vp_data.dvMaxX = 256; \
1358     vp_data.dvMaxY = 256; \
1359     vp_data.dvScaleX = 5; \
1360     vp_data.dvScaleY = 5; \
1361     vp_data.dvMinZ = -25; \
1362     vp_data.dvMaxZ = 60;
1363
1364 static void Direct3D1Test(void)
1365 {
1366     HRESULT hr;
1367     D3DEXECUTEBUFFERDESC desc;
1368     D3DVIEWPORT vp_data;
1369     D3DINSTRUCTION *instr;
1370     D3DBRANCH *branch;
1371     IDirect3D *Direct3D_alt;
1372     IDirect3DLight *d3dlight;
1373     ULONG refcount;
1374     unsigned int idx = 0;
1375     static struct v_in testverts[] = {
1376         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
1377         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1378     };
1379     static struct v_in cliptest[] = {
1380         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
1381         {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1382     };
1383     static struct v_in offscreentest[] = {
1384         {128.1, 0.0, 0.0},
1385     };
1386     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1387     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1388     D3DTRANSFORMDATA transformdata;
1389     DWORD i = FALSE;
1390
1391     /* Interface consistency check. */
1392     hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1393     ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1394     ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1395     IDirect3D_Release(Direct3D_alt);
1396
1397     memset(&desc, 0, sizeof(desc));
1398     desc.dwSize = sizeof(desc);
1399     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1400     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1401
1402     memset(desc.lpData, 0, 128);
1403     instr = desc.lpData;
1404     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1405     instr[idx].bSize = sizeof(*branch);
1406     instr[idx].wCount = 1;
1407     idx++;
1408     branch = (D3DBRANCH *) &instr[idx];
1409     branch->dwMask = 0x0;
1410     branch->dwValue = 1;
1411     branch->bNegate = TRUE;
1412     branch->dwOffset = 0;
1413     idx += (sizeof(*branch) / sizeof(*instr));
1414     instr[idx].bOpcode = D3DOP_EXIT;
1415     instr[idx].bSize = 0;
1416     instr[idx].wCount = 0;
1417     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1418     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1419
1420     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1421     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1422
1423     memset(&desc, 0, sizeof(desc));
1424     desc.dwSize = sizeof(desc);
1425
1426     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1427     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1428
1429     memset(desc.lpData, 0, 128);
1430     instr = desc.lpData;
1431     idx = 0;
1432     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1433     instr[idx].bSize = sizeof(*branch);
1434     instr[idx].wCount = 1;
1435     idx++;
1436     branch = (D3DBRANCH *) &instr[idx];
1437     branch->dwMask = 0x0;
1438     branch->dwValue = 1;
1439     branch->bNegate = TRUE;
1440     branch->dwOffset = 64;
1441     instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1442     instr[0].bOpcode = D3DOP_EXIT;
1443     instr[0].bSize = 0;
1444     instr[0].wCount = 0;
1445     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1446     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1447
1448     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1449     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1450
1451     /* Test rendering 0 triangles */
1452     memset(&desc, 0, sizeof(desc));
1453     desc.dwSize = sizeof(desc);
1454
1455     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1456     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1457
1458     memset(desc.lpData, 0, 128);
1459     instr = desc.lpData;
1460
1461     instr->bOpcode = D3DOP_TRIANGLE;
1462     instr->bSize = sizeof(D3DOP_TRIANGLE);
1463     instr->wCount = 0;
1464     instr++;
1465     instr->bOpcode = D3DOP_EXIT;
1466     instr->bSize = 0;
1467     instr->wCount = 0;
1468     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1469     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1470
1471     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1472     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1473
1474     memset(&transformdata, 0, sizeof(transformdata));
1475     transformdata.dwSize = sizeof(transformdata);
1476     transformdata.lpIn = testverts;
1477     transformdata.dwInSize = sizeof(testverts[0]);
1478     transformdata.lpOut = out;
1479     transformdata.dwOutSize = sizeof(out[0]);
1480
1481     transformdata.lpHOut = NULL;
1482     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1483                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1484                                              &i);
1485     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1486
1487     transformdata.lpHOut = outH;
1488     memset(outH, 0xcc, sizeof(outH));
1489     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1490                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1491                                              &i);
1492     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1493     ok(i == 0, "Offscreen is %d\n", i);
1494
1495     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1496         static const struct v_out cmp[] = {
1497             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1498             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1499         };
1500
1501         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1502            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1503            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1504            out[i].x, out[i].y, out[i].z, out[i].rhw,
1505            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1506     }
1507     for(i = 0; i < sizeof(outH); i++) {
1508         if(((unsigned char *) outH)[i] != 0xcc) {
1509             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1510             break;
1511         }
1512     }
1513
1514     SET_VP_DATA(vp_data);
1515     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1516     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1517     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1518                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1519                                              &i);
1520     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1521     ok(i == 0, "Offscreen is %d\n", i);
1522
1523     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1524         static const struct v_out cmp[] = {
1525             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1526             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1527         };
1528         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1529            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1530            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1531            out[i].x, out[i].y, out[i].z, out[i].rhw,
1532            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1533     }
1534
1535     SET_VP_DATA(vp_data);
1536     vp_data.dwX = 10;
1537     vp_data.dwY = 20;
1538     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1539     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1540     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1541                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1542                                              &i);
1543     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1544     ok(i == 0, "Offscreen is %d\n", i);
1545     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1546         static const struct v_out cmp[] = {
1547             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1548             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1549         };
1550         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1551            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1552            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1553            out[i].x, out[i].y, out[i].z, out[i].rhw,
1554            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1555     }
1556
1557     memset(out, 0xcc, sizeof(out));
1558     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1559                                              &transformdata, D3DTRANSFORM_CLIPPED,
1560                                              &i);
1561     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1562     ok(i == 0, "Offscreen is %d\n", i);
1563     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1564         static const D3DHVERTEX cmpH[] = {
1565             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1566             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1567             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1568         };
1569         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1570            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1571            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1572            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1573            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1574
1575         /* No scheme has been found behind those return values. It seems to be
1576          * whatever data windows has when throwing the vertex away. Modify the
1577          * input test vertices to test this more. Depending on the input data
1578          * it can happen that the z coord gets written into y, or similar things
1579          */
1580         if(0)
1581         {
1582             static const struct v_out cmp[] = {
1583                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1584                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1585             };
1586             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1587                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1588                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1589                out[i].x, out[i].y, out[i].z, out[i].rhw,
1590                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1591         }
1592     }
1593     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1594         ok(((DWORD *) out)[i] != 0xcccccccc,
1595                 "Regular output DWORD %d remained untouched\n", i);
1596     }
1597
1598     transformdata.lpIn = cliptest;
1599     transformdata.dwInSize = sizeof(cliptest[0]);
1600     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1601                                              &transformdata, D3DTRANSFORM_CLIPPED,
1602                                              &i);
1603     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1604     ok(i == 0, "Offscreen is %d\n", i);
1605     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1606         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1607         {
1608             0,
1609             0,
1610             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1611             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1612         };
1613         ok(Flags[i] == outH[i].dwFlags,
1614            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1615            outH[i].dwFlags, Flags[i]);
1616     }
1617
1618     SET_VP_DATA(vp_data);
1619     vp_data.dwWidth = 10;
1620     vp_data.dwHeight = 1000;
1621     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1622     i = 10;
1623     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1624     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1625                                              &transformdata, D3DTRANSFORM_CLIPPED,
1626                                              &i);
1627     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1628     ok(i == 0, "Offscreen is %d\n", i);
1629     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1630         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1631         {
1632             D3DCLIP_RIGHT,
1633             D3DCLIP_LEFT,
1634             D3DCLIP_RIGHT | D3DCLIP_BACK,
1635             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1636         };
1637         ok(Flags[i] == outH[i].dwFlags,
1638            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1639            outH[i].dwFlags, Flags[i]);
1640     }
1641
1642     SET_VP_DATA(vp_data);
1643     vp_data.dwWidth = 256;
1644     vp_data.dwHeight = 256;
1645     vp_data.dvScaleX = 1;
1646     vp_data.dvScaleY = 1;
1647     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1648     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1649     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1650                                              &transformdata, D3DTRANSFORM_CLIPPED,
1651                                              &i);
1652     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1653     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1654     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1655         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1656         {
1657             0,
1658             0,
1659             D3DCLIP_BACK,
1660             D3DCLIP_FRONT,
1661         };
1662         ok(Flags[i] == outH[i].dwFlags,
1663            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1664            outH[i].dwFlags, Flags[i]);
1665     }
1666
1667     /* Finally try to figure out how the DWORD dwOffscreen works.
1668      * Apparently no vertex is offscreen with clipping off,
1669      * and with clipping on the offscreen flag is set if only one vertex
1670      * is transformed, and this vertex is offscreen.
1671      */
1672     SET_VP_DATA(vp_data);
1673     vp_data.dwWidth = 5;
1674     vp_data.dwHeight = 5;
1675     vp_data.dvScaleX = 10000;
1676     vp_data.dvScaleY = 10000;
1677     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1678     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1679     transformdata.lpIn = cliptest;
1680     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1681                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1682                                              &i);
1683     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1684     ok(i == 0, "Offscreen is %d\n", i);
1685     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1686                                              &transformdata, D3DTRANSFORM_CLIPPED,
1687                                              &i);
1688     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1689     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1690     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1691                                              &transformdata, D3DTRANSFORM_CLIPPED,
1692                                              &i);
1693     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1694     ok(i == 0, "Offscreen is %d\n", i);
1695     transformdata.lpIn = cliptest + 1;
1696     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1697                                              &transformdata, D3DTRANSFORM_CLIPPED,
1698                                              &i);
1699     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1700     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1701
1702     transformdata.lpIn = offscreentest;
1703     transformdata.dwInSize = sizeof(offscreentest[0]);
1704     SET_VP_DATA(vp_data);
1705     vp_data.dwWidth = 257;
1706     vp_data.dwHeight = 257;
1707     vp_data.dvScaleX = 1;
1708     vp_data.dvScaleY = 1;
1709     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1710     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1711     i = 12345;
1712     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1713                                              &transformdata, D3DTRANSFORM_CLIPPED,
1714                                              &i);
1715     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1716     ok(i == 0, "Offscreen is %d\n", i);
1717     vp_data.dwWidth = 256;
1718     vp_data.dwHeight = 256;
1719     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1720     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1721     i = 12345;
1722     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1723                                              &transformdata, D3DTRANSFORM_CLIPPED,
1724                                              &i);
1725     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1726     ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1727
1728     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1729                                              &transformdata, 0,
1730                                              &i);
1731     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1732
1733     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1734     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1735
1736     hr = IDirect3DViewport_AddLight(Viewport, Light);
1737     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1738     refcount = getRefcount((IUnknown*) Light);
1739     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1740
1741     hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1742     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1743     ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1744     refcount = getRefcount((IUnknown*) Light);
1745     ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1746
1747     hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1748     ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1749     refcount = getRefcount((IUnknown*) Light);
1750     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1751
1752     IDirect3DLight_Release(Light);
1753 }
1754
1755 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1756 {
1757     int i;
1758
1759     for (i = 0; i < 256; i++) {
1760        if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1761            table1[i].peBlue != table2[i].peBlue) return FALSE;
1762     }
1763
1764     return TRUE;
1765 }
1766
1767 /* test palette handling in IDirect3DTexture_Load */
1768 static void TextureLoadTest(void)
1769 {
1770     IDirectDrawSurface *TexSurface = NULL;
1771     IDirect3DTexture *Texture = NULL;
1772     IDirectDrawSurface *TexSurface2 = NULL;
1773     IDirect3DTexture *Texture2 = NULL;
1774     IDirectDrawPalette *palette = NULL;
1775     IDirectDrawPalette *palette2 = NULL;
1776     IDirectDrawPalette *palette_tmp = NULL;
1777     PALETTEENTRY table1[256], table2[256], table_tmp[256];
1778     HRESULT hr;
1779     DDSURFACEDESC ddsd;
1780     int i;
1781
1782     memset (&ddsd, 0, sizeof (ddsd));
1783     ddsd.dwSize = sizeof (ddsd);
1784     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1785     ddsd.dwHeight = 128;
1786     ddsd.dwWidth = 128;
1787     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1788     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1789     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1790     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1791
1792     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1793     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1794     if (FAILED(hr)) {
1795         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1796         goto cleanup;
1797     }
1798
1799     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1800                 (void *)&Texture);
1801     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1802     if (FAILED(hr)) {
1803         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1804         goto cleanup;
1805     }
1806
1807     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1808     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1809     if (FAILED(hr)) {
1810         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1811         goto cleanup;
1812     }
1813
1814     hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1815                 (void *)&Texture2);
1816     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1817     if (FAILED(hr)) {
1818         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1819         goto cleanup;
1820     }
1821
1822     /* test load of Texture to Texture */
1823     hr = IDirect3DTexture_Load(Texture, Texture);
1824     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1825
1826     /* test Load when both textures have no palette */
1827     hr = IDirect3DTexture_Load(Texture2, Texture);
1828     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1829
1830     for (i = 0; i < 256; i++) {
1831         table1[i].peRed = i;
1832         table1[i].peGreen = i;
1833         table1[i].peBlue = i;
1834         table1[i].peFlags = 0;
1835     }
1836
1837     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1838     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1839     if (FAILED(hr)) {
1840         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1841         goto cleanup;
1842     }
1843
1844     /* test Load when source texture has palette and destination has no palette */
1845     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1846     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1847     hr = IDirect3DTexture_Load(Texture2, Texture);
1848     ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1849
1850     for (i = 0; i < 256; i++) {
1851         table2[i].peRed = 255 - i;
1852         table2[i].peGreen = 255 - i;
1853         table2[i].peBlue = 255 - i;
1854         table2[i].peFlags = 0;
1855     }
1856
1857     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1858     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1859     if (FAILED(hr)) {
1860         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1861         goto cleanup;
1862     }
1863
1864     /* test Load when source has no palette and destination has a palette */
1865     hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1866     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1867     hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1868     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1869     hr = IDirect3DTexture_Load(Texture2, Texture);
1870     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1871     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1872     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1873     if (!palette_tmp) {
1874         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1875         goto cleanup;
1876     } else {
1877         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1878         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1879         ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1880         IDirectDrawPalette_Release(palette_tmp);
1881     }
1882
1883     /* test Load when both textures have palettes */
1884     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1885     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1886     hr = IDirect3DTexture_Load(Texture2, Texture);
1887     ok(hr == DD_OK, "IDirect3DTexture_Load 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(table1, table_tmp), "Unexpected palettized texture color table\n");
1899         IDirectDrawPalette_Release(palette_tmp);
1900     }
1901
1902     cleanup:
1903
1904     if (palette) IDirectDrawPalette_Release(palette);
1905     if (palette2) IDirectDrawPalette_Release(palette2);
1906     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1907     if (Texture) IDirect3DTexture_Release(Texture);
1908     if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1909     if (Texture2) IDirect3DTexture_Release(Texture2);
1910 }
1911
1912 static void VertexBufferDescTest(void)
1913 {
1914     HRESULT rc;
1915     D3DVERTEXBUFFERDESC desc;
1916     union mem_t
1917     {
1918         D3DVERTEXBUFFERDESC desc2;
1919         unsigned char buffer[512];
1920     } mem;
1921
1922     memset(&desc, 0, sizeof(desc));
1923     desc.dwSize = sizeof(desc);
1924     desc.dwCaps = 0;
1925     desc.dwFVF = D3DFVF_XYZ;
1926     desc.dwNumVertices = 1;
1927     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1928     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1929     if (!lpVBufSrc)
1930     {
1931         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1932         goto out;
1933     }
1934
1935     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1936     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1937     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1938     if(rc != D3D_OK)
1939         skip("GetVertexBuffer Failed!\n");
1940     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1941     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1942     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1943     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1944     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1945
1946     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1947     mem.desc2.dwSize = 0;
1948     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1949     if(rc != D3D_OK)
1950         skip("GetVertexBuffer Failed!\n");
1951     ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1952     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1953     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1954     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1955     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1956
1957     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1958     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1959     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1960     if(rc != D3D_OK)
1961         skip("GetVertexBuffer Failed!\n");
1962     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1963     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1964     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1965     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1966     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1967
1968 out:
1969     IDirect3DVertexBuffer7_Release(lpVBufSrc);
1970 }
1971
1972 static void D3D7_OldRenderStateTest(void)
1973 {
1974     HRESULT hr;
1975     DWORD val;
1976
1977     /* Test reaction to some deprecated states in D3D7. */
1978     hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1979     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1980     hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1981     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1982     hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1983     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1984     hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1985     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1986 }
1987
1988 #define IS_VALUE_NEAR(a, b)    ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1989 #define MIN(a, b)    ((a) < (b) ? (a) : (b))
1990
1991 static void DeviceLoadTest(void)
1992 {
1993     DDSURFACEDESC2 ddsd;
1994     IDirectDrawSurface7 *texture_levels[2][8];
1995     IDirectDrawSurface7 *cube_face_levels[2][6][8];
1996     DWORD flags;
1997     HRESULT hr;
1998     DDBLTFX ddbltfx;
1999     RECT loadrect;
2000     POINT loadpoint;
2001     int i, i1, i2;
2002     unsigned diff_count = 0, diff_count2 = 0;
2003     unsigned x, y;
2004     BOOL load_mip_subset_broken = FALSE;
2005     IDirectDrawPalette *palettes[5];
2006     PALETTEENTRY table1[256];
2007     DDCOLORKEY ddckey;
2008     D3DDEVICEDESC7 d3dcaps;
2009
2010     /* Test loading of texture subrectangle with a mipmap surface. */
2011     memset(texture_levels, 0, sizeof(texture_levels));
2012     memset(cube_face_levels, 0, sizeof(cube_face_levels));
2013     memset(palettes, 0, sizeof(palettes));
2014
2015     for (i = 0; i < 2; i++)
2016     {
2017         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2018         ddsd.dwSize = sizeof(ddsd);
2019         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2020         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2021         ddsd.dwWidth = 128;
2022         ddsd.dwHeight = 128;
2023         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2024         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2025         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2026         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2027         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2028         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2029         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2030         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2031         if (FAILED(hr)) goto out;
2032
2033         /* Check the number of created mipmaps */
2034         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2035         ddsd.dwSize = sizeof(ddsd);
2036         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2037         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2038         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2039         if (U2(ddsd).dwMipMapCount != 8) goto out;
2040
2041         for (i1 = 1; i1 < 8; i1++)
2042         {
2043             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2044             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2045             if (FAILED(hr)) goto out;
2046         }
2047     }
2048
2049     for (i1 = 0; i1 < 8; i1++)
2050     {
2051         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2052         ddsd.dwSize = sizeof(ddsd);
2053         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2054         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2055         if (FAILED(hr)) goto out;
2056
2057         for (y = 0 ; y < ddsd.dwHeight; y++)
2058         {
2059             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2060
2061             for (x = 0; x < ddsd.dwWidth;  x++)
2062             {
2063                 /* x stored in green component, y in blue. */
2064                 DWORD color = 0xff0000 | (x << 8)  | y;
2065                 *textureRow++ = color;
2066             }
2067         }
2068
2069         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2070         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2071     }
2072
2073     for (i1 = 0; i1 < 8; i1++)
2074     {
2075         memset(&ddbltfx, 0, sizeof(ddbltfx));
2076         ddbltfx.dwSize = sizeof(ddbltfx);
2077         U5(ddbltfx).dwFillColor = 0;
2078         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2079         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2080     }
2081
2082     /* First test some broken coordinates. */
2083     loadpoint.x = loadpoint.y = 0;
2084     loadrect.left = 0;
2085     loadrect.top = 0;
2086     loadrect.right = 0;
2087     loadrect.bottom = 0;
2088     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2089     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2090
2091     loadpoint.x = loadpoint.y = 50;
2092     loadrect.left = 0;
2093     loadrect.top = 0;
2094     loadrect.right = 100;
2095     loadrect.bottom = 100;
2096     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2097     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2098
2099     /* Test actual loading. */
2100     loadpoint.x = loadpoint.y = 31;
2101     loadrect.left = 30;
2102     loadrect.top = 20;
2103     loadrect.right = 93;
2104     loadrect.bottom = 52;
2105
2106     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2107     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2108
2109     for (i1 = 0; i1 < 8; i1++)
2110     {
2111         diff_count = 0;
2112         diff_count2 = 0;
2113
2114         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2115         ddsd.dwSize = sizeof(ddsd);
2116         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2117         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2118         if (FAILED(hr)) goto out;
2119
2120         for (y = 0 ; y < ddsd.dwHeight; y++)
2121         {
2122             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2123
2124             for (x = 0; x < ddsd.dwWidth;  x++)
2125             {
2126                 DWORD color = *textureRow++;
2127
2128                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2129                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2130                 {
2131                     if (color & 0xffffff) diff_count++;
2132                 }
2133                 else
2134                 {
2135                     DWORD r = (color & 0xff0000) >> 16;
2136                     DWORD g = (color & 0xff00) >> 8;
2137                     DWORD b = (color & 0xff);
2138
2139                     if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
2140                 }
2141
2142                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2143                    technically be correct as it's not precisely defined by docs. */
2144                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2145                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2146                 {
2147                     if (color & 0xffffff) diff_count2++;
2148                 }
2149                 else
2150                 {
2151                     DWORD r = (color & 0xff0000) >> 16;
2152                     DWORD g = (color & 0xff00) >> 8;
2153                     DWORD b = (color & 0xff);
2154
2155                     if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2156                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2157                 }
2158             }
2159         }
2160
2161         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2162         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2163
2164         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2165                 MIN(diff_count, diff_count2), i1);
2166
2167         loadpoint.x /= 2;
2168         loadpoint.y /= 2;
2169         loadrect.top /= 2;
2170         loadrect.left /= 2;
2171         loadrect.right = (loadrect.right + 1) / 2;
2172         loadrect.bottom = (loadrect.bottom + 1) / 2;
2173     }
2174
2175     /* This crashes on native (tested on real windows XP / directx9 / nvidia and
2176      * qemu Win98 / directx7 / RGB software rasterizer):
2177      * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
2178     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
2179     */
2180
2181     /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
2182     for (i = 0; i < 2; i++)
2183     {
2184         for (i1 = 7; i1 >= 0; i1--)
2185         {
2186             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2187         }
2188     }
2189     memset(texture_levels, 0, sizeof(texture_levels));
2190
2191     /* Test texture size mismatch. */
2192     for (i = 0; i < 2; i++)
2193     {
2194         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2195         ddsd.dwSize = sizeof(ddsd);
2196         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2197         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2198         ddsd.dwWidth = i ? 256 : 128;
2199         ddsd.dwHeight = 128;
2200         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2201         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2202         if (FAILED(hr)) goto out;
2203     }
2204
2205     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2206     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2207
2208     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
2209     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2210
2211     IDirectDrawSurface7_Release(texture_levels[0][0]);
2212     IDirectDrawSurface7_Release(texture_levels[1][0]);
2213     memset(texture_levels, 0, sizeof(texture_levels));
2214
2215     memset(&d3dcaps, 0, sizeof(d3dcaps));
2216     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
2217     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
2218
2219     if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
2220     {
2221         skip("No cubemap support\n");
2222     }
2223     else
2224     {
2225         /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
2226         for (i = 0; i < 2; i++)
2227         {
2228             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2229             ddsd.dwSize = sizeof(ddsd);
2230             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2231             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2232             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2233             ddsd.dwWidth = 128;
2234             ddsd.dwHeight = 128;
2235             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2236             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2237             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2238             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2239             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2240             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2241             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
2242             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2243             if (FAILED(hr)) goto out;
2244
2245             flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
2246             for (i1 = 1; i1 < 6; i1++, flags <<= 1)
2247             {
2248                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2249                 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
2250                 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
2251                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2252                 if (FAILED(hr)) goto out;
2253             }
2254
2255             for (i1 = 0; i1 < 6; i1++)
2256             {
2257                 /* Check the number of created mipmaps */
2258                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2259                 ddsd.dwSize = sizeof(ddsd);
2260                 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
2261                 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2262                 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2263                 if (U2(ddsd).dwMipMapCount != 8) goto out;
2264
2265                 for (i2 = 1; i2 < 8; i2++)
2266                 {
2267                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
2268                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
2269                     hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
2270                     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2271                     if (FAILED(hr)) goto out;
2272                 }
2273             }
2274         }
2275
2276         for (i = 0; i < 6; i++)
2277             for (i1 = 0; i1 < 8; i1++)
2278             {
2279                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2280                 ddsd.dwSize = sizeof(ddsd);
2281                 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2282                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2283                 if (FAILED(hr)) goto out;
2284
2285                 for (y = 0 ; y < ddsd.dwHeight; y++)
2286                 {
2287                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2288
2289                     for (x = 0; x < ddsd.dwWidth;  x++)
2290                     {
2291                         /* face number in low 4 bits of red, x stored in green component, y in blue. */
2292                         DWORD color = 0xf00000 | (i << 16) | (x << 8)  | y;
2293                         *textureRow++ = color;
2294                     }
2295                 }
2296
2297                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
2298                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2299             }
2300
2301         for (i = 0; i < 6; i++)
2302             for (i1 = 0; i1 < 8; i1++)
2303             {
2304                 memset(&ddbltfx, 0, sizeof(ddbltfx));
2305                 ddbltfx.dwSize = sizeof(ddbltfx);
2306                 U5(ddbltfx).dwFillColor = 0;
2307                 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2308                 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2309             }
2310
2311         loadpoint.x = loadpoint.y = 10;
2312         loadrect.left = 30;
2313         loadrect.top = 20;
2314         loadrect.right = 93;
2315         loadrect.bottom = 52;
2316
2317         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2318                                         DDSCAPS2_CUBEMAP_ALLFACES);
2319         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2320
2321         for (i = 0; i < 6; i++)
2322         {
2323             loadpoint.x = loadpoint.y = 10;
2324             loadrect.left = 30;
2325             loadrect.top = 20;
2326             loadrect.right = 93;
2327             loadrect.bottom = 52;
2328
2329             for (i1 = 0; i1 < 8; i1++)
2330             {
2331                 diff_count = 0;
2332                 diff_count2 = 0;
2333
2334                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2335                 ddsd.dwSize = sizeof(ddsd);
2336                 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2337                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2338                 if (FAILED(hr)) goto out;
2339
2340                 for (y = 0 ; y < ddsd.dwHeight; y++)
2341                 {
2342                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2343
2344                     for (x = 0; x < ddsd.dwWidth;  x++)
2345                     {
2346                         DWORD color = *textureRow++;
2347
2348                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2349                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2350                         {
2351                             if (color & 0xffffff) diff_count++;
2352                         }
2353                         else
2354                         {
2355                             DWORD r = (color & 0xff0000) >> 16;
2356                             DWORD g = (color & 0xff00) >> 8;
2357                             DWORD b = (color & 0xff);
2358
2359                             if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2360                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2361                         }
2362
2363                         /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2364                         technically be correct as it's not precisely defined by docs. */
2365                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2366                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2367                         {
2368                             if (color & 0xffffff) diff_count2++;
2369                         }
2370                         else
2371                         {
2372                             DWORD r = (color & 0xff0000) >> 16;
2373                             DWORD g = (color & 0xff00) >> 8;
2374                             DWORD b = (color & 0xff);
2375
2376                             if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2377                                 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2378                         }
2379                     }
2380                 }
2381
2382                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2383                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2384
2385                 ok(diff_count == 0 || diff_count2 == 0,
2386                     "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2387                     MIN(diff_count, diff_count2), i, i1);
2388
2389                 loadpoint.x /= 2;
2390                 loadpoint.y /= 2;
2391                 loadrect.top /= 2;
2392                 loadrect.left /= 2;
2393                 loadrect.right = (loadrect.right + 1) / 2;
2394                 loadrect.bottom = (loadrect.bottom + 1) / 2;
2395             }
2396         }
2397
2398         for (i = 0; i < 2; i++)
2399             for (i1 = 5; i1 >= 0; i1--)
2400                 for (i2 = 7; i2 >= 0; i2--)
2401                 {
2402                     if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2403                 }
2404         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2405
2406         /* Test cubemap loading from regular texture. */
2407         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2408         ddsd.dwSize = sizeof(ddsd);
2409         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2410         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2411         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2412         ddsd.dwWidth = 128;
2413         ddsd.dwHeight = 128;
2414         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2415         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2416         if (FAILED(hr)) goto out;
2417
2418         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2419         ddsd.dwSize = sizeof(ddsd);
2420         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2421         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2422         ddsd.dwWidth = 128;
2423         ddsd.dwHeight = 128;
2424         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2425         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2426         if (FAILED(hr)) goto out;
2427
2428         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2429                                         DDSCAPS2_CUBEMAP_ALLFACES);
2430         ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2431
2432         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2433         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2434         IDirectDrawSurface7_Release(texture_levels[0][0]);
2435         memset(texture_levels, 0, sizeof(texture_levels));
2436
2437         /* Partial cube maps(e.g. created with an explicitly set DDSCAPS2_CUBEMAP_POSITIVEX flag)
2438          * BSOD some Windows machines when an app tries to create them(Radeon X1600, Windows XP,
2439          * Catalyst 10.2 driver, 6.14.10.6925)
2440          */
2441     }
2442
2443     /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2444     for (i = 0; i < 2; i++)
2445     {
2446         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2447         ddsd.dwSize = sizeof(ddsd);
2448         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2449         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2450         ddsd.dwWidth = 128;
2451         ddsd.dwHeight = 128;
2452         U2(ddsd).dwMipMapCount = i ? 4 : 8;
2453         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2454         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2455         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2456         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2457         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2458         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2459         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2460         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2461         if (FAILED(hr)) goto out;
2462
2463         /* Check the number of created mipmaps */
2464         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2465         ddsd.dwSize = sizeof(ddsd);
2466         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2467         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2468         ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2469         if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2470
2471         for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2472         {
2473             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2474             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2475             if (FAILED(hr)) goto out;
2476         }
2477     }
2478
2479     for (i1 = 0; i1 < 8; i1++)
2480     {
2481         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2482         ddsd.dwSize = sizeof(ddsd);
2483         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2484         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2485         if (FAILED(hr)) goto out;
2486
2487         for (y = 0 ; y < ddsd.dwHeight; y++)
2488         {
2489             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2490
2491             for (x = 0; x < ddsd.dwWidth;  x++)
2492             {
2493                 /* x stored in green component, y in blue. */
2494                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2495                 *textureRow++ = color;
2496             }
2497         }
2498
2499         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2500         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2501     }
2502
2503     for (i1 = 0; i1 < 4; i1++)
2504     {
2505         memset(&ddbltfx, 0, sizeof(ddbltfx));
2506         ddbltfx.dwSize = sizeof(ddbltfx);
2507         U5(ddbltfx).dwFillColor = 0;
2508         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2509         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2510     }
2511
2512     loadpoint.x = loadpoint.y = 31;
2513     loadrect.left = 30;
2514     loadrect.top = 20;
2515     loadrect.right = 93;
2516     loadrect.bottom = 52;
2517
2518     /* Destination mip levels are a subset of source mip levels. */
2519     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2520     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2521
2522     for (i1 = 0; i1 < 4; i1++)
2523     {
2524         diff_count = 0;
2525         diff_count2 = 0;
2526
2527         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2528         ddsd.dwSize = sizeof(ddsd);
2529         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2530         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2531         if (FAILED(hr)) goto out;
2532
2533         for (y = 0 ; y < ddsd.dwHeight; y++)
2534         {
2535             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2536
2537             for (x = 0; x < ddsd.dwWidth;  x++)
2538             {
2539                 DWORD color = *textureRow++;
2540
2541                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2542                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2543                 {
2544                     if (color & 0xffffff) diff_count++;
2545                 }
2546                 else
2547                 {
2548                     DWORD r = (color & 0xff0000) >> 16;
2549                     DWORD g = (color & 0xff00) >> 8;
2550                     DWORD b = (color & 0xff);
2551
2552                     if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2553                         b != y + loadrect.top - loadpoint.y) diff_count++;
2554                 }
2555
2556                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2557                 technically be correct as it's not precisely defined by docs. */
2558                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2559                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2560                 {
2561                     if (color & 0xffffff) diff_count2++;
2562                 }
2563                 else
2564                 {
2565                     DWORD r = (color & 0xff0000) >> 16;
2566                     DWORD g = (color & 0xff00) >> 8;
2567                     DWORD b = (color & 0xff);
2568
2569                     if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2570                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2571                 }
2572             }
2573         }
2574
2575         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2576         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2577
2578         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2579              MIN(diff_count, diff_count2), i1);
2580
2581         loadpoint.x /= 2;
2582         loadpoint.y /= 2;
2583         loadrect.top /= 2;
2584         loadrect.left /= 2;
2585         loadrect.right = (loadrect.right + 1) / 2;
2586         loadrect.bottom = (loadrect.bottom + 1) / 2;
2587     }
2588
2589     /* Destination mip levels are a superset of source mip levels (should fail). */
2590     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2591     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2592
2593     for (i = 0; i < 2; i++)
2594     {
2595         for (i1 = 7; i1 >= 0; i1--)
2596         {
2597             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2598         }
2599     }
2600     memset(texture_levels, 0, sizeof(texture_levels));
2601
2602     /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2603     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2604     ddsd.dwSize = sizeof(ddsd);
2605     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2606     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2607     ddsd.dwWidth = 128;
2608     ddsd.dwHeight = 128;
2609     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2610     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2611     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2612     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2613     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2614     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2615     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2616     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2617     if (FAILED(hr)) goto out;
2618
2619     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2620     ddsd.dwSize = sizeof(ddsd);
2621     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2622     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2623     ddsd.dwWidth = 32;
2624     ddsd.dwHeight = 32;
2625     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2626     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2627     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2628     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2629     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2630     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2631     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2632     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2633     if (FAILED(hr)) goto out;
2634
2635     for (i1 = 1; i1 < 8; i1++)
2636     {
2637         hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2638         ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2639         if (FAILED(hr)) goto out;
2640     }
2641
2642     for (i1 = 0; i1 < 8; i1++)
2643     {
2644         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2645         ddsd.dwSize = sizeof(ddsd);
2646         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2647         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2648         if (FAILED(hr)) goto out;
2649
2650         for (y = 0 ; y < ddsd.dwHeight; y++)
2651         {
2652             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2653
2654             for (x = 0; x < ddsd.dwWidth;  x++)
2655             {
2656                 /* x stored in green component, y in blue. */
2657                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2658                 *textureRow++ = color;
2659             }
2660         }
2661
2662         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2663         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2664     }
2665
2666     memset(&ddbltfx, 0, sizeof(ddbltfx));
2667     ddbltfx.dwSize = sizeof(ddbltfx);
2668     U5(ddbltfx).dwFillColor = 0;
2669     hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2670     ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2671
2672     loadpoint.x = loadpoint.y = 32;
2673     loadrect.left = 32;
2674     loadrect.top = 32;
2675     loadrect.right = 96;
2676     loadrect.bottom = 96;
2677
2678     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2679     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2680
2681     loadpoint.x /= 4;
2682     loadpoint.y /= 4;
2683     loadrect.top /= 4;
2684     loadrect.left /= 4;
2685     loadrect.right = (loadrect.right + 3) / 4;
2686     loadrect.bottom = (loadrect.bottom + 3) / 4;
2687
2688     /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2689      * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2690      * copied subrectangles divided more than needed, without apparent logic. But it works
2691      * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2692      * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2693      * The following code attempts to detect broken results, actual tests will then be skipped
2694      */
2695     load_mip_subset_broken = TRUE;
2696     diff_count = 0;
2697
2698     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2699     ddsd.dwSize = sizeof(ddsd);
2700     hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2701     ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2702     if (FAILED(hr)) goto out;
2703
2704     for (y = 0 ; y < ddsd.dwHeight; y++)
2705     {
2706         DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2707
2708         for (x = 0; x < ddsd.dwWidth;  x++)
2709         {
2710             DWORD color = *textureRow++;
2711
2712             if (x < 2 || x >= 2 + 4 ||
2713                 y < 2 || y >= 2 + 4)
2714             {
2715                 if (color & 0xffffff) diff_count++;
2716             }
2717             else
2718             {
2719                 DWORD r = (color & 0xff0000) >> 16;
2720
2721                 if ((r & (0xf0)) != 0xf0) diff_count++;
2722             }
2723         }
2724     }
2725
2726     if (diff_count) load_mip_subset_broken = FALSE;
2727
2728     if (load_mip_subset_broken) {
2729         skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2730     } else {
2731         diff_count = 0;
2732
2733         for (y = 0 ; y < ddsd.dwHeight; y++)
2734         {
2735             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2736
2737             for (x = 0; x < ddsd.dwWidth;  x++)
2738             {
2739                 DWORD color = *textureRow++;
2740
2741                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2742                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2743                 {
2744                     if (color & 0xffffff) diff_count++;
2745                 }
2746                 else
2747                 {
2748                     DWORD r = (color & 0xff0000) >> 16;
2749                     DWORD g = (color & 0xff00) >> 8;
2750                     DWORD b = (color & 0xff);
2751
2752                     if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2753                         b != y + loadrect.top - loadpoint.y) diff_count++;
2754                 }
2755             }
2756         }
2757     }
2758
2759     hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2760     ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2761
2762     ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2763
2764     for (i = 0; i < 2; i++)
2765     {
2766         for (i1 = 7; i1 >= 0; i1--)
2767         {
2768             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2769         }
2770     }
2771     memset(texture_levels, 0, sizeof(texture_levels));
2772
2773     if (!load_mip_subset_broken)
2774     {
2775         /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2776         * surface (than first source mip level)
2777         */
2778         for (i = 0; i < 2; i++)
2779         {
2780             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2781             ddsd.dwSize = sizeof(ddsd);
2782             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2783             if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2784             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2785             ddsd.dwWidth = i ? 32 : 128;
2786             ddsd.dwHeight = i ? 32 : 128;
2787             if (i) U2(ddsd).dwMipMapCount = 4;
2788             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2789             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2790             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2791             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2792             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2793             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2794             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2795             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2796             if (FAILED(hr)) goto out;
2797
2798             /* Check the number of created mipmaps */
2799             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2800             ddsd.dwSize = sizeof(ddsd);
2801             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2802             ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2803             ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2804             if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2805
2806             for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2807             {
2808                 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2809                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2810                 if (FAILED(hr)) goto out;
2811             }
2812         }
2813
2814         for (i1 = 0; i1 < 8; i1++)
2815         {
2816             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2817             ddsd.dwSize = sizeof(ddsd);
2818             hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2819             ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2820             if (FAILED(hr)) goto out;
2821
2822             for (y = 0 ; y < ddsd.dwHeight; y++)
2823             {
2824                 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2825
2826                 for (x = 0; x < ddsd.dwWidth;  x++)
2827                 {
2828                     /* x stored in green component, y in blue. */
2829                     DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2830                     *textureRow++ = color;
2831                 }
2832             }
2833
2834             hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2835             ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2836         }
2837
2838         for (i1 = 0; i1 < 4; i1++)
2839         {
2840             memset(&ddbltfx, 0, sizeof(ddbltfx));
2841             ddbltfx.dwSize = sizeof(ddbltfx);
2842             U5(ddbltfx).dwFillColor = 0;
2843             hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2844             ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2845         }
2846
2847         loadpoint.x = loadpoint.y = 0;
2848         loadrect.left = 0;
2849         loadrect.top = 0;
2850         loadrect.right = 64;
2851         loadrect.bottom = 64;
2852
2853         hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2854         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2855
2856         i = 0;
2857         for (i1 = 0; i1 < 8 && i < 4; i1++)
2858         {
2859             DDSURFACEDESC2 ddsd2;
2860
2861             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2862             ddsd.dwSize = sizeof(ddsd);
2863             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2864             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2865
2866             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2867             ddsd2.dwSize = sizeof(ddsd2);
2868             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2869             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2870
2871             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2872             {
2873                 diff_count = 0;
2874
2875                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2876                 ddsd.dwSize = sizeof(ddsd);
2877                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2878                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2879                 if (FAILED(hr)) goto out;
2880
2881                 for (y = 0 ; y < ddsd.dwHeight; y++)
2882                 {
2883                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2884
2885                     for (x = 0; x < ddsd.dwWidth;  x++)
2886                     {
2887                         DWORD color = *textureRow++;
2888
2889                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2890                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2891                         {
2892                             if (color & 0xffffff) diff_count++;
2893                         }
2894                         else
2895                         {
2896                             DWORD r = (color & 0xff0000) >> 16;
2897                             DWORD g = (color & 0xff00) >> 8;
2898                             DWORD b = (color & 0xff);
2899
2900                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2901                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2902                         }
2903                     }
2904                 }
2905
2906                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2907                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2908
2909                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2910
2911                 i++;
2912             }
2913
2914             loadpoint.x /= 2;
2915             loadpoint.y /= 2;
2916             loadrect.top /= 2;
2917             loadrect.left /= 2;
2918             loadrect.right = (loadrect.right + 1) / 2;
2919             loadrect.bottom = (loadrect.bottom + 1) / 2;
2920         }
2921
2922         for (i = 0; i < 2; i++)
2923         {
2924             for (i1 = 7; i1 >= 0; i1--)
2925             {
2926                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2927             }
2928         }
2929         memset(texture_levels, 0, sizeof(texture_levels));
2930     }
2931
2932     /* Test palette copying. */
2933     for (i = 0; i < 2; i++)
2934     {
2935         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2936         ddsd.dwSize = sizeof(ddsd);
2937         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2938         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2939         ddsd.dwWidth = 128;
2940         ddsd.dwHeight = 128;
2941         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2942         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2943         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2944         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2945         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2946         if (FAILED(hr)) goto out;
2947
2948         /* Check the number of created mipmaps */
2949         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2950         ddsd.dwSize = sizeof(ddsd);
2951         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2952         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2953         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2954         if (U2(ddsd).dwMipMapCount != 8) goto out;
2955
2956         for (i1 = 1; i1 < 8; i1++)
2957         {
2958             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2959             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2960             if (FAILED(hr)) goto out;
2961         }
2962     }
2963
2964     memset(table1, 0, sizeof(table1));
2965     for (i = 0; i < 3; i++)
2966     {
2967         table1[0].peBlue = i + 1;
2968         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2969         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2970         if (FAILED(hr))
2971         {
2972             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2973             goto out;
2974         }
2975     }
2976
2977     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2978     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2979
2980     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2981     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2982
2983     hr = IDirectDrawSurface7_GetPalette(texture_levels[0][1], &palettes[4]);
2984     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2985
2986     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2987     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2988
2989     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2990     ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2991     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2992     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2993
2994     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2995     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2996
2997     memset(table1, 0, sizeof(table1));
2998     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2999     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
3000     if (SUCCEEDED(hr))
3001     {
3002         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
3003         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
3004         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
3005     }
3006
3007     /* Test colorkey copying. */
3008     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
3009     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
3010     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
3011     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
3012     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
3013
3014     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
3015     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
3016
3017     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
3018     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
3019
3020     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
3021     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
3022     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
3023         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
3024
3025     out:
3026
3027     for (i = 0; i < 5; i++)
3028     {
3029         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
3030     }
3031
3032     for (i = 0; i < 2; i++)
3033     {
3034         for (i1 = 7; i1 >= 0; i1--)
3035         {
3036             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
3037         }
3038     }
3039
3040     for (i = 0; i < 2; i++)
3041         for (i1 = 5; i1 >= 0; i1--)
3042             for (i2 = 7; i2 >= 0; i2--)
3043             {
3044                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
3045             }
3046 }
3047
3048 static void SetMaterialTest(void)
3049 {
3050     HRESULT rc;
3051
3052     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
3053     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
3054 }
3055
3056 static void ComputeSphereVisibility(void)
3057 {
3058     D3DMATRIX proj, view, world;
3059     D3DVALUE radius[3];
3060     D3DVECTOR center[3];
3061     DWORD result[3];
3062     HRESULT rc;
3063
3064     world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
3065     world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
3066     world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
3067     world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
3068
3069     view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
3070     view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
3071     view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
3072     view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
3073
3074     proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
3075     proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
3076     proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
3077     proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
3078
3079     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
3080     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
3081     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3082
3083     U1(center[0]).x=11.461533;
3084     U2(center[0]).y=-4.761727;
3085     U3(center[0]).z=-1.171646;
3086
3087     radius[0]=38.252632;
3088
3089     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3090
3091     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3092     ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
3093
3094     U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
3095     radius[0]=4.354097;
3096     U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
3097     radius[1]=12.500704;
3098     U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
3099     radius[2]=17.251318;
3100
3101     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
3102
3103     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3104     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
3105     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3106     ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
3107     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3108     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
3109
3110     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
3111     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
3112     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
3113     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
3114
3115     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
3116     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
3117     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
3118     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
3119
3120     U1(center[0]).x=0.0;
3121     U2(center[0]).y=0.0;
3122     U3(center[0]).z=0.05;
3123
3124     radius[0]=0.04;
3125
3126     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
3127     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3128
3129     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3130
3131     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3132     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3133
3134     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
3135     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
3136     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
3137     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
3138
3139     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3140
3141     U1(center[0]).x=0.0;
3142     U2(center[0]).y=0.0;
3143     U3(center[0]).z=0.5;
3144
3145     radius[0]=0.5;
3146
3147     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3148
3149     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3150     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3151
3152     U1(center[0]).x=0.0;
3153     U2(center[0]).y=0.0;
3154     U3(center[0]).z=0.0;
3155
3156     radius[0]=0.0;
3157
3158     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3159
3160     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3161     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3162
3163     U1(center[0]).x=-1.0;
3164     U2(center[0]).y=-1.0;
3165     U3(center[0]).z=0.50;
3166
3167     radius[0]=0.25;
3168
3169     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3170
3171     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3172     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
3173
3174     U1(center[0]).x=-20.0;
3175     U2(center[0]).y=0.0;
3176     U3(center[0]).z=0.50;
3177
3178     radius[0]=3.0;
3179
3180     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3181
3182     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3183     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
3184
3185     U1(center[0]).x=20.0;
3186     U2(center[0]).y=0.0;
3187     U3(center[0]).z=0.50;
3188
3189     radius[0]=3.0f;
3190
3191     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3192
3193     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3194     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
3195
3196     U1(center[0]).x=0.0;
3197     U2(center[0]).y=-20.0;
3198     U3(center[0]).z=0.50;
3199
3200     radius[0]=3.0;
3201
3202     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3203
3204     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3205     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
3206
3207     U1(center[0]).x=0.0;
3208     U2(center[0]).y=20.0;
3209     U3(center[0]).z=0.5;
3210
3211     radius[0]=3.0;
3212
3213     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3214
3215     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3216     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
3217
3218     U1(center[0]).x=0.0;
3219     U2(center[0]).y=0.0;
3220     U3(center[0]).z=-20;
3221
3222     radius[0]=3.0;
3223
3224     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3225
3226     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3227     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
3228
3229     U1(center[0]).x=0.0;
3230     U2(center[0]).y=0.0;
3231     U3(center[0]).z=20.0;
3232
3233     radius[0]=3.0;
3234
3235     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3236
3237     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3238     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
3239 }
3240
3241 static void SetRenderTargetTest(void)
3242 {
3243     HRESULT hr;
3244     IDirectDrawSurface7 *newrt, *failrt, *oldrt, *temprt;
3245     D3DVIEWPORT7 vp;
3246     DDSURFACEDESC2 ddsd, ddsd2;
3247     DWORD stateblock;
3248     ULONG refcount;
3249
3250     memset(&ddsd, 0, sizeof(ddsd));
3251     ddsd.dwSize = sizeof(ddsd);
3252     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3253     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
3254     ddsd.dwWidth = 64;
3255     ddsd.dwHeight = 64;
3256
3257     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
3258     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3259     if(FAILED(hr))
3260     {
3261         skip("Skipping SetRenderTarget test\n");
3262         return;
3263     }
3264
3265     memset(&ddsd2, 0, sizeof(ddsd2));
3266     ddsd2.dwSize = sizeof(ddsd2);
3267     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3268     ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER;
3269     ddsd2.dwWidth = 64;
3270     ddsd2.dwHeight = 64;
3271     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
3272     U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3273     U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3274     U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3275
3276     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd2, &failrt, NULL);
3277     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3278
3279     memset(&vp, 0, sizeof(vp));
3280     vp.dwX = 10;
3281     vp.dwY = 10;
3282     vp.dwWidth = 246;
3283     vp.dwHeight = 246;
3284     vp.dvMinZ = 0.25;
3285     vp.dvMaxZ = 0.75;
3286     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3287     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3288
3289     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3290     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3291
3292     refcount = getRefcount((IUnknown*) oldrt);
3293     todo_wine ok(refcount == 3, "Refcount should be 3, returned is %d\n", refcount);
3294
3295     refcount = getRefcount((IUnknown*) failrt);
3296     ok(refcount == 1, "Refcount should be 1, returned is %d\n", refcount);
3297
3298     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, failrt, 0);
3299     ok(hr != D3D_OK, "IDirect3DDevice7_SetRenderTarget succeeded\n");
3300
3301     refcount = getRefcount((IUnknown*) oldrt);
3302     todo_wine ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3303
3304     refcount = getRefcount((IUnknown*) failrt);
3305     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3306
3307     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &temprt);
3308     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3309     ok(failrt == temprt, "Wrong iface returned\n");
3310
3311     refcount = getRefcount((IUnknown*) failrt);
3312     ok(refcount == 3, "Refcount should be 3, returned is %d\n", refcount);
3313
3314     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3315     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3316
3317     refcount = getRefcount((IUnknown*) failrt);
3318     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3319
3320     memset(&vp, 0xff, sizeof(vp));
3321     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3322     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3323     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3324     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3325     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3326     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3327     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.25\n", vp.dvMinZ);
3328     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.75\n", vp.dvMaxZ);
3329
3330     memset(&vp, 0, sizeof(vp));
3331     vp.dwX = 0;
3332     vp.dwY = 0;
3333     vp.dwWidth = 64;
3334     vp.dwHeight = 64;
3335     vp.dvMinZ = 0.0;
3336     vp.dvMaxZ = 1.0;
3337     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3338     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3339
3340     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3341     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3342     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3343     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3344
3345     /* Check this twice, before and after ending the stateblock */
3346     memset(&vp, 0xff, sizeof(vp));
3347     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3348     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3349     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3350     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3351     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3352     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3353     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3354     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3355
3356     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3357     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3358
3359     memset(&vp, 0xff, sizeof(vp));
3360     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3361     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3362     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3363     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3364     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3365     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3366     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3367     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3368
3369     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3370     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3371
3372     memset(&vp, 0, sizeof(vp));
3373     vp.dwX = 0;
3374     vp.dwY = 0;
3375     vp.dwWidth = 256;
3376     vp.dwHeight = 256;
3377     vp.dvMinZ = 0.0;
3378     vp.dvMaxZ = 0.0;
3379     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3380     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3381
3382     IDirectDrawSurface7_Release(oldrt);
3383     IDirectDrawSurface7_Release(newrt);
3384     IDirectDrawSurface7_Release(failrt);
3385     IDirectDrawSurface7_Release(failrt);
3386 }
3387
3388 static const UINT *expect_messages;
3389
3390 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3391 {
3392     if (expect_messages && message == *expect_messages) ++expect_messages;
3393
3394     return DefWindowProcA(hwnd, message, wparam, lparam);
3395 }
3396
3397 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
3398  * interface. This prevents subsequent SetCooperativeLevel() calls on a
3399  * different window from failing with DDERR_HWNDALREADYSET. */
3400 static void fix_wndproc(HWND window, LONG_PTR proc)
3401 {
3402     IDirectDraw7 *ddraw7;
3403     HRESULT hr;
3404
3405     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3406     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 object, hr %#x.\n", hr);
3407     if (FAILED(hr)) return;
3408
3409     SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
3410     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3411     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3412     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3413     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3414
3415     IDirectDraw7_Release(ddraw7);
3416 }
3417
3418 static void test_wndproc(void)
3419 {
3420     LONG_PTR proc, ddraw_proc;
3421     IDirectDraw7 *ddraw7;
3422     WNDCLASSA wc = {0};
3423     HWND window;
3424     HRESULT hr;
3425     ULONG ref;
3426
3427     static const UINT messages[] =
3428     {
3429         WM_WINDOWPOSCHANGING,
3430         WM_MOVE,
3431         WM_SIZE,
3432         WM_WINDOWPOSCHANGING,
3433         WM_ACTIVATE,
3434         WM_SETFOCUS,
3435         0,
3436     };
3437
3438     /* DDSCL_EXCLUSIVE replaces the window's window proc. */
3439     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3440     if (FAILED(hr))
3441     {
3442         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3443         return;
3444     }
3445
3446     wc.lpfnWndProc = test_proc;
3447     wc.lpszClassName = "d3d7_test_wndproc_wc";
3448     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3449
3450     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test",
3451             WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3452
3453     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3454     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3455             (LONG_PTR)test_proc, proc);
3456
3457     expect_messages = messages;
3458
3459     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3460     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3461     if (FAILED(hr))
3462     {
3463         IDirectDraw7_Release(ddraw7);
3464         goto done;
3465     }
3466
3467     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3468     expect_messages = NULL;
3469
3470     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3471     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3472             (LONG_PTR)test_proc, proc);
3473
3474     ref = IDirectDraw7_Release(ddraw7);
3475     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3476
3477     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3478     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3479             (LONG_PTR)test_proc, proc);
3480
3481     /* DDSCL_NORMAL doesn't. */
3482     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3483     if (FAILED(hr))
3484     {
3485         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3486         return;
3487     }
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     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3494     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3495     if (FAILED(hr))
3496     {
3497         IDirectDraw7_Release(ddraw7);
3498         goto done;
3499     }
3500
3501     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3502     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3503             (LONG_PTR)test_proc, proc);
3504
3505     ref = IDirectDraw7_Release(ddraw7);
3506     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
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     /* The original window proc is only restored by ddraw if the current
3513      * window proc matches the one ddraw set. This also affects switching
3514      * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
3515     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3516     if (FAILED(hr))
3517     {
3518         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3519         return;
3520     }
3521
3522     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3523     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3524             (LONG_PTR)test_proc, proc);
3525
3526     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3527     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3528     if (FAILED(hr))
3529     {
3530         IDirectDraw7_Release(ddraw7);
3531         goto done;
3532     }
3533
3534     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3535     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3536             (LONG_PTR)test_proc, proc);
3537     ddraw_proc = proc;
3538
3539     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3540     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3541     if (FAILED(hr))
3542     {
3543         IDirectDraw7_Release(ddraw7);
3544         goto done;
3545     }
3546
3547     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3548     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3549             (LONG_PTR)test_proc, proc);
3550
3551     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3552     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3553     if (FAILED(hr))
3554     {
3555         IDirectDraw7_Release(ddraw7);
3556         goto done;
3557     }
3558
3559     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3560     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3561             (LONG_PTR)test_proc, proc);
3562
3563     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3564     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3565     if (FAILED(hr))
3566     {
3567         IDirectDraw7_Release(ddraw7);
3568         goto done;
3569     }
3570
3571     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3572     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3573             (LONG_PTR)DefWindowProcA, proc);
3574
3575     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3576     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3577     if (FAILED(hr))
3578     {
3579         IDirectDraw7_Release(ddraw7);
3580         goto done;
3581     }
3582
3583     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
3584     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3585             (LONG_PTR)DefWindowProcA, proc);
3586
3587     ref = IDirectDraw7_Release(ddraw7);
3588     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3589
3590     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3591     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3592             (LONG_PTR)test_proc, proc);
3593
3594     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3595     if (FAILED(hr))
3596     {
3597         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3598         return;
3599     }
3600
3601     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3602     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3603             (LONG_PTR)test_proc, proc);
3604
3605     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3606     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3607     if (FAILED(hr))
3608     {
3609         IDirectDraw7_Release(ddraw7);
3610         goto done;
3611     }
3612
3613     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3614     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3615             (LONG_PTR)test_proc, proc);
3616
3617     ref = IDirectDraw7_Release(ddraw7);
3618     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3619
3620     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3621     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3622             (LONG_PTR)DefWindowProcA, proc);
3623
3624 done:
3625     fix_wndproc(window, (LONG_PTR)test_proc);
3626     expect_messages = NULL;
3627     DestroyWindow(window);
3628     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
3629 }
3630
3631 static void VertexBufferLockRest(void)
3632 {
3633     D3DVERTEXBUFFERDESC desc;
3634     IDirect3DVertexBuffer7 *buffer;
3635     HRESULT hr;
3636     unsigned int i;
3637     void *data;
3638     const struct
3639     {
3640         DWORD flags;
3641         const char *debug_string;
3642         HRESULT result;
3643     }
3644     test_data[] =
3645     {
3646         {0,                                         "(none)",                                       D3D_OK },
3647         {DDLOCK_WAIT,                               "DDLOCK_WAIT",                                  D3D_OK },
3648         {DDLOCK_EVENT,                              "DDLOCK_EVENT",                                 D3D_OK },
3649         {DDLOCK_READONLY,                           "DDLOCK_READONLY",                              D3D_OK },
3650         {DDLOCK_WRITEONLY,                          "DDLOCK_WRITEONLY",                             D3D_OK },
3651         {DDLOCK_NOSYSLOCK,                          "DDLOCK_NOSYSLOCK",                             D3D_OK },
3652         {DDLOCK_NOOVERWRITE,                        "DDLOCK_NOOVERWRITE",                           D3D_OK },
3653         {DDLOCK_DISCARDCONTENTS,                    "DDLOCK_DISCARDCONTENTS",                       D3D_OK },
3654
3655         {DDLOCK_READONLY | DDLOCK_WRITEONLY,        "DDLOCK_READONLY | DDLOCK_WRITEONLY",           D3D_OK },
3656         {DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS,  "DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS",     D3D_OK },
3657         {0xdeadbeef,                                "0xdeadbeef",                                   D3D_OK },
3658     };
3659
3660     memset(&desc, 0 , sizeof(desc));
3661     desc.dwSize = sizeof(desc);
3662     desc.dwCaps = 0;
3663     desc.dwFVF = D3DFVF_XYZ;
3664     desc.dwNumVertices = 64;
3665     hr = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &buffer, 0);
3666     ok(hr == D3D_OK, "IDirect3D7_CreateVertexBuffer failed, 0x%08x\n", hr);
3667
3668     for(i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
3669     {
3670         hr = IDirect3DVertexBuffer7_Lock(buffer, test_data[i].flags, &data, NULL);
3671         ok(hr == test_data[i].result, "Lock flags %s returned 0x%08x, expected 0x%08x\n",
3672             test_data[i].debug_string, hr, test_data[i].result);
3673         if(SUCCEEDED(hr))
3674         {
3675             ok(data != NULL, "The data pointer returned by Lock is NULL\n");
3676             hr = IDirect3DVertexBuffer7_Unlock(buffer);
3677             ok(hr == D3D_OK, "IDirect3DVertexBuffer7_Unlock failed, 0x%08x\n", hr);
3678         }
3679     }
3680
3681     IDirect3DVertexBuffer7_Release(buffer);
3682 }
3683
3684 static void FindDevice(void)
3685 {
3686     static const struct
3687     {
3688         const GUID *guid;
3689         int todo;
3690     } deviceGUIDs[] =
3691     {
3692         {&IID_IDirect3DRampDevice, 1},
3693         {&IID_IDirect3DRGBDevice},
3694     };
3695
3696     static const GUID *nonexistent_deviceGUIDs[] = {&IID_IDirect3DMMXDevice,
3697                                                     &IID_IDirect3DRefDevice,
3698                                                     &IID_IDirect3DTnLHalDevice,
3699                                                     &IID_IDirect3DNullDevice};
3700
3701     D3DFINDDEVICESEARCH search = {0};
3702     D3DFINDDEVICERESULT result = {0};
3703     IDirect3DDevice *d3dhal;
3704     HRESULT hr;
3705     int i;
3706
3707     /* Test invalid parameters. */
3708     hr = IDirect3D_FindDevice(Direct3D1, NULL, NULL);
3709     ok(hr == DDERR_INVALIDPARAMS,
3710        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3711
3712     hr = IDirect3D_FindDevice(Direct3D1, NULL, &result);
3713     ok(hr == DDERR_INVALIDPARAMS,
3714        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3715
3716     hr = IDirect3D_FindDevice(Direct3D1, &search, NULL);
3717     ok(hr == DDERR_INVALIDPARAMS,
3718        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3719
3720     search.dwSize = 0;
3721     result.dwSize = 0;
3722
3723     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3724     ok(hr == DDERR_INVALIDPARAMS,
3725        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3726
3727     search.dwSize = sizeof(search) + 1;
3728     result.dwSize = sizeof(result) + 1;
3729
3730     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3731     ok(hr == DDERR_INVALIDPARAMS,
3732        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3733
3734     /* Specifying no flags is permitted. */
3735     search.dwSize = sizeof(search);
3736     search.dwFlags = 0;
3737     result.dwSize = sizeof(result);
3738
3739     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3740     ok(hr == D3D_OK,
3741        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3742
3743     /* Try an arbitrary non-device GUID. */
3744     search.dwSize = sizeof(search);
3745     search.dwFlags = D3DFDS_GUID;
3746     search.guid = IID_IDirect3D;
3747     result.dwSize = sizeof(result);
3748
3749     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3750     ok(hr == DDERR_NOTFOUND,
3751        "Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", hr);
3752
3753     /* These GUIDs appear to be never present. */
3754     for (i = 0; i < sizeof(nonexistent_deviceGUIDs)/sizeof(nonexistent_deviceGUIDs[0]); i++)
3755     {
3756         search.dwSize = sizeof(search);
3757         search.dwFlags = D3DFDS_GUID;
3758         search.guid = *nonexistent_deviceGUIDs[i];
3759         result.dwSize = sizeof(result);
3760
3761         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3762         ok(hr == DDERR_NOTFOUND,
3763            "[%d] Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", i, hr);
3764     }
3765
3766     /* The HAL device can only be enumerated if hardware acceleration is present. */
3767     search.dwSize = sizeof(search);
3768     search.dwFlags = D3DFDS_GUID;
3769     search.guid = IID_IDirect3DHALDevice;
3770     result.dwSize = sizeof(result);
3771
3772     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3773     trace("IDirect3D::FindDevice returned 0x%08x for the HAL device GUID\n", hr);
3774     if (SUCCEEDED(hr))
3775     {
3776         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3777         /* Currently Wine only supports the creation of one Direct3D device
3778          * for a given DirectDraw instance. */
3779         todo_wine
3780         ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
3781            "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3782
3783         if (SUCCEEDED(hr))
3784             IDirect3DDevice_Release(d3dhal);
3785     }
3786     else
3787     {
3788         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3789         ok(FAILED(hr), "Expected IDirectDrawSurface::QueryInterface to fail, got 0x%08x\n", hr);
3790
3791         if (SUCCEEDED(hr))
3792             IDirect3DDevice_Release(d3dhal);
3793     }
3794
3795     /* These GUIDs appear to be always present. */
3796     for (i = 0; i < sizeof(deviceGUIDs)/sizeof(deviceGUIDs[0]); i++)
3797     {
3798         search.dwSize = sizeof(search);
3799         search.dwFlags = D3DFDS_GUID;
3800         search.guid = *deviceGUIDs[i].guid;
3801         result.dwSize = sizeof(result);
3802
3803         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3804
3805         if (deviceGUIDs[i].todo)
3806         {
3807             todo_wine
3808             ok(hr == D3D_OK,
3809                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3810         }
3811         else
3812         {
3813             ok(hr == D3D_OK,
3814                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3815         }
3816     }
3817
3818     /* Curiously the color model criteria seem to be ignored. */
3819     search.dwSize = sizeof(search);
3820     search.dwFlags = D3DFDS_COLORMODEL;
3821     search.dcmColorModel = 0xdeadbeef;
3822     result.dwSize = sizeof(result);
3823
3824     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3825     todo_wine
3826     ok(hr == D3D_OK,
3827        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3828 }
3829
3830 static void BackBuffer3DCreateSurfaceTest(void)
3831 {
3832     DDSURFACEDESC ddsd;
3833     DDSURFACEDESC created_ddsd;
3834     DDSURFACEDESC2 ddsd2;
3835     IDirectDrawSurface *surf;
3836     IDirectDrawSurface4 *surf4;
3837     IDirectDrawSurface7 *surf7;
3838     HRESULT hr;
3839     IDirectDraw2 *dd2;
3840     IDirectDraw4 *dd4;
3841     IDirectDraw7 *dd7;
3842     DDCAPS ddcaps;
3843     IDirect3DDevice *d3dhal;
3844
3845     const DWORD caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3846     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3847
3848     memset(&ddcaps, 0, sizeof(ddcaps));
3849     ddcaps.dwSize = sizeof(DDCAPS);
3850     hr = IDirectDraw_GetCaps(DirectDraw1, &ddcaps, NULL);
3851     ok(SUCCEEDED(hr), "DirectDraw_GetCaps failed: 0x%08x\n", hr);
3852     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3853     {
3854         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3855         return ;
3856     }
3857
3858     memset(&ddsd, 0, sizeof(ddsd));
3859     ddsd.dwSize = sizeof(ddsd);
3860     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3861     ddsd.dwWidth = 64;
3862     ddsd.dwHeight = 64;
3863     ddsd.ddsCaps.dwCaps = caps;
3864     memset(&ddsd2, 0, sizeof(ddsd2));
3865     ddsd2.dwSize = sizeof(ddsd2);
3866     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3867     ddsd2.dwWidth = 64;
3868     ddsd2.dwHeight = 64;
3869     ddsd2.ddsCaps.dwCaps = caps;
3870     memset(&created_ddsd, 0, sizeof(created_ddsd));
3871     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3872
3873     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
3874     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3875     if (surf != NULL)
3876     {
3877         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3878         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3879         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3880            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3881            expected_caps);
3882
3883         hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3884         /* Currently Wine only supports the creation of one Direct3D device
3885            for a given DirectDraw instance. It has been created already
3886            in D3D1_createObjects() - IID_IDirect3DRGBDevice */
3887         todo_wine ok(SUCCEEDED(hr), "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3888
3889         if (SUCCEEDED(hr))
3890             IDirect3DDevice_Release(d3dhal);
3891
3892         IDirectDrawSurface_Release(surf);
3893     }
3894
3895     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw2, (void **) &dd2);
3896     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3897
3898     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3899     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3900        DDERR_INVALIDCAPS, hr);
3901
3902     IDirectDraw2_Release(dd2);
3903
3904     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void **) &dd4);
3905     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3906
3907     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3908     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3909        DDERR_INVALIDCAPS, hr);
3910
3911     IDirectDraw4_Release(dd4);
3912
3913     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw7, (void **) &dd7);
3914     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3915
3916     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3917     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3918        DDERR_INVALIDCAPS, hr);
3919
3920     IDirectDraw7_Release(dd7);
3921 }
3922
3923 static void BackBuffer3DAttachmentTest(void)
3924 {
3925     HRESULT hr;
3926     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3927     DDSURFACEDESC ddsd;
3928     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3929
3930     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3931     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3932
3933     /* Perform attachment tests on a back-buffer */
3934     memset(&ddsd, 0, sizeof(ddsd));
3935     ddsd.dwSize = sizeof(ddsd);
3936     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3937     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3938     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3939     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3940     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface2, NULL);
3941     ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3942
3943     if (surface2 != NULL)
3944     {
3945         /* Try a single primary and a two back buffers */
3946         memset(&ddsd, 0, sizeof(ddsd));
3947         ddsd.dwSize = sizeof(ddsd);
3948         ddsd.dwFlags = DDSD_CAPS;
3949         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3950         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface1, NULL);
3951         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3952
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, &surface3, NULL);
3960         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3961
3962         /* This one has a different size */
3963         memset(&ddsd, 0, sizeof(ddsd));
3964         ddsd.dwSize = sizeof(ddsd);
3965         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3966         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3967         ddsd.dwWidth = 128;
3968         ddsd.dwHeight = 128;
3969         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface4, NULL);
3970         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3971
3972         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3973         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3974            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3975         if(SUCCEEDED(hr))
3976         {
3977             /* Try the reverse without detaching first */
3978             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3979             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3980             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3981             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3982         }
3983         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3984         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3985            "Attaching a front buffer to a back buffer returned %08x\n", hr);
3986         if(SUCCEEDED(hr))
3987         {
3988             /* Try to detach reversed */
3989             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3990             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3991             /* Now the proper detach */
3992             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3993             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3994         }
3995         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3996         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3997            "Attaching a back buffer to another back buffer returned %08x\n", hr);
3998         if(SUCCEEDED(hr))
3999         {
4000             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
4001             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
4002         }
4003         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4004         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
4005         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4006         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
4007
4008         IDirectDrawSurface_Release(surface4);
4009         IDirectDrawSurface_Release(surface3);
4010         IDirectDrawSurface_Release(surface2);
4011         IDirectDrawSurface_Release(surface1);
4012     }
4013
4014     hr =IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
4015     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
4016
4017     DestroyWindow(window);
4018 }
4019
4020 static void test_window_style(void)
4021 {
4022     LONG style, exstyle, tmp;
4023     RECT fullscreen_rect, r;
4024     IDirectDraw7 *ddraw7;
4025     HWND window;
4026     HRESULT hr;
4027     ULONG ref;
4028
4029     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
4030     if (FAILED(hr))
4031     {
4032         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4033         return;
4034     }
4035
4036     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
4037             0, 0, 100, 100, 0, 0, 0, 0);
4038
4039     style = GetWindowLongA(window, GWL_STYLE);
4040     exstyle = GetWindowLongA(window, GWL_EXSTYLE);
4041     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
4042
4043     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4044     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4045     if (FAILED(hr))
4046     {
4047         IDirectDraw7_Release(ddraw7);
4048         DestroyWindow(window);
4049         return;
4050     }
4051
4052     tmp = GetWindowLongA(window, GWL_STYLE);
4053     todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
4054     tmp = GetWindowLongA(window, GWL_EXSTYLE);
4055     todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
4056
4057     GetWindowRect(window, &r);
4058     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4059             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4060             r.left, r.top, r.right, r.bottom);
4061     GetClientRect(window, &r);
4062     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
4063
4064     ref = IDirectDraw7_Release(ddraw7);
4065     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4066
4067     DestroyWindow(window);
4068 }
4069
4070 static void test_redundant_mode_set(void)
4071 {
4072     DDSURFACEDESC2 surface_desc = {0};
4073     IDirectDraw7 *ddraw7;
4074     HWND window;
4075     HRESULT hr;
4076     RECT r, s;
4077     ULONG ref;
4078
4079     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
4080     if (FAILED(hr))
4081     {
4082         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4083         return;
4084     }
4085
4086     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
4087             0, 0, 100, 100, 0, 0, 0, 0);
4088
4089     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4090     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4091     if (FAILED(hr))
4092     {
4093         IDirectDraw7_Release(ddraw7);
4094         DestroyWindow(window);
4095         return;
4096     }
4097
4098     surface_desc.dwSize = sizeof(surface_desc);
4099     hr = IDirectDraw7_GetDisplayMode(ddraw7, &surface_desc);
4100     ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
4101
4102     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
4103             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
4104     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4105
4106     GetWindowRect(window, &r);
4107     r.right /= 2;
4108     r.bottom /= 2;
4109     SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
4110     GetWindowRect(window, &s);
4111     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4112             r.left, r.top, r.right, r.bottom,
4113             s.left, s.top, s.right, s.bottom);
4114
4115     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
4116             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
4117     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4118
4119     GetWindowRect(window, &s);
4120     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4121             r.left, r.top, r.right, r.bottom,
4122             s.left, s.top, s.right, s.bottom);
4123
4124     ref = IDirectDraw7_Release(ddraw7);
4125     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4126
4127     DestroyWindow(window);
4128 }
4129
4130 static SIZE screen_size;
4131
4132 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4133 {
4134     if (message == WM_SIZE)
4135     {
4136         screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
4137         screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
4138     }
4139
4140     return test_proc(hwnd, message, wparam, lparam);
4141 }
4142
4143 static void test_coop_level_mode_set(void)
4144 {
4145     RECT fullscreen_rect, r, s;
4146     IDirectDraw7 *ddraw7;
4147     WNDCLASSA wc = {0};
4148     HWND window;
4149     HRESULT hr;
4150     ULONG ref;
4151
4152     static const UINT exclusive_messages[] =
4153     {
4154         WM_WINDOWPOSCHANGING,
4155         WM_WINDOWPOSCHANGED,
4156         WM_SIZE,
4157         /* WM_DISPLAYCHANGE,    This message is received after WM_SIZE on native. However, the
4158          *                      more important behaviour is that at the time the WM_SIZE message
4159          *                      is processed SM_CXSCREEN and SM_CYSCREEN already have the new
4160          *                      values. */
4161         0,
4162     };
4163
4164     static const UINT normal_messages[] =
4165     {
4166         WM_DISPLAYCHANGE,
4167         0,
4168     };
4169
4170     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
4171     if (FAILED(hr))
4172     {
4173         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4174         return;
4175     }
4176
4177     wc.lpfnWndProc = mode_set_proc;
4178     wc.lpszClassName = "d3d7_test_wndproc_wc";
4179     ok(RegisterClassA(&wc), "Failed to register window class.\n");
4180
4181     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
4182             0, 0, 100, 100, 0, 0, 0, 0);
4183
4184     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
4185     SetRect(&s, 0, 0, 640, 480);
4186
4187     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4188     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4189     if (FAILED(hr))
4190     {
4191         IDirectDraw7_Release(ddraw7);
4192         goto done;
4193     }
4194
4195     GetWindowRect(window, &r);
4196     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4197             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4198             r.left, r.top, r.right, r.bottom);
4199
4200     expect_messages = exclusive_messages;
4201     screen_size.cx = 0;
4202     screen_size.cy = 0;
4203
4204     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4205     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4206
4207     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4208     expect_messages = NULL;
4209     ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
4210             "Expected screen size %ux%u, got %ux%u.\n",
4211             s.right, s.bottom, screen_size.cx, screen_size.cy);
4212
4213     GetWindowRect(window, &r);
4214     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4215             s.left, s.top, s.right, s.bottom,
4216             r.left, r.top, r.right, r.bottom);
4217
4218     expect_messages = exclusive_messages;
4219     screen_size.cx = 0;
4220     screen_size.cy = 0;
4221
4222     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4223     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4224
4225     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4226     expect_messages = NULL;
4227     ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
4228             "Expected screen size %ux%u, got %ux%u.\n",
4229             fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
4230
4231     GetWindowRect(window, &r);
4232     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4233             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4234             r.left, r.top, r.right, r.bottom);
4235
4236     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4237     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4238
4239     GetWindowRect(window, &r);
4240     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4241             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4242             r.left, r.top, r.right, r.bottom);
4243
4244     expect_messages = normal_messages;
4245     screen_size.cx = 0;
4246     screen_size.cy = 0;
4247
4248     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4249     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4250
4251     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4252     expect_messages = NULL;
4253     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4254
4255     GetWindowRect(window, &r);
4256     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4257             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4258             r.left, r.top, r.right, r.bottom);
4259
4260     expect_messages = normal_messages;
4261     screen_size.cx = 0;
4262     screen_size.cy = 0;
4263
4264     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4265     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4266
4267     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4268     expect_messages = NULL;
4269     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4270
4271     GetWindowRect(window, &r);
4272     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4273             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4274             r.left, r.top, r.right, r.bottom);
4275
4276     /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
4277      * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
4278      * not DDSCL_FULLSCREEN. */
4279     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
4280     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4281
4282     GetWindowRect(window, &r);
4283     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4284             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4285             r.left, r.top, r.right, r.bottom);
4286
4287     expect_messages = normal_messages;
4288     screen_size.cx = 0;
4289     screen_size.cy = 0;
4290
4291     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4292     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4293
4294     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4295     expect_messages = NULL;
4296     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", 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     expect_messages = normal_messages;
4304     screen_size.cx = 0;
4305     screen_size.cy = 0;
4306
4307     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4308     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4309
4310     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
4311     expect_messages = NULL;
4312     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
4313
4314     GetWindowRect(window, &r);
4315     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4316             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4317             r.left, r.top, r.right, r.bottom);
4318
4319     ref = IDirectDraw7_Release(ddraw7);
4320     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4321
4322     GetWindowRect(window, &r);
4323     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4324             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4325             r.left, r.top, r.right, r.bottom);
4326
4327 done:
4328     expect_messages = NULL;
4329     DestroyWindow(window);
4330     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
4331 }
4332
4333 static void dump_format(const DDPIXELFORMAT *fmt)
4334 {
4335     trace("dwFlags %08x, FourCC %08x, dwZBufferBitDepth %u, stencil %08x\n", fmt->dwFlags, fmt->dwFourCC,
4336           U1(*fmt).dwZBufferBitDepth, U2(*fmt).dwStencilBitDepth);
4337     trace("dwZBitMask %08x, dwStencilBitMask %08x, dwRGBZBitMask %08x\n", U3(*fmt).dwZBitMask,
4338           U4(*fmt).dwStencilBitMask, U5(*fmt).dwRGBZBitMask);
4339 }
4340
4341 static HRESULT WINAPI enum_z_fmt_cb(DDPIXELFORMAT *fmt, void *ctx)
4342 {
4343     static const DDPIXELFORMAT formats[] =
4344     {
4345         {
4346             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4347             {16}, {0}, {0x0000ffff}, {0x00000000}, {0x00000000}
4348         },
4349         {
4350             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4351             {32}, {0}, {0xffffff00}, {0x00000000}, {0x00000000}
4352         },
4353         {
4354             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
4355             {32}, {8}, {0xffffff00}, {0x000000ff}, {0x00000000}
4356         },
4357         {
4358             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4359             {32}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4360         },
4361         {
4362             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
4363             {32}, {8}, {0x00ffffff}, {0xff000000}, {0x00000000}
4364         },
4365         {
4366             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4367             {24}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4368         },
4369         {
4370             sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4371             {32}, {0}, {0xffffffff}, {0x00000000}, {0x00000000}
4372         },
4373     };
4374     unsigned int *count = ctx, i, expected_pitch;
4375     DDSURFACEDESC2 ddsd;
4376     IDirectDrawSurface7 *surface;
4377     HRESULT hr;
4378     (*count)++;
4379
4380     memset(&ddsd, 0, sizeof(ddsd));
4381     ddsd.dwSize = sizeof(ddsd);
4382     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4383     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4384     U4(ddsd).ddpfPixelFormat = *fmt;
4385     ddsd.dwWidth = 1024;
4386     ddsd.dwHeight = 1024;
4387     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface, NULL);
4388     ok(SUCCEEDED(hr), "IDirectDraw7_CreateSurface failed, hr %#x.\n", hr);
4389     memset(&ddsd, 0, sizeof(ddsd));
4390     ddsd.dwSize = sizeof(ddsd);
4391     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4392     ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc failed, hr %#x.\n", hr);
4393     IDirectDrawSurface7_Release(surface);
4394
4395     ok(ddsd.dwFlags & DDSD_PIXELFORMAT, "DDSD_PIXELFORMAT is not set\n");
4396     ok(!(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH), "DDSD_ZBUFFERBITDEPTH is set\n");
4397
4398     /* 24 bit unpadded depth buffers are actually padded(Geforce 9600, Win7,
4399      * Radeon 9000M WinXP) */
4400     if (U1(*fmt).dwZBufferBitDepth == 24) expected_pitch = ddsd.dwWidth * 4;
4401     else expected_pitch = ddsd.dwWidth * U1(*fmt).dwZBufferBitDepth / 8;
4402
4403     /* Some formats(16 bit depth without stencil) return pitch 0
4404      *
4405      * The Radeon X1600 Catalyst 10.2 Windows XP driver returns an otherwise sane
4406      * pitch with an extra 128 bytes, regardless of the format and width */
4407     if (U1(ddsd).lPitch != 0 && U1(ddsd).lPitch != expected_pitch
4408             && !broken(U1(ddsd).lPitch == expected_pitch + 128))
4409     {
4410         ok(0, "Z buffer pitch is %u, expected %u\n", U1(ddsd).lPitch, expected_pitch);
4411         dump_format(fmt);
4412     }
4413
4414     for (i = 0; i < (sizeof(formats)/sizeof(*formats)); i++)
4415     {
4416         if (memcmp(&formats[i], fmt, fmt->dwSize) == 0) return DDENUMRET_OK;
4417     }
4418
4419     ok(0, "Unexpected Z format enumerated\n");
4420     dump_format(fmt);
4421
4422     return DDENUMRET_OK;
4423 }
4424
4425 static void z_format_test(void)
4426 {
4427     unsigned int count = 0;
4428     HRESULT hr;
4429
4430     hr = IDirect3D7_EnumZBufferFormats(lpD3D, &IID_IDirect3DHALDevice, enum_z_fmt_cb, &count);
4431     if (hr == DDERR_NOZBUFFERHW)
4432     {
4433         skip("Z buffers not supported, skipping Z buffer format test\n");
4434         return;
4435     }
4436
4437     ok(SUCCEEDED(hr), "IDirect3D7_EnumZBufferFormats failed, hr %#x.\n", hr);
4438     ok(count, "Expected at least one supported Z Buffer format\n");
4439 }
4440
4441 static void test_initialize(void)
4442 {
4443     IDirectDraw7 *ddraw7;
4444     IDirectDraw4 *ddraw4;
4445     IDirectDraw2 *ddraw2;
4446     IDirectDraw *ddraw1;
4447     IDirect3D *d3d1;
4448     HRESULT hr;
4449
4450     /* IDirectDraw */
4451     if (FAILED(hr = DirectDrawCreate(NULL, &ddraw1, NULL)))
4452     {
4453         skip("Failed to create IDirectDraw object (%#x), skipping tests.\n", hr);
4454         return;
4455     }
4456
4457     hr = IDirectDraw_Initialize(ddraw1, NULL);
4458     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4459     IDirectDraw_Release(ddraw1);
4460
4461     CoInitialize(NULL);
4462     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw1);
4463     ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
4464     hr = IDirectDraw_Initialize(ddraw1, NULL);
4465     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4466     hr = IDirectDraw_Initialize(ddraw1, NULL);
4467     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4468     IDirectDraw_Release(ddraw1);
4469     CoUninitialize();
4470
4471     hr = DirectDrawCreate(NULL, &ddraw1, NULL);
4472     ok(SUCCEEDED(hr), "Failed to create IDirectDraw object, hr %#x.\n", hr);
4473
4474     /* IDirectDraw2 */
4475     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2)))
4476     {
4477         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4478         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4479         IDirectDraw2_Release(ddraw2);
4480
4481         CoInitialize(NULL);
4482         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw2);
4483         ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
4484         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4485         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4486         hr = IDirectDraw2_Initialize(ddraw2, NULL);
4487         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4488         IDirectDraw2_Release(ddraw2);
4489         CoUninitialize();
4490     }
4491     else skip("Failed to query IDirectDraw2 interface, skipping tests.\n");
4492
4493     /* IDirectDraw4 */
4494     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4)))
4495     {
4496         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4497         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4498         IDirectDraw4_Release(ddraw4);
4499
4500         CoInitialize(NULL);
4501         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw4);
4502         ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
4503         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4504         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4505         hr = IDirectDraw4_Initialize(ddraw4, NULL);
4506         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4507         IDirectDraw4_Release(ddraw4);
4508         CoUninitialize();
4509     }
4510     else skip("Failed to query IDirectDraw4 interface, skipping tests.\n");
4511
4512     /* IDirect3D */
4513     if (SUCCEEDED(IDirectDraw_QueryInterface(ddraw1, &IID_IDirect3D, (void **)&d3d1)))
4514     {
4515         IDirectDraw *ddraw;
4516
4517         hr = IDirect3D_Initialize(d3d1, NULL);
4518         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4519         IDirect3D_Release(d3d1);
4520
4521         if (0) /* This crashes on the W2KPROSP4 testbot. */
4522         {
4523             CoInitialize(NULL);
4524             hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d1);
4525             ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
4526             CoUninitialize();
4527         }
4528
4529         CoInitialize(NULL);
4530         hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
4531         ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
4532         hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d1);
4533         ok(SUCCEEDED(hr), "Failed to query IDirect3D interface, hr %#x.\n", hr);
4534         IDirectDraw_Release(ddraw);
4535         /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
4536         hr = IDirect3D_Initialize(d3d1, NULL);
4537         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4538         hr = IDirectDraw_Initialize(ddraw, NULL);
4539         ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4540         hr = IDirectDraw_Initialize(ddraw, NULL);
4541         ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4542         IDirect3D_Release(d3d1);
4543         CoUninitialize();
4544     }
4545     else skip("Failed to query IDirect3D interface, skipping tests.\n");
4546
4547     IDirectDraw_Release(ddraw1);
4548
4549     /* IDirectDraw7 */
4550     if (FAILED(hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL)))
4551     {
4552         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4553         return;
4554     }
4555     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4556     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4557     IDirectDraw7_Release(ddraw7);
4558
4559     CoInitialize(NULL);
4560     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw7);
4561     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
4562     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4563     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4564     hr = IDirectDraw7_Initialize(ddraw7, NULL);
4565     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4566     IDirectDraw7_Release(ddraw7);
4567     CoUninitialize();
4568 }
4569
4570 START_TEST(d3d)
4571 {
4572     init_function_pointers();
4573     if(!pDirectDrawCreateEx) {
4574         win_skip("function DirectDrawCreateEx not available\n");
4575         return;
4576     }
4577
4578     if(!CreateDirect3D()) {
4579         skip("Skipping d3d7 tests\n");
4580     } else {
4581         LightTest();
4582         ProcessVerticesTest();
4583         StateTest();
4584         SceneTest();
4585         LimitTest();
4586         D3D7EnumTest();
4587         D3D7EnumLifetimeTest();
4588         SetMaterialTest();
4589         ComputeSphereVisibility();
4590         CapsTest();
4591         VertexBufferDescTest();
4592         D3D7_OldRenderStateTest();
4593         DeviceLoadTest();
4594         SetRenderTargetTest();
4595         VertexBufferLockRest();
4596         z_format_test();
4597         ReleaseDirect3D();
4598     }
4599
4600     if (!D3D1_createObjects()) {
4601         skip("Skipping d3d1 tests\n");
4602     } else {
4603         Direct3D1Test();
4604         TextureLoadTest();
4605         ViewportTest();
4606         FindDevice();
4607         BackBuffer3DCreateSurfaceTest();
4608         BackBuffer3DAttachmentTest();
4609         D3D1_releaseObjects();
4610     }
4611
4612     test_wndproc();
4613     test_window_style();
4614     test_redundant_mode_set();
4615     test_coop_level_mode_set();
4616     test_initialize();
4617 }