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