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