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