ddraw: Fix SetRenderTarget behaviour on failure.
[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, *temprt;
3264     D3DVIEWPORT7 vp;
3265     DDSURFACEDESC2 ddsd, ddsd2;
3266     DWORD stateblock;
3267     ULONG refcount;
3268
3269     memset(&ddsd, 0, sizeof(ddsd));
3270     ddsd.dwSize = sizeof(ddsd);
3271     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3272     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
3273     ddsd.dwWidth = 64;
3274     ddsd.dwHeight = 64;
3275
3276     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
3277     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3278     if(FAILED(hr))
3279     {
3280         skip("Skipping SetRenderTarget test\n");
3281         return;
3282     }
3283
3284     memset(&ddsd2, 0, sizeof(ddsd2));
3285     ddsd2.dwSize = sizeof(ddsd2);
3286     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3287     ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER;
3288     ddsd2.dwWidth = 64;
3289     ddsd2.dwHeight = 64;
3290     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
3291     U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3292     U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3293     U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3294
3295     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd2, &failrt, NULL);
3296     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3297
3298     memset(&vp, 0, sizeof(vp));
3299     vp.dwX = 10;
3300     vp.dwY = 10;
3301     vp.dwWidth = 246;
3302     vp.dwHeight = 246;
3303     vp.dvMinZ = 0.25;
3304     vp.dvMaxZ = 0.75;
3305     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3306     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3307
3308     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3309     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3310
3311     refcount = getRefcount((IUnknown*) oldrt);
3312     todo_wine ok(refcount == 3, "Refcount should be 3, returned is %d\n", refcount);
3313
3314     refcount = getRefcount((IUnknown*) failrt);
3315     ok(refcount == 1, "Refcount should be 1, returned is %d\n", refcount);
3316
3317     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, failrt, 0);
3318     ok(hr != D3D_OK, "IDirect3DDevice7_SetRenderTarget succeeded\n");
3319
3320     refcount = getRefcount((IUnknown*) oldrt);
3321     todo_wine ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3322
3323     refcount = getRefcount((IUnknown*) failrt);
3324     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3325
3326     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &temprt);
3327     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3328     ok(failrt == temprt, "Wrong iface returned\n");
3329
3330     refcount = getRefcount((IUnknown*) failrt);
3331     ok(refcount == 3, "Refcount should be 3, returned is %d\n", refcount);
3332
3333     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3334     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3335
3336     refcount = getRefcount((IUnknown*) failrt);
3337     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
3338
3339     memset(&vp, 0xff, sizeof(vp));
3340     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3341     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3342     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3343     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3344     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3345     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3346     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.25\n", vp.dvMinZ);
3347     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.75\n", vp.dvMaxZ);
3348
3349     memset(&vp, 0, sizeof(vp));
3350     vp.dwX = 0;
3351     vp.dwY = 0;
3352     vp.dwWidth = 64;
3353     vp.dwHeight = 64;
3354     vp.dvMinZ = 0.0;
3355     vp.dvMaxZ = 1.0;
3356     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3357     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3358
3359     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3360     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3361     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3362     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3363
3364     /* Check this twice, before and after ending the stateblock */
3365     memset(&vp, 0xff, sizeof(vp));
3366     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3367     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3368     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3369     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3370     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3371     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3372     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3373     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3374
3375     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3376     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3377
3378     memset(&vp, 0xff, sizeof(vp));
3379     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3380     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3381     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3382     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3383     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3384     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3385     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3386     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3387
3388     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3389     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3390
3391     memset(&vp, 0, sizeof(vp));
3392     vp.dwX = 0;
3393     vp.dwY = 0;
3394     vp.dwWidth = 256;
3395     vp.dwHeight = 256;
3396     vp.dvMinZ = 0.0;
3397     vp.dvMaxZ = 0.0;
3398     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3399     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3400
3401     IDirectDrawSurface7_Release(oldrt);
3402     IDirectDrawSurface7_Release(newrt);
3403     IDirectDrawSurface7_Release(failrt);
3404     IDirectDrawSurface7_Release(failrt);
3405 }
3406
3407 static const UINT *expect_messages;
3408
3409 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3410 {
3411     if (expect_messages && message == *expect_messages) ++expect_messages;
3412
3413     return DefWindowProcA(hwnd, message, wparam, lparam);
3414 }
3415
3416 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
3417  * interface. This prevents subsequent SetCooperativeLevel() calls on a
3418  * different window from failing with DDERR_HWNDALREADYSET. */
3419 static void fix_wndproc(HWND window, LONG_PTR proc)
3420 {
3421     IDirectDraw7 *ddraw7;
3422     HRESULT hr;
3423
3424     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3425     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 object, hr %#x.\n", hr);
3426     if (FAILED(hr)) return;
3427
3428     SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
3429     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3430     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3431     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3432     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3433
3434     IDirectDraw7_Release(ddraw7);
3435 }
3436
3437 static void test_wndproc(void)
3438 {
3439     LONG_PTR proc, ddraw_proc;
3440     IDirectDraw7 *ddraw7;
3441     WNDCLASSA wc = {0};
3442     HWND window;
3443     HRESULT hr;
3444     ULONG ref;
3445
3446     static const UINT messages[] =
3447     {
3448         WM_WINDOWPOSCHANGING,
3449         WM_MOVE,
3450         WM_SIZE,
3451         WM_WINDOWPOSCHANGING,
3452         WM_ACTIVATE,
3453         WM_SETFOCUS,
3454         0,
3455     };
3456
3457     /* DDSCL_EXCLUSIVE replaces the window's window proc. */
3458     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3459     if (FAILED(hr))
3460     {
3461         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3462         return;
3463     }
3464
3465     wc.lpfnWndProc = test_proc;
3466     wc.lpszClassName = "d3d7_test_wndproc_wc";
3467     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3468
3469     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test",
3470             WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3471
3472     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3473     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3474             (LONG_PTR)test_proc, proc);
3475
3476     expect_messages = messages;
3477
3478     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3479     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3480     if (FAILED(hr))
3481     {
3482         IDirectDraw7_Release(ddraw7);
3483         goto done;
3484     }
3485
3486     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3487     expect_messages = NULL;
3488
3489     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3490     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3491             (LONG_PTR)test_proc, proc);
3492
3493     ref = IDirectDraw7_Release(ddraw7);
3494     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3495
3496     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3497     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3498             (LONG_PTR)test_proc, proc);
3499
3500     /* DDSCL_NORMAL doesn't. */
3501     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3502     if (FAILED(hr))
3503     {
3504         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3505         return;
3506     }
3507
3508     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3509     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3510             (LONG_PTR)test_proc, proc);
3511
3512     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3513     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3514     if (FAILED(hr))
3515     {
3516         IDirectDraw7_Release(ddraw7);
3517         goto done;
3518     }
3519
3520     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3521     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3522             (LONG_PTR)test_proc, proc);
3523
3524     ref = IDirectDraw7_Release(ddraw7);
3525     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3526
3527     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3528     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3529             (LONG_PTR)test_proc, proc);
3530
3531     /* The original window proc is only restored by ddraw if the current
3532      * window proc matches the one ddraw set. This also affects switching
3533      * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
3534     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3535     if (FAILED(hr))
3536     {
3537         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3538         return;
3539     }
3540
3541     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3542     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3543             (LONG_PTR)test_proc, proc);
3544
3545     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3546     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3547     if (FAILED(hr))
3548     {
3549         IDirectDraw7_Release(ddraw7);
3550         goto done;
3551     }
3552
3553     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3554     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3555             (LONG_PTR)test_proc, proc);
3556     ddraw_proc = proc;
3557
3558     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3559     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3560     if (FAILED(hr))
3561     {
3562         IDirectDraw7_Release(ddraw7);
3563         goto done;
3564     }
3565
3566     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3567     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3568             (LONG_PTR)test_proc, proc);
3569
3570     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3571     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3572     if (FAILED(hr))
3573     {
3574         IDirectDraw7_Release(ddraw7);
3575         goto done;
3576     }
3577
3578     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3579     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3580             (LONG_PTR)test_proc, proc);
3581
3582     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3583     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3584     if (FAILED(hr))
3585     {
3586         IDirectDraw7_Release(ddraw7);
3587         goto done;
3588     }
3589
3590     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3591     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3592             (LONG_PTR)DefWindowProcA, proc);
3593
3594     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3595     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3596     if (FAILED(hr))
3597     {
3598         IDirectDraw7_Release(ddraw7);
3599         goto done;
3600     }
3601
3602     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
3603     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3604             (LONG_PTR)DefWindowProcA, proc);
3605
3606     ref = IDirectDraw7_Release(ddraw7);
3607     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3608
3609     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3610     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3611             (LONG_PTR)test_proc, proc);
3612
3613     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3614     if (FAILED(hr))
3615     {
3616         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3617         return;
3618     }
3619
3620     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3621     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3622             (LONG_PTR)test_proc, proc);
3623
3624     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3625     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3626     if (FAILED(hr))
3627     {
3628         IDirectDraw7_Release(ddraw7);
3629         goto done;
3630     }
3631
3632     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3633     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3634             (LONG_PTR)test_proc, proc);
3635
3636     ref = IDirectDraw7_Release(ddraw7);
3637     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3638
3639     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3640     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3641             (LONG_PTR)DefWindowProcA, proc);
3642
3643 done:
3644     fix_wndproc(window, (LONG_PTR)test_proc);
3645     expect_messages = NULL;
3646     DestroyWindow(window);
3647     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
3648 }
3649
3650 static void VertexBufferLockRest(void)
3651 {
3652     D3DVERTEXBUFFERDESC desc;
3653     IDirect3DVertexBuffer7 *buffer;
3654     HRESULT hr;
3655     unsigned int i;
3656     void *data;
3657     const struct
3658     {
3659         DWORD flags;
3660         const char *debug_string;
3661         HRESULT result;
3662     }
3663     test_data[] =
3664     {
3665         {0,                                         "(none)",                                       D3D_OK },
3666         {DDLOCK_WAIT,                               "DDLOCK_WAIT",                                  D3D_OK },
3667         {DDLOCK_EVENT,                              "DDLOCK_EVENT",                                 D3D_OK },
3668         {DDLOCK_READONLY,                           "DDLOCK_READONLY",                              D3D_OK },
3669         {DDLOCK_WRITEONLY,                          "DDLOCK_WRITEONLY",                             D3D_OK },
3670         {DDLOCK_NOSYSLOCK,                          "DDLOCK_NOSYSLOCK",                             D3D_OK },
3671         {DDLOCK_NOOVERWRITE,                        "DDLOCK_NOOVERWRITE",                           D3D_OK },
3672         {DDLOCK_DISCARDCONTENTS,                    "DDLOCK_DISCARDCONTENTS",                       D3D_OK },
3673
3674         {DDLOCK_READONLY | DDLOCK_WRITEONLY,        "DDLOCK_READONLY | DDLOCK_WRITEONLY",           D3D_OK },
3675         {DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS,  "DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS",     D3D_OK },
3676         {0xdeadbeef,                                "0xdeadbeef",                                   D3D_OK },
3677     };
3678
3679     memset(&desc, 0 , sizeof(desc));
3680     desc.dwSize = sizeof(desc);
3681     desc.dwCaps = 0;
3682     desc.dwFVF = D3DFVF_XYZ;
3683     desc.dwNumVertices = 64;
3684     hr = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &buffer, 0);
3685     ok(hr == D3D_OK, "IDirect3D7_CreateVertexBuffer failed, 0x%08x\n", hr);
3686
3687     for(i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
3688     {
3689         hr = IDirect3DVertexBuffer7_Lock(buffer, test_data[i].flags, &data, NULL);
3690         ok(hr == test_data[i].result, "Lock flags %s returned 0x%08x, expected 0x%08x\n",
3691             test_data[i].debug_string, hr, test_data[i].result);
3692         if(SUCCEEDED(hr))
3693         {
3694             ok(data != NULL, "The data pointer returned by Lock is NULL\n");
3695             hr = IDirect3DVertexBuffer7_Unlock(buffer);
3696             ok(hr == D3D_OK, "IDirect3DVertexBuffer7_Unlock failed, 0x%08x\n", hr);
3697         }
3698     }
3699
3700     IDirect3DVertexBuffer7_Release(buffer);
3701 }
3702
3703 static void FindDevice(void)
3704 {
3705     static const struct
3706     {
3707         const GUID *guid;
3708         int todo;
3709     } deviceGUIDs[] =
3710     {
3711         {&IID_IDirect3DRampDevice, 1},
3712         {&IID_IDirect3DRGBDevice},
3713     };
3714
3715     static const GUID *nonexistent_deviceGUIDs[] = {&IID_IDirect3DMMXDevice,
3716                                                     &IID_IDirect3DRefDevice,
3717                                                     &IID_IDirect3DTnLHalDevice,
3718                                                     &IID_IDirect3DNullDevice};
3719
3720     D3DFINDDEVICESEARCH search = {0};
3721     D3DFINDDEVICERESULT result = {0};
3722     IDirect3DDevice *d3dhal;
3723     HRESULT hr;
3724     int i;
3725
3726     /* Test invalid parameters. */
3727     hr = IDirect3D_FindDevice(Direct3D1, NULL, NULL);
3728     ok(hr == DDERR_INVALIDPARAMS,
3729        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3730
3731     hr = IDirect3D_FindDevice(Direct3D1, NULL, &result);
3732     ok(hr == DDERR_INVALIDPARAMS,
3733        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3734
3735     hr = IDirect3D_FindDevice(Direct3D1, &search, NULL);
3736     ok(hr == DDERR_INVALIDPARAMS,
3737        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3738
3739     search.dwSize = 0;
3740     result.dwSize = 0;
3741
3742     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3743     ok(hr == DDERR_INVALIDPARAMS,
3744        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3745
3746     search.dwSize = sizeof(search) + 1;
3747     result.dwSize = sizeof(result) + 1;
3748
3749     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3750     ok(hr == DDERR_INVALIDPARAMS,
3751        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3752
3753     /* Specifying no flags is permitted. */
3754     search.dwSize = sizeof(search);
3755     search.dwFlags = 0;
3756     result.dwSize = sizeof(result);
3757
3758     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3759     ok(hr == D3D_OK,
3760        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3761
3762     /* Try an arbitrary non-device GUID. */
3763     search.dwSize = sizeof(search);
3764     search.dwFlags = D3DFDS_GUID;
3765     search.guid = IID_IDirect3D;
3766     result.dwSize = sizeof(result);
3767
3768     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3769     ok(hr == DDERR_NOTFOUND,
3770        "Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", hr);
3771
3772     /* These GUIDs appear to be never present. */
3773     for (i = 0; i < sizeof(nonexistent_deviceGUIDs)/sizeof(nonexistent_deviceGUIDs[0]); i++)
3774     {
3775         search.dwSize = sizeof(search);
3776         search.dwFlags = D3DFDS_GUID;
3777         search.guid = *nonexistent_deviceGUIDs[i];
3778         result.dwSize = sizeof(result);
3779
3780         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3781         ok(hr == DDERR_NOTFOUND,
3782            "[%d] Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", i, hr);
3783     }
3784
3785     /* The HAL device can only be enumerated if hardware acceleration is present. */
3786     search.dwSize = sizeof(search);
3787     search.dwFlags = D3DFDS_GUID;
3788     search.guid = IID_IDirect3DHALDevice;
3789     result.dwSize = sizeof(result);
3790
3791     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3792     trace("IDirect3D::FindDevice returned 0x%08x for the HAL device GUID\n", hr);
3793     if (SUCCEEDED(hr))
3794     {
3795         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3796         /* Currently Wine only supports the creation of one Direct3D device
3797          * for a given DirectDraw instance. */
3798         todo_wine
3799         ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
3800            "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3801
3802         if (SUCCEEDED(hr))
3803             IDirect3DDevice_Release(d3dhal);
3804     }
3805     else
3806     {
3807         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3808         ok(FAILED(hr), "Expected IDirectDrawSurface::QueryInterface to fail, got 0x%08x\n", hr);
3809
3810         if (SUCCEEDED(hr))
3811             IDirect3DDevice_Release(d3dhal);
3812     }
3813
3814     /* These GUIDs appear to be always present. */
3815     for (i = 0; i < sizeof(deviceGUIDs)/sizeof(deviceGUIDs[0]); i++)
3816     {
3817         search.dwSize = sizeof(search);
3818         search.dwFlags = D3DFDS_GUID;
3819         search.guid = *deviceGUIDs[i].guid;
3820         result.dwSize = sizeof(result);
3821
3822         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3823
3824         if (deviceGUIDs[i].todo)
3825         {
3826             todo_wine
3827             ok(hr == D3D_OK,
3828                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3829         }
3830         else
3831         {
3832             ok(hr == D3D_OK,
3833                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3834         }
3835     }
3836
3837     /* Curiously the color model criteria seem to be ignored. */
3838     search.dwSize = sizeof(search);
3839     search.dwFlags = D3DFDS_COLORMODEL;
3840     search.dcmColorModel = 0xdeadbeef;
3841     result.dwSize = sizeof(result);
3842
3843     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3844     todo_wine
3845     ok(hr == D3D_OK,
3846        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3847 }
3848
3849 static void BackBuffer3DCreateSurfaceTest(void)
3850 {
3851     DDSURFACEDESC ddsd;
3852     DDSURFACEDESC created_ddsd;
3853     DDSURFACEDESC2 ddsd2;
3854     IDirectDrawSurface *surf;
3855     IDirectDrawSurface4 *surf4;
3856     IDirectDrawSurface7 *surf7;
3857     HRESULT hr;
3858     IDirectDraw2 *dd2;
3859     IDirectDraw4 *dd4;
3860     IDirectDraw7 *dd7;
3861     DDCAPS ddcaps;
3862     IDirect3DDevice *d3dhal;
3863
3864     const DWORD caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3865     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3866
3867     memset(&ddcaps, 0, sizeof(ddcaps));
3868     ddcaps.dwSize = sizeof(DDCAPS);
3869     hr = IDirectDraw_GetCaps(DirectDraw1, &ddcaps, NULL);
3870     ok(SUCCEEDED(hr), "DirectDraw_GetCaps failed: 0x%08x\n", hr);
3871     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3872     {
3873         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3874         return ;
3875     }
3876
3877     memset(&ddsd, 0, sizeof(ddsd));
3878     ddsd.dwSize = sizeof(ddsd);
3879     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3880     ddsd.dwWidth = 64;
3881     ddsd.dwHeight = 64;
3882     ddsd.ddsCaps.dwCaps = caps;
3883     memset(&ddsd2, 0, sizeof(ddsd2));
3884     ddsd2.dwSize = sizeof(ddsd2);
3885     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3886     ddsd2.dwWidth = 64;
3887     ddsd2.dwHeight = 64;
3888     ddsd2.ddsCaps.dwCaps = caps;
3889     memset(&created_ddsd, 0, sizeof(created_ddsd));
3890     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3891
3892     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
3893     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3894     if (surf != NULL)
3895     {
3896         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3897         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3898         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3899            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3900            expected_caps);
3901
3902         hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3903         /* Currently Wine only supports the creation of one Direct3D device
3904            for a given DirectDraw instance. It has been created already
3905            in D3D1_createObjects() - IID_IDirect3DRGBDevice */
3906         todo_wine ok(SUCCEEDED(hr), "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3907
3908         if (SUCCEEDED(hr))
3909             IDirect3DDevice_Release(d3dhal);
3910
3911         IDirectDrawSurface_Release(surf);
3912     }
3913
3914     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw2, (void **) &dd2);
3915     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3916
3917     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3918     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3919        DDERR_INVALIDCAPS, hr);
3920
3921     IDirectDraw2_Release(dd2);
3922
3923     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void **) &dd4);
3924     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3925
3926     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3927     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3928        DDERR_INVALIDCAPS, hr);
3929
3930     IDirectDraw4_Release(dd4);
3931
3932     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw7, (void **) &dd7);
3933     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3934
3935     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3936     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3937        DDERR_INVALIDCAPS, hr);
3938
3939     IDirectDraw7_Release(dd7);
3940 }
3941
3942 static void BackBuffer3DAttachmentTest(void)
3943 {
3944     HRESULT hr;
3945     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3946     DDSURFACEDESC ddsd;
3947     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3948
3949     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3950     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3951
3952     /* Perform attachment tests on a back-buffer */
3953     memset(&ddsd, 0, sizeof(ddsd));
3954     ddsd.dwSize = sizeof(ddsd);
3955     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3956     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3957     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3958     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3959     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface2, NULL);
3960     ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3961
3962     if (surface2 != NULL)
3963     {
3964         /* Try a single primary and a two back buffers */
3965         memset(&ddsd, 0, sizeof(ddsd));
3966         ddsd.dwSize = sizeof(ddsd);
3967         ddsd.dwFlags = DDSD_CAPS;
3968         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3969         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface1, NULL);
3970         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3971
3972         memset(&ddsd, 0, sizeof(ddsd));
3973         ddsd.dwSize = sizeof(ddsd);
3974         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3975         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3976         ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3977         ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3978         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface3, NULL);
3979         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3980
3981         /* This one has a different size */
3982         memset(&ddsd, 0, sizeof(ddsd));
3983         ddsd.dwSize = sizeof(ddsd);
3984         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3985         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3986         ddsd.dwWidth = 128;
3987         ddsd.dwHeight = 128;
3988         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface4, NULL);
3989         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3990
3991         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3992         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3993            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3994         if(SUCCEEDED(hr))
3995         {
3996             /* Try the reverse without detaching first */
3997             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3998             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3999             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4000             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
4001         }
4002         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4003         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
4004            "Attaching a front buffer to a back buffer returned %08x\n", hr);
4005         if(SUCCEEDED(hr))
4006         {
4007             /* Try to detach reversed */
4008             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4009             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
4010             /* Now the proper detach */
4011             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
4012             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
4013         }
4014         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
4015         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
4016            "Attaching a back buffer to another back buffer returned %08x\n", hr);
4017         if(SUCCEEDED(hr))
4018         {
4019             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
4020             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
4021         }
4022         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4023         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
4024         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4025         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
4026
4027         IDirectDrawSurface_Release(surface4);
4028         IDirectDrawSurface_Release(surface3);
4029         IDirectDrawSurface_Release(surface2);
4030         IDirectDrawSurface_Release(surface1);
4031     }
4032
4033     hr =IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
4034     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
4035
4036     DestroyWindow(window);
4037 }
4038
4039 static void test_window_style(void)
4040 {
4041     LONG style, exstyle, tmp;
4042     RECT fullscreen_rect, r;
4043     IDirectDraw7 *ddraw7;
4044     HWND window;
4045     HRESULT hr;
4046     ULONG ref;
4047
4048     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
4049     if (FAILED(hr))
4050     {
4051         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4052         return;
4053     }
4054
4055     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
4056             0, 0, 100, 100, 0, 0, 0, 0);
4057
4058     style = GetWindowLongA(window, GWL_STYLE);
4059     exstyle = GetWindowLongA(window, GWL_EXSTYLE);
4060     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
4061
4062     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4063     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4064     if (FAILED(hr))
4065     {
4066         IDirectDraw7_Release(ddraw7);
4067         DestroyWindow(window);
4068         return;
4069     }
4070
4071     tmp = GetWindowLongA(window, GWL_STYLE);
4072     todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
4073     tmp = GetWindowLongA(window, GWL_EXSTYLE);
4074     todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
4075
4076     GetWindowRect(window, &r);
4077     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4078             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4079             r.left, r.top, r.right, r.bottom);
4080     GetClientRect(window, &r);
4081     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
4082
4083     ref = IDirectDraw7_Release(ddraw7);
4084     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4085
4086     DestroyWindow(window);
4087 }
4088
4089 static void test_redundant_mode_set(void)
4090 {
4091     DDSURFACEDESC2 surface_desc = {0};
4092     IDirectDraw7 *ddraw7;
4093     HWND window;
4094     HRESULT hr;
4095     RECT r, s;
4096     ULONG ref;
4097
4098     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
4099     if (FAILED(hr))
4100     {
4101         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4102         return;
4103     }
4104
4105     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
4106             0, 0, 100, 100, 0, 0, 0, 0);
4107
4108     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4109     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4110     if (FAILED(hr))
4111     {
4112         IDirectDraw7_Release(ddraw7);
4113         DestroyWindow(window);
4114         return;
4115     }
4116
4117     surface_desc.dwSize = sizeof(surface_desc);
4118     hr = IDirectDraw7_GetDisplayMode(ddraw7, &surface_desc);
4119     ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
4120
4121     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
4122             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
4123     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4124
4125     GetWindowRect(window, &r);
4126     r.right /= 2;
4127     r.bottom /= 2;
4128     SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
4129     GetWindowRect(window, &s);
4130     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4131             r.left, r.top, r.right, r.bottom,
4132             s.left, s.top, s.right, s.bottom);
4133
4134     hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
4135             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
4136     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4137
4138     GetWindowRect(window, &s);
4139     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4140             r.left, r.top, r.right, r.bottom,
4141             s.left, s.top, s.right, s.bottom);
4142
4143     ref = IDirectDraw7_Release(ddraw7);
4144     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4145
4146     DestroyWindow(window);
4147 }
4148
4149 static void test_coop_level_mode_set(void)
4150 {
4151     RECT fullscreen_rect, r, s;
4152     IDirectDraw7 *ddraw7;
4153     HWND window;
4154     HRESULT hr;
4155     ULONG ref;
4156
4157     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
4158     if (FAILED(hr))
4159     {
4160         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
4161         return;
4162     }
4163
4164     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
4165             0, 0, 100, 100, 0, 0, 0, 0);
4166
4167     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
4168     SetRect(&s, 0, 0, 640, 480);
4169
4170     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4171     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4172     if (FAILED(hr))
4173     {
4174         IDirectDraw7_Release(ddraw7);
4175         DestroyWindow(window);
4176         return;
4177     }
4178
4179     GetWindowRect(window, &r);
4180     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4181             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4182             r.left, r.top, r.right, r.bottom);
4183
4184     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4185     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4186
4187     GetWindowRect(window, &r);
4188     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4189             s.left, s.top, s.right, s.bottom,
4190             r.left, r.top, r.right, r.bottom);
4191
4192     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4193     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4194
4195     GetWindowRect(window, &r);
4196     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4197             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4198             r.left, r.top, r.right, r.bottom);
4199
4200     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4201
4202     GetWindowRect(window, &r);
4203     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4204             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4205             r.left, r.top, r.right, r.bottom);
4206
4207     hr = IDirectDraw7_SetDisplayMode(ddraw7, 640, 480, 32, 0, 0);
4208     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
4209
4210     GetWindowRect(window, &r);
4211     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4212             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4213             r.left, r.top, r.right, r.bottom);
4214
4215     hr = IDirectDraw_RestoreDisplayMode(ddraw7);
4216     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4217
4218     GetWindowRect(window, &r);
4219     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4220             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4221             r.left, r.top, r.right, r.bottom);
4222
4223     ref = IDirectDraw7_Release(ddraw7);
4224     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4225
4226     GetWindowRect(window, &r);
4227     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4228             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4229             r.left, r.top, r.right, r.bottom);
4230
4231     DestroyWindow(window);
4232 }
4233
4234 START_TEST(d3d)
4235 {
4236     init_function_pointers();
4237     if(!pDirectDrawCreateEx) {
4238         win_skip("function DirectDrawCreateEx not available\n");
4239         return;
4240     }
4241
4242     if(!CreateDirect3D()) {
4243         skip("Skipping d3d7 tests\n");
4244     } else {
4245         LightTest();
4246         ProcessVerticesTest();
4247         StateTest();
4248         SceneTest();
4249         LimitTest();
4250         D3D7EnumTest();
4251         D3D7EnumLifetimeTest();
4252         SetMaterialTest();
4253         ComputeSphereVisibility();
4254         CapsTest();
4255         VertexBufferDescTest();
4256         D3D7_OldRenderStateTest();
4257         DeviceLoadTest();
4258         SetRenderTargetTest();
4259         VertexBufferLockRest();
4260         ReleaseDirect3D();
4261     }
4262
4263     if (!D3D1_createObjects()) {
4264         skip("Skipping d3d1 tests\n");
4265     } else {
4266         Direct3D1Test();
4267         TextureLoadTest();
4268         ViewportTest();
4269         FindDevice();
4270         BackBuffer3DCreateSurfaceTest();
4271         BackBuffer3DAttachmentTest();
4272         D3D1_releaseObjects();
4273     }
4274
4275     test_wndproc();
4276     test_window_style();
4277     test_redundant_mode_set();
4278     test_coop_level_mode_set();
4279 }