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