ddraw/tests: Fix compilation on systems that don't support nameless unions.
[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 /* To compare bad floating point numbers. Not the ideal way to do it,
58  * but it should be enough for here */
59 #define comparefloat(a, b) ( (((a) - (b)) < 0.0001) && (((a) - (b)) > -0.0001) )
60
61 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
62
63 typedef struct _VERTEX
64 {
65     float x, y, z;  /* position */
66 } VERTEX, *LPVERTEX;
67
68 typedef struct _TVERTEX
69 {
70     float x, y, z;  /* position */
71     float rhw;
72 } TVERTEX, *LPTVERTEX;
73
74
75 static void init_function_pointers(void)
76 {
77     HMODULE hmod = GetModuleHandleA("ddraw.dll");
78     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
79 }
80
81
82 static ULONG getRefcount(IUnknown *iface)
83 {
84     IUnknown_AddRef(iface);
85     return IUnknown_Release(iface);
86 }
87
88
89 static BOOL CreateDirect3D(void)
90 {
91     HRESULT rc;
92     DDSURFACEDESC2 ddsd;
93
94     rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
95         &IID_IDirectDraw7, NULL);
96     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
97     if (!lpDD) {
98         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
99         return FALSE;
100     }
101
102     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
103     ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
104
105     rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
106     if (rc == E_NOINTERFACE) return FALSE;
107     ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
108
109     memset(&ddsd, 0, sizeof(ddsd));
110     ddsd.dwSize = sizeof(ddsd);
111     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
112     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
113     ddsd.dwWidth = 256;
114     ddsd.dwHeight = 256;
115     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
116     if (FAILED(rc))
117         return FALSE;
118
119     memset(&ddsd, 0, sizeof(ddsd));
120     ddsd.dwSize = sizeof(ddsd);
121     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
122     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
123     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
124     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
125     U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 16;
126     U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
127     ddsd.dwWidth = 256;
128     ddsd.dwHeight = 256;
129     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDSdepth, NULL);
130     ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
131     if (FAILED(rc)) {
132         lpDDSdepth = NULL;
133     } else {
134         rc = IDirectDrawSurface_AddAttachedSurface(lpDDS, lpDDSdepth);
135         ok(rc == DD_OK, "IDirectDrawSurface_AddAttachedSurface returned %x\n", rc);
136         if (FAILED(rc))
137             return FALSE;
138     }
139
140     rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
141         &lpD3DDevice);
142     ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
143     if (!lpD3DDevice) {
144         trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
145         rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
146             &lpD3DDevice);
147         if (!lpD3DDevice) {
148             trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
149             rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
150                 &lpD3DDevice);
151             if (!lpD3DDevice) {
152                 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
153                 return FALSE;
154             }
155         }
156     }
157
158     return TRUE;
159 }
160
161 static void ReleaseDirect3D(void)
162 {
163     if (lpD3DDevice != NULL)
164     {
165         IDirect3DDevice7_Release(lpD3DDevice);
166         lpD3DDevice = NULL;
167     }
168
169     if (lpDDSdepth != NULL)
170     {
171         IDirectDrawSurface_Release(lpDDSdepth);
172         lpDDSdepth = NULL;
173     }
174
175     if (lpDDS != NULL)
176     {
177         IDirectDrawSurface_Release(lpDDS);
178         lpDDS = NULL;
179     }
180
181     if (lpD3D != NULL)
182     {
183         IDirect3D7_Release(lpD3D);
184         lpD3D = NULL;
185     }
186
187     if (lpDD != NULL)
188     {
189         IDirectDraw_Release(lpDD);
190         lpDD = NULL;
191     }
192 }
193
194 static void LightTest(void)
195 {
196     HRESULT rc;
197     D3DLIGHT7 light;
198     D3DLIGHT7 defaultlight;
199     BOOL bEnabled = FALSE;
200     float one = 1.0f;
201     float zero= 0.0f;
202     D3DMATERIAL7 mat;
203     BOOL enabled;
204     unsigned int i;
205     D3DDEVICEDESC7 caps;
206
207     /* Set a few lights with funky indices. */
208     memset(&light, 0, sizeof(light));
209     light.dltType = D3DLIGHT_DIRECTIONAL;
210     U1(light.dcvDiffuse).r = 0.5f;
211     U2(light.dcvDiffuse).g = 0.6f;
212     U3(light.dcvDiffuse).b = 0.7f;
213     U2(light.dvDirection).y = 1.f;
214
215     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
216     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
217     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
218     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
219     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
220     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
221
222
223     /* Try to retrieve a light beyond the indices of the lights that have
224        been set. */
225     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
226     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
227     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
228     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
229
230
231     /* Try to retrieve one of the lights that have been set */
232     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
233     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
234
235
236     /* Enable a light that have been previously set. */
237     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
238     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
239
240
241     /* Enable some lights that have not been previously set, and verify that
242        they have been initialized with proper default values. */
243     memset(&defaultlight, 0, sizeof(D3DLIGHT7));
244     defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
245     U1(defaultlight.dcvDiffuse).r = 1.f;
246     U2(defaultlight.dcvDiffuse).g = 1.f;
247     U3(defaultlight.dcvDiffuse).b = 1.f;
248     U3(defaultlight.dvDirection).z = 1.f;
249
250     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
251     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
252     memset(&light, 0, sizeof(D3DLIGHT7));
253     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
254     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
255     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
256         "light data doesn't match expected default values\n" );
257
258     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
259     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
260     memset(&light, 0, sizeof(D3DLIGHT7));
261     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
262     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
263     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
264         "light data doesn't match expected default values\n" );
265
266
267     /* Disable one of the light that have been previously enabled. */
268     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
269     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
270
271     /* Try to retrieve the enable status of some lights */
272     /* Light 20 is supposed to be disabled */
273     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
274     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
275     ok(!bEnabled, "GetLightEnable says the light is enabled\n");
276
277     /* Light 10 is supposed to be enabled */
278     bEnabled = FALSE;
279     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
280     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
281     ok(bEnabled, "GetLightEnable says the light is disabled\n");
282
283     /* Light 80 has not been set */
284     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
285     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
286
287     /* Light 23 has not been set */
288     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
289     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
290
291     /* Set some lights with invalid parameters */
292     memset(&light, 0, sizeof(D3DLIGHT7));
293     light.dltType = 0;
294     U1(light.dcvDiffuse).r = 1.f;
295     U2(light.dcvDiffuse).g = 1.f;
296     U3(light.dcvDiffuse).b = 1.f;
297     U3(light.dvDirection).z = 1.f;
298     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
299     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
300
301     memset(&light, 0, sizeof(D3DLIGHT7));
302     light.dltType = 12345;
303     U1(light.dcvDiffuse).r = 1.f;
304     U2(light.dcvDiffuse).g = 1.f;
305     U3(light.dcvDiffuse).b = 1.f;
306     U3(light.dvDirection).z = 1.f;
307     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
308     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
309
310     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
311     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
312
313     memset(&light, 0, sizeof(D3DLIGHT7));
314     light.dltType = D3DLIGHT_SPOT;
315     U1(light.dcvDiffuse).r = 1.f;
316     U2(light.dcvDiffuse).g = 1.f;
317     U3(light.dcvDiffuse).b = 1.f;
318     U3(light.dvDirection).z = 1.f;
319
320     light.dvAttenuation0 = -one / zero; /* -INFINITY */
321     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
322     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
323
324     light.dvAttenuation0 = -1.0;
325     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
326     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
327
328     light.dvAttenuation0 = 0.0;
329     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
330     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
331
332     light.dvAttenuation0 = 1.0;
333     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
334     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
335
336     light.dvAttenuation0 = one / zero; /* +INFINITY */
337     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
338     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
339
340     light.dvAttenuation0 = zero / zero; /* NaN */
341     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
342     ok(rc==D3D_OK ||
343        broken(rc==DDERR_INVALIDPARAMS), "SetLight returned: %x\n", rc);
344
345     /* Directional light ignores attenuation */
346     light.dltType = D3DLIGHT_DIRECTIONAL;
347     light.dvAttenuation0 = -1.0;
348     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
349     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
350
351     memset(&mat, 0, sizeof(mat));
352     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
353     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial returned: %x\n", rc);
354
355     U4(mat).power = 129.0;
356     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
357     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = 129.0) returned: %x\n", rc);
358     memset(&mat, 0, sizeof(mat));
359     rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
360     ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
361     ok(U4(mat).power == 129, "Returned power is %f\n", U4(mat).power);
362
363     U4(mat).power = -1.0;
364     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
365     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = -1.0) returned: %x\n", rc);
366     memset(&mat, 0, sizeof(mat));
367     rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
368     ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
369     ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
370
371     memset(&caps, 0, sizeof(caps));
372     rc = IDirect3DDevice7_GetCaps(lpD3DDevice, &caps);
373     ok(rc == D3D_OK, "IDirect3DDevice7_GetCaps failed with %x\n", rc);
374
375     if ( caps.dwMaxActiveLights == (DWORD) -1) {
376         /* Some cards without T&L Support return -1 (Examples: Voodoo Banshee, RivaTNT / NV4) */
377         skip("T&L not supported\n");
378         return;
379     }
380
381     for(i = 1; i <= caps.dwMaxActiveLights; i++) {
382         rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, TRUE);
383         ok(rc == D3D_OK, "Enabling light %u failed with %x\n", i, rc);
384         rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i, &enabled);
385         ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i, rc);
386         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
387     }
388
389     /* TODO: Test the rendering results in this situation */
390     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, TRUE);
391     ok(rc == D3D_OK, "Enabling one light more than supported returned %x\n", rc);
392     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i + 1, &enabled);
393     ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i + 1,  rc);
394     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
395     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, FALSE);
396     ok(rc == D3D_OK, "Disabling the additional returned %x\n", rc);
397
398     for(i = 1; i <= caps.dwMaxActiveLights; i++) {
399         rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, FALSE);
400         ok(rc == D3D_OK, "Disabling light %u failed with %x\n", i, rc);
401     }
402 }
403
404 static void ProcessVerticesTest(void)
405 {
406     D3DVERTEXBUFFERDESC desc;
407     HRESULT rc;
408     VERTEX *in;
409     TVERTEX *out;
410     VERTEX *out2;
411     D3DVIEWPORT7 vp;
412     D3DMATRIX view = {  2.0, 0.0, 0.0, 0.0,
413                         0.0, -1.0, 0.0, 0.0,
414                         0.0, 0.0, 1.0, 0.0,
415                         0.0, 0.0, 0.0, 3.0 };
416
417     D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
418                         1.0, 0.0, 0.0, 0.0,
419                         0.0, 0.0, 0.0, 1.0,
420                         0.0, 1.0, 1.0, 1.0 };
421
422     D3DMATRIX proj = {  1.0, 0.0, 0.0, 1.0,
423                         0.0, 1.0, 1.0, 0.0,
424                         0.0, 1.0, 1.0, 0.0,
425                         1.0, 0.0, 0.0, 1.0 };
426     /* Create some vertex buffers */
427
428     memset(&desc, 0, sizeof(desc));
429     desc.dwSize = sizeof(desc);
430     desc.dwCaps = 0;
431     desc.dwFVF = D3DFVF_XYZ;
432     desc.dwNumVertices = 16;
433     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
434     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
435     if (!lpVBufSrc)
436     {
437         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
438         goto out;
439     }
440
441     memset(&desc, 0, sizeof(desc));
442     desc.dwSize = sizeof(desc);
443     desc.dwCaps = 0;
444     desc.dwFVF = D3DFVF_XYZRHW;
445     desc.dwNumVertices = 16;
446     /* Msdn says that the last parameter must be 0 - check that */
447     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
448     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
449     if (!lpVBufDest1)
450     {
451         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
452         goto out;
453     }
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     /* Msdn says that the last parameter must be 0 - check that */
461     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
462     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
463     if (!lpVBufDest2)
464     {
465         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
466         goto out;
467     }
468
469     rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
470     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
471     if(!in) goto out;
472
473     /* Check basic transformation */
474
475     in[0].x = 0.0;
476     in[0].y = 0.0;
477     in[0].z = 0.0;
478
479     in[1].x = 1.0;
480     in[1].y = 1.0;
481     in[1].z = 1.0;
482
483     in[2].x = -1.0;
484     in[2].y = -1.0;
485     in[2].z = 0.5;
486
487     in[3].x = 0.5;
488     in[3].y = -0.5;
489     in[3].z = 0.25;
490     rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
491     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
492
493     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
494     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
495
496     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
497     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
498
499     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
500     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
501     if(!out) goto out;
502
503     /* Check the results */
504     ok( comparefloat(out[0].x, 128.0 ) &&
505         comparefloat(out[0].y, 128.0 ) &&
506         comparefloat(out[0].z, 0.0 ) &&
507         comparefloat(out[0].rhw, 1.0 ),
508         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
509
510     ok( comparefloat(out[1].x, 256.0 ) &&
511         comparefloat(out[1].y, 0.0 ) &&
512         comparefloat(out[1].z, 1.0 ) &&
513         comparefloat(out[1].rhw, 1.0 ),
514         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
515
516     ok( comparefloat(out[2].x, 0.0 ) &&
517         comparefloat(out[2].y, 256.0 ) &&
518         comparefloat(out[2].z, 0.5 ) &&
519         comparefloat(out[2].rhw, 1.0 ),
520         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
521
522     ok( comparefloat(out[3].x, 192.0 ) &&
523         comparefloat(out[3].y, 192.0 ) &&
524         comparefloat(out[3].z, 0.25 ) &&
525         comparefloat(out[3].rhw, 1.0 ),
526         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
527
528     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
529     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
530     out = NULL;
531
532     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
533     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
534     if(!out2) goto out;
535     /* Small thing without much practical meaning, but I stumbled upon it,
536      * so let's check for it: If the output vertex buffer has to RHW value,
537      * The RHW value of the last vertex is written into the next vertex
538      */
539     ok( comparefloat(out2[4].x, 1.0 ) &&
540         comparefloat(out2[4].y, 0.0 ) &&
541         comparefloat(out2[4].z, 0.0 ),
542         "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
543
544     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
545     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
546     out = NULL;
547
548     /* Try a more complicated viewport, same vertices */
549     memset(&vp, 0, sizeof(vp));
550     vp.dwX = 10;
551     vp.dwY = 5;
552     vp.dwWidth = 246;
553     vp.dwHeight = 130;
554     vp.dvMinZ = -2.0;
555     vp.dvMaxZ = 4.0;
556     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
557     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
558
559     /* Process again */
560     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
561     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
562
563     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
564     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
565     if(!out) goto out;
566
567     /* Check the results */
568     ok( comparefloat(out[0].x, 133.0 ) &&
569         comparefloat(out[0].y, 70.0 ) &&
570         comparefloat(out[0].z, -2.0 ) &&
571         comparefloat(out[0].rhw, 1.0 ),
572         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
573
574     ok( comparefloat(out[1].x, 256.0 ) &&
575         comparefloat(out[1].y, 5.0 ) &&
576         comparefloat(out[1].z, 4.0 ) &&
577         comparefloat(out[1].rhw, 1.0 ),
578         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
579
580     ok( comparefloat(out[2].x, 10.0 ) &&
581         comparefloat(out[2].y, 135.0 ) &&
582         comparefloat(out[2].z, 1.0 ) &&
583         comparefloat(out[2].rhw, 1.0 ),
584         "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
585
586     ok( comparefloat(out[3].x, 194.5 ) &&
587         comparefloat(out[3].y, 102.5 ) &&
588         comparefloat(out[3].z, -0.5 ) &&
589         comparefloat(out[3].rhw, 1.0 ),
590         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
591
592     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
593     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
594     out = NULL;
595
596     /* Play with some matrices. */
597
598     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
599     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
600
601     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
602     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
603
604     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
605     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
606
607     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
608     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
609
610     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
611     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
612     if(!out) goto out;
613
614     /* Keep the viewport simpler, otherwise we get bad numbers to compare */
615     vp.dwX = 0;
616     vp.dwY = 0;
617     vp.dwWidth = 100;
618     vp.dwHeight = 100;
619     vp.dvMinZ = 1.0;
620     vp.dvMaxZ = 0.0;
621     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
622     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
623
624     /* Check the results */
625     ok( comparefloat(out[0].x, 256.0 ) &&    /* X coordinate is cut at the surface edges */
626         comparefloat(out[0].y, 70.0 ) &&
627         comparefloat(out[0].z, -2.0 ) &&
628         comparefloat(out[0].rhw, (1.0 / 3.0)),
629         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
630
631     ok( comparefloat(out[1].x, 256.0 ) &&
632         comparefloat(out[1].y, 78.125000 ) &&
633         comparefloat(out[1].z, -2.750000 ) &&
634         comparefloat(out[1].rhw, 0.125000 ),
635         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
636
637     ok( comparefloat(out[2].x, 256.0 ) &&
638         comparefloat(out[2].y, 44.000000 ) &&
639         comparefloat(out[2].z, 0.400000 ) &&
640         comparefloat(out[2].rhw, 0.400000 ),
641         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
642
643     ok( comparefloat(out[3].x, 256.0 ) &&
644         comparefloat(out[3].y, 81.818184 ) &&
645         comparefloat(out[3].z, -3.090909 ) &&
646         comparefloat(out[3].rhw, 0.363636 ),
647         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
648
649     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
650     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
651     out = NULL;
652
653 out:
654     IDirect3DVertexBuffer7_Release(lpVBufSrc);
655     IDirect3DVertexBuffer7_Release(lpVBufDest1);
656     IDirect3DVertexBuffer7_Release(lpVBufDest2);
657 }
658
659 static void StateTest( void )
660 {
661     HRESULT rc;
662
663     /* The msdn says its undocumented, does it return an error too? */
664     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
665     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
666     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
667     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
668 }
669
670
671 static void SceneTest(void)
672 {
673     HRESULT                      hr;
674
675     /* Test an EndScene without beginscene. Should return an error */
676     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
677     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
678
679     /* Test a normal BeginScene / EndScene pair, this should work */
680     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
681     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
682     if(SUCCEEDED(hr))
683     {
684         DDBLTFX fx;
685         memset(&fx, 0, sizeof(fx));
686         fx.dwSize = sizeof(fx);
687
688         if(lpDDSdepth) {
689             hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
690             ok(hr == D3D_OK, "Depthfill failed in a BeginScene / EndScene pair\n");
691         } else {
692             skip("Depth stencil creation failed at startup, skipping\n");
693         }
694         hr = IDirect3DDevice7_EndScene(lpD3DDevice);
695         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
696     }
697
698     /* Test another EndScene without having begun a new scene. Should return an error */
699     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
700     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
701
702     /* Two nested BeginScene and EndScene calls */
703     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
704     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
705     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
706     ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
707     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
708     ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
709     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
710     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
711
712     /* TODO: Verify that blitting works in the same way as in d3d9 */
713 }
714
715 static void LimitTest(void)
716 {
717     IDirectDrawSurface7 *pTexture = NULL;
718     HRESULT hr;
719     int i;
720     DDSURFACEDESC2 ddsd;
721
722     memset(&ddsd, 0, sizeof(ddsd));
723     ddsd.dwSize = sizeof(ddsd);
724     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
725     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
726     ddsd.dwWidth = 16;
727     ddsd.dwHeight = 16;
728     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
729     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
730     if(!pTexture) return;
731
732     for(i = 0; i < 8; i++) {
733         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
734         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
735         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
736         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
737         hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
738         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
739     }
740
741     IDirectDrawSurface7_Release(pTexture);
742 }
743
744 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
745 {
746     UINT ver = *((UINT *) ctx);
747     if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
748     {
749         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
750            "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
751         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
752            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
753         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
754            "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
755         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
756            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
757
758         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
759            "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
760         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
761            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
762         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
763            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
764         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
765            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
766     }
767     else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
768     {
769         /* pow2 is hardware dependent */
770
771         ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
772            "HAL Device %d hal line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
773         ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
774            "HAL Device %d hal tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
775         ok((hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
776            "HAL Device %d hel line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
777         ok((hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
778            "HAL Device %d hel tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
779     }
780     else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
781     {
782         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
783            "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
784         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
785            "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
786         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
787            "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
788         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
789            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
790
791         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
792            "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
793         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
794            "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
795         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
796            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
797         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
798            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
799     }
800     else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
801     {
802         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
803            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
804         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
805            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
806         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
807            "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
808         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
809            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
810
811         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
812            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
813         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
814            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
815         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
816            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
817         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
818            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
819     }
820     else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
821     {
822         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
823            "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
824         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
825            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
826         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
827            "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
828         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
829            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
830
831         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
832            "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
833         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
834            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
835         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
836            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
837         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
838            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
839     }
840     else
841     {
842         ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
843         if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
844         else trace("hal line does NOT have pow2 set\n");
845         if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
846         else trace("hal tri does NOT have pow2 set\n");
847         if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
848         else trace("hel line does NOT have pow2 set\n");
849         if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
850         else trace("hel tri does NOT have pow2 set\n");
851     }
852     return DDENUMRET_OK;
853 }
854
855 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
856 {
857     D3D7ETest *d3d7et = Context;
858     if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
859         d3d7et->rgb++;
860     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
861         d3d7et->hal++;
862     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
863         d3d7et->tnlhal++;
864     else
865         d3d7et->unk++;
866
867     d3d7et->total++;
868
869     return DDENUMRET_OK;
870 }
871
872
873 /*  Check the deviceGUID of devices enumerated by
874     IDirect3D7_EnumDevices. */
875 static void D3D7EnumTest(void)
876 {
877     D3D7ETest d3d7et;
878
879     if (!lpD3D) {
880         skip("No Direct3D7 interface.\n");
881         return;
882     }
883
884     memset(&d3d7et, 0, sizeof(d3d7et));
885     IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et);
886
887
888     /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
889     ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
890
891     /* We make two additional assumptions. */
892     ok(d3d7et.rgb, "No RGB Device enumerated.\n");
893
894     if(d3d7et.tnlhal)
895         ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
896
897     return;
898 }
899
900 static void CapsTest(void)
901 {
902     IDirect3D3 *d3d3;
903     IDirect3D3 *d3d2;
904     IDirectDraw *dd1;
905     HRESULT hr;
906     UINT ver;
907
908     hr = DirectDrawCreate(NULL, &dd1, NULL);
909     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
910     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
911     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
912     ver = 3;
913     IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
914
915     IDirect3D3_Release(d3d3);
916     IDirectDraw_Release(dd1);
917
918     hr = DirectDrawCreate(NULL, &dd1, NULL);
919     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
920     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
921     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
922     ver = 2;
923     IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
924
925     IDirect3D2_Release(d3d2);
926     IDirectDraw_Release(dd1);
927 }
928
929 struct v_in {
930     float x, y, z;
931 };
932 struct v_out {
933     float x, y, z, rhw;
934 };
935
936 static BOOL D3D1_createObjects(void)
937 {
938     HRESULT hr;
939     DDSURFACEDESC ddsd;
940     D3DEXECUTEBUFFERDESC desc;
941     D3DVIEWPORT vp_data;
942
943     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
944     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
945     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
946     if (!DirectDraw1) {
947         return FALSE;
948     }
949
950     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
951     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
952
953     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
954     if (hr == E_NOINTERFACE) return FALSE;
955     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
956     if (!Direct3D1) {
957         return FALSE;
958     }
959
960     memset(&ddsd, 0, sizeof(ddsd));
961     ddsd.dwSize = sizeof(ddsd);
962     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
963     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
964     ddsd.dwWidth = 256;
965     ddsd.dwHeight = 256;
966     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
967     if (!Surface1) {
968         skip("DDSCAPS_3DDEVICE surface not available\n");
969         return FALSE;
970     }
971
972     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
973     ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
974     if(!Direct3DDevice1) {
975         return FALSE;
976     }
977
978     memset(&desc, 0, sizeof(desc));
979     desc.dwSize = sizeof(desc);
980     desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
981     desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
982     desc.dwBufferSize = 128;
983     desc.lpData = NULL;
984     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
985     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
986     if(!ExecuteBuffer) {
987         return FALSE;
988     }
989
990     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
991     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
992     if(!Viewport) {
993         return FALSE;
994     }
995
996     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
997     ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
998
999     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
1000     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1001     vp_data.dwSize = sizeof(vp_data);
1002     vp_data.dwX = 0;
1003     vp_data.dwY = 0;
1004     vp_data.dwWidth = 256;
1005     vp_data.dwHeight = 256;
1006     vp_data.dvScaleX = 1;
1007     vp_data.dvScaleY = 1;
1008     vp_data.dvMaxX = 256;
1009     vp_data.dvMaxY = 256;
1010     vp_data.dvMinZ = 0;
1011     vp_data.dvMaxZ = 1;
1012     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1013     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1014
1015     hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1016     ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1017     if (!Light)
1018         return FALSE;
1019
1020     return TRUE;
1021 }
1022
1023 static void D3D1_releaseObjects(void)
1024 {
1025     if (Light) IDirect3DLight_Release(Light);
1026     if (Viewport) IDirect3DViewport_Release(Viewport);
1027     if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1028     if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1029     if (Surface1) IDirectDrawSurface_Release(Surface1);
1030     if (Direct3D1) IDirect3D_Release(Direct3D1);
1031     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1032 }
1033
1034 #define SET_VP_DATA(vp_data) \
1035     vp_data.dwSize = sizeof(vp_data); \
1036     vp_data.dwX = 0; \
1037     vp_data.dwY = 0; \
1038     vp_data.dwWidth = 256; \
1039     vp_data.dwHeight = 256; \
1040     vp_data.dvMaxX = 256; \
1041     vp_data.dvMaxY = 256; \
1042     vp_data.dvScaleX = 5; \
1043     vp_data.dvScaleY = 5; \
1044     vp_data.dvMinZ = -25; \
1045     vp_data.dvMaxZ = 60;
1046
1047 static void Direct3D1Test(void)
1048 {
1049     HRESULT hr;
1050     D3DEXECUTEBUFFERDESC desc;
1051     D3DVIEWPORT vp_data;
1052     D3DINSTRUCTION *instr;
1053     D3DBRANCH *branch;
1054     IDirect3D *Direct3D_alt;
1055     IDirect3DLight *d3dlight;
1056     ULONG refcount;
1057     unsigned int idx = 0;
1058     static struct v_in testverts[] = {
1059         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
1060         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1061     };
1062     static struct v_in cliptest[] = {
1063         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
1064         {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1065     };
1066     static struct v_in offscreentest[] = {
1067         {128.1, 0.0, 0.0},
1068     };
1069     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1070     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1071     D3DTRANSFORMDATA transformdata;
1072     DWORD i = FALSE;
1073
1074     /* Interface consistency check. */
1075     hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1076     ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1077     if (hr == D3D_OK)
1078         ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1079
1080     memset(&desc, 0, sizeof(desc));
1081     desc.dwSize = sizeof(desc);
1082     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1083     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1084
1085     memset(desc.lpData, 0, 128);
1086     instr = desc.lpData;
1087     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1088     instr[idx].bSize = sizeof(*branch);
1089     instr[idx].wCount = 1;
1090     idx++;
1091     branch = (D3DBRANCH *) &instr[idx];
1092     branch->dwMask = 0x0;
1093     branch->dwValue = 1;
1094     branch->bNegate = TRUE;
1095     branch->dwOffset = 0;
1096     idx += (sizeof(*branch) / sizeof(*instr));
1097     instr[idx].bOpcode = D3DOP_EXIT;
1098     instr[idx].bSize = 0;
1099     instr[idx].wCount = 0;
1100     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1101     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1102
1103     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1104     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1105
1106     memset(&desc, 0, sizeof(desc));
1107     desc.dwSize = sizeof(desc);
1108
1109     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1110     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1111
1112     memset(desc.lpData, 0, 128);
1113     instr = desc.lpData;
1114     idx = 0;
1115     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1116     instr[idx].bSize = sizeof(*branch);
1117     instr[idx].wCount = 1;
1118     idx++;
1119     branch = (D3DBRANCH *) &instr[idx];
1120     branch->dwMask = 0x0;
1121     branch->dwValue = 1;
1122     branch->bNegate = TRUE;
1123     branch->dwOffset = 64;
1124     instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1125     instr[0].bOpcode = D3DOP_EXIT;
1126     instr[0].bSize = 0;
1127     instr[0].wCount = 0;
1128     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1129     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1130
1131     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1132     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1133
1134     /* Test rendering 0 triangles */
1135     memset(&desc, 0, sizeof(desc));
1136     desc.dwSize = sizeof(desc);
1137
1138     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1139     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1140
1141     memset(desc.lpData, 0, 128);
1142     instr = desc.lpData;
1143     idx = 0;
1144
1145     instr->bOpcode = D3DOP_TRIANGLE;
1146     instr->bSize = sizeof(D3DOP_TRIANGLE);
1147     instr->wCount = 0;
1148     instr++;
1149     instr->bOpcode = D3DOP_EXIT;
1150     instr->bSize = 0;
1151     instr->wCount = 0;
1152     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1153     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1154
1155     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1156     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1157
1158     memset(&transformdata, 0, sizeof(transformdata));
1159     transformdata.dwSize = sizeof(transformdata);
1160     transformdata.lpIn = testverts;
1161     transformdata.dwInSize = sizeof(testverts[0]);
1162     transformdata.lpOut = out;
1163     transformdata.dwOutSize = sizeof(out[0]);
1164
1165     transformdata.lpHOut = NULL;
1166     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1167                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1168                                              &i);
1169     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1170
1171     transformdata.lpHOut = outH;
1172     memset(outH, 0xcc, sizeof(outH));
1173     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1174                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1175                                              &i);
1176     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1177     ok(i == 0, "Offscreen is %d\n", i);
1178
1179     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1180         static const struct v_out cmp[] = {
1181             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1182             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1183         };
1184
1185         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1186            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1187            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1188            out[i].x, out[i].y, out[i].z, out[i].rhw,
1189            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1190     }
1191     for(i = 0; i < sizeof(outH); i++) {
1192         if(((unsigned char *) outH)[i] != 0xcc) {
1193             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1194             break;
1195         }
1196     }
1197
1198     SET_VP_DATA(vp_data);
1199     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1200     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1201     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1202                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1203                                              &i);
1204     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1205     ok(i == 0, "Offscreen is %d\n", i);
1206
1207     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1208         static const struct v_out cmp[] = {
1209             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1210             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1211         };
1212         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1213            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1214            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1215            out[i].x, out[i].y, out[i].z, out[i].rhw,
1216            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1217     }
1218
1219     SET_VP_DATA(vp_data);
1220     vp_data.dwX = 10;
1221     vp_data.dwY = 20;
1222     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1223     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1224     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1225                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1226                                              &i);
1227     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1228     ok(i == 0, "Offscreen is %d\n", i);
1229     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1230         static const struct v_out cmp[] = {
1231             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1232             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1233         };
1234         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1235            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1236            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1237            out[i].x, out[i].y, out[i].z, out[i].rhw,
1238            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1239     }
1240
1241     memset(out, 0xcc, sizeof(out));
1242     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1243                                              &transformdata, D3DTRANSFORM_CLIPPED,
1244                                              &i);
1245     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1246     ok(i == 0, "Offscreen is %d\n", i);
1247     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1248         static const D3DHVERTEX cmpH[] = {
1249             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1250             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1251             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1252         };
1253         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1254            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1255            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1256            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1257            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1258
1259         /* No scheme has been found behind those return values. It seems to be
1260          * whatever data windows has when throwing the vertex away. Modify the
1261          * input test vertices to test this more. Depending on the input data
1262          * it can happen that the z coord gets written into y, or similar things
1263          */
1264         if(0)
1265         {
1266             static const struct v_out cmp[] = {
1267                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1268                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1269             };
1270             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1271                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1272                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1273                out[i].x, out[i].y, out[i].z, out[i].rhw,
1274                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1275         }
1276     }
1277     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1278         ok(((DWORD *) out)[i] != 0xcccccccc,
1279                 "Regular output DWORD %d remained untouched\n", i);
1280     }
1281
1282     transformdata.lpIn = cliptest;
1283     transformdata.dwInSize = sizeof(cliptest[0]);
1284     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1285                                              &transformdata, D3DTRANSFORM_CLIPPED,
1286                                              &i);
1287     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1288     ok(i == 0, "Offscreen is %d\n", i);
1289     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1290         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1291         {
1292             0,
1293             0,
1294             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1295             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1296         };
1297         ok(Flags[i] == outH[i].dwFlags,
1298            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1299            outH[i].dwFlags, Flags[i]);
1300     }
1301
1302     SET_VP_DATA(vp_data);
1303     vp_data.dwWidth = 10;
1304     vp_data.dwHeight = 1000;
1305     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1306     i = 10;
1307     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1308     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1309                                              &transformdata, D3DTRANSFORM_CLIPPED,
1310                                              &i);
1311     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1312     ok(i == 0, "Offscreen is %d\n", i);
1313     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1314         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1315         {
1316             D3DCLIP_RIGHT,
1317             D3DCLIP_LEFT,
1318             D3DCLIP_RIGHT | D3DCLIP_BACK,
1319             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1320         };
1321         ok(Flags[i] == outH[i].dwFlags,
1322            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1323            outH[i].dwFlags, Flags[i]);
1324     }
1325
1326     SET_VP_DATA(vp_data);
1327     vp_data.dwWidth = 256;
1328     vp_data.dwHeight = 256;
1329     vp_data.dvScaleX = 1;
1330     vp_data.dvScaleY = 1;
1331     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1332     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1333     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1334                                              &transformdata, D3DTRANSFORM_CLIPPED,
1335                                              &i);
1336     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1337     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1338     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1339         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1340         {
1341             0,
1342             0,
1343             D3DCLIP_BACK,
1344             D3DCLIP_FRONT,
1345         };
1346         ok(Flags[i] == outH[i].dwFlags,
1347            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1348            outH[i].dwFlags, Flags[i]);
1349     }
1350
1351     /* Finally try to figure out how the DWORD dwOffscreen works.
1352      * Apparently no vertex is offscreen with clipping off,
1353      * and with clipping on the offscreen flag is set if only one vertex
1354      * is transformed, and this vertex is offscreen.
1355      */
1356     SET_VP_DATA(vp_data);
1357     vp_data.dwWidth = 5;
1358     vp_data.dwHeight = 5;
1359     vp_data.dvScaleX = 10000;
1360     vp_data.dvScaleY = 10000;
1361     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1362     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1363     transformdata.lpIn = cliptest;
1364     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1365                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1366                                              &i);
1367     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1368     ok(i == 0, "Offscreen is %d\n", i);
1369     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1370                                              &transformdata, D3DTRANSFORM_CLIPPED,
1371                                              &i);
1372     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1373     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1374     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1375                                              &transformdata, D3DTRANSFORM_CLIPPED,
1376                                              &i);
1377     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1378     ok(i == 0, "Offscreen is %d\n", i);
1379     transformdata.lpIn = cliptest + 1;
1380     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1381                                              &transformdata, D3DTRANSFORM_CLIPPED,
1382                                              &i);
1383     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1384     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1385
1386     transformdata.lpIn = offscreentest;
1387     transformdata.dwInSize = sizeof(offscreentest[0]);
1388     SET_VP_DATA(vp_data);
1389     vp_data.dwWidth = 257;
1390     vp_data.dwHeight = 257;
1391     vp_data.dvScaleX = 1;
1392     vp_data.dvScaleY = 1;
1393     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1394     i = 12345;
1395     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1396                                              &transformdata, D3DTRANSFORM_CLIPPED,
1397                                              &i);
1398     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1399     ok(i == 0, "Offscreen is %d\n", i);
1400     vp_data.dwWidth = 256;
1401     vp_data.dwHeight = 256;
1402     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1403     i = 12345;
1404     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1405                                              &transformdata, D3DTRANSFORM_CLIPPED,
1406                                              &i);
1407     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1408     ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1409
1410     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1411                                              &transformdata, 0,
1412                                              &i);
1413     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1414
1415     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1416     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1417
1418     hr = IDirect3DViewport_AddLight(Viewport, Light);
1419     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1420     refcount = getRefcount((IUnknown*) Light);
1421     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1422
1423     hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1424     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1425     ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1426     refcount = getRefcount((IUnknown*) Light);
1427     ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1428
1429     hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1430     ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1431     refcount = getRefcount((IUnknown*) Light);
1432     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1433
1434     IDirect3DLight_Release(Light);
1435 }
1436
1437 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1438 {
1439     int i;
1440
1441     for (i = 0; i < 256; i++) {
1442        if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1443            table1[i].peBlue != table2[i].peBlue) return FALSE;
1444     }
1445
1446     return TRUE;
1447 }
1448
1449 /* test palette handling in IDirect3DTexture_Load */
1450 static void TextureLoadTest(void)
1451 {
1452     IDirectDrawSurface *TexSurface = NULL;
1453     IDirect3DTexture *Texture = NULL;
1454     IDirectDrawSurface *TexSurface2 = NULL;
1455     IDirect3DTexture *Texture2 = NULL;
1456     IDirectDrawPalette *palette = NULL;
1457     IDirectDrawPalette *palette2 = NULL;
1458     IDirectDrawPalette *palette_tmp = NULL;
1459     PALETTEENTRY table1[256], table2[256], table_tmp[256];
1460     HRESULT hr;
1461     DDSURFACEDESC ddsd;
1462     int i;
1463
1464     memset (&ddsd, 0, sizeof (ddsd));
1465     ddsd.dwSize = sizeof (ddsd);
1466     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1467     ddsd.dwHeight = 128;
1468     ddsd.dwWidth = 128;
1469     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1470     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1471     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1472     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1473
1474     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1475     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1476     if (FAILED(hr)) {
1477         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1478         goto cleanup;
1479     }
1480
1481     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1482                 (void *)&Texture);
1483     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1484     if (FAILED(hr)) {
1485         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1486         goto cleanup;
1487     }
1488
1489     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1490     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1491     if (FAILED(hr)) {
1492         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1493         goto cleanup;
1494     }
1495
1496     hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1497                 (void *)&Texture2);
1498     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1499     if (FAILED(hr)) {
1500         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1501         goto cleanup;
1502     }
1503
1504     /* test load of Texture to Texture */
1505     hr = IDirect3DTexture_Load(Texture, Texture);
1506     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1507
1508     /* test Load when both textures have no palette */
1509     hr = IDirect3DTexture_Load(Texture2, Texture);
1510     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1511
1512     for (i = 0; i < 256; i++) {
1513         table1[i].peRed = i;
1514         table1[i].peGreen = i;
1515         table1[i].peBlue = i;
1516         table1[i].peFlags = 0;
1517     }
1518
1519     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1520     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1521     if (FAILED(hr)) {
1522         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1523         goto cleanup;
1524     }
1525
1526     /* test Load when source texture has palette and destination has no palette */
1527     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1528     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1529     hr = IDirect3DTexture_Load(Texture2, Texture);
1530     ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1531
1532     for (i = 0; i < 256; i++) {
1533         table2[i].peRed = 255 - i;
1534         table2[i].peGreen = 255 - i;
1535         table2[i].peBlue = 255 - i;
1536         table2[i].peFlags = 0;
1537     }
1538
1539     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1540     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1541     if (FAILED(hr)) {
1542         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1543         goto cleanup;
1544     }
1545
1546     /* test Load when source has no palette and destination has a palette */
1547     hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1548     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1549     hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1550     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1551     hr = IDirect3DTexture_Load(Texture2, Texture);
1552     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1553     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1554     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1555     if (!palette_tmp) {
1556         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1557         goto cleanup;
1558     } else {
1559         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1560         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1561         ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1562         IDirectDrawPalette_Release(palette_tmp);
1563     }
1564
1565     /* test Load when both textures have palettes */
1566     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1567     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1568     hr = IDirect3DTexture_Load(Texture2, Texture);
1569     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1570     hr = IDirect3DTexture_Load(Texture2, Texture);
1571     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1572     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1573     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1574     if (!palette_tmp) {
1575         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1576         goto cleanup;
1577     } else {
1578         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1579         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1580         ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1581         IDirectDrawPalette_Release(palette_tmp);
1582     }
1583
1584     cleanup:
1585
1586     if (palette) IDirectDrawPalette_Release(palette);
1587     if (palette2) IDirectDrawPalette_Release(palette2);
1588     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1589     if (Texture) IDirect3DTexture_Release(Texture);
1590     if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1591     if (Texture2) IDirect3DTexture_Release(Texture2);
1592 }
1593
1594 static void VertexBufferDescTest(void)
1595 {
1596     HRESULT rc;
1597     D3DVERTEXBUFFERDESC desc;
1598     union mem_t
1599     {
1600         D3DVERTEXBUFFERDESC desc2;
1601         unsigned char buffer[512];
1602     } mem;
1603
1604     memset(&desc, 0, sizeof(desc));
1605     desc.dwSize = sizeof(desc);
1606     desc.dwCaps = 0;
1607     desc.dwFVF = D3DFVF_XYZ;
1608     desc.dwNumVertices = 1;
1609     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1610     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1611     if (!lpVBufSrc)
1612     {
1613         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1614         goto out;
1615     }
1616
1617     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1618     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1619     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1620     if(rc != D3D_OK)
1621         skip("GetVertexBuffer Failed!\n");
1622     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1623     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1624     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1625     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1626     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1627
1628     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1629     mem.desc2.dwSize = 0;
1630     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1631     if(rc != D3D_OK)
1632         skip("GetVertexBuffer Failed!\n");
1633     ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1634     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1635     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1636     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1637     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1638
1639     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1640     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1641     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1642     if(rc != D3D_OK)
1643         skip("GetVertexBuffer Failed!\n");
1644     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1645     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1646     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1647     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1648     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1649
1650 out:
1651     IDirect3DVertexBuffer7_Release(lpVBufSrc);
1652 }
1653
1654 static void D3D7_OldRenderStateTest(void)
1655 {
1656     HRESULT rc;
1657     DWORD val;
1658
1659     /* Test reaction to some deprecated states in D3D7.
1660
1661      * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1662      * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1663      * need not to be handled in D3D7.
1664      */
1665     todo_wine {
1666         rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1667         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1668
1669         rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1670         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1671
1672         rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1673         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1674
1675         rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1676         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1677     }
1678 }
1679
1680 #define IS_VALUE_NEAR(a, b)    ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1681 #define MIN(a, b)    ((a) < (b) ? (a) : (b))
1682
1683 static void DeviceLoadTest(void)
1684 {
1685     DDSURFACEDESC2 ddsd;
1686     IDirectDrawSurface7 *texture_levels[2][8];
1687     IDirectDrawSurface7 *cube_face_levels[2][6][8];
1688     DWORD flags;
1689     HRESULT hr;
1690     DDBLTFX ddbltfx;
1691     RECT loadrect;
1692     POINT loadpoint;
1693     int i, i1, i2;
1694     unsigned diff_count = 0, diff_count2 = 0;
1695     unsigned x, y;
1696     BOOL load_mip_subset_broken = FALSE;
1697     IDirectDrawPalette *palettes[5];
1698     PALETTEENTRY table1[256];
1699     DDCOLORKEY ddckey;
1700     D3DDEVICEDESC7 d3dcaps;
1701
1702     /* Test loading of texture subrectangle with a mipmap surface. */
1703     memset(texture_levels, 0, sizeof(texture_levels));
1704     memset(cube_face_levels, 0, sizeof(cube_face_levels));
1705     memset(palettes, 0, sizeof(palettes));
1706
1707     for (i = 0; i < 2; i++)
1708     {
1709         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1710         ddsd.dwSize = sizeof(ddsd);
1711         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1712         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1713         ddsd.dwWidth = 128;
1714         ddsd.dwHeight = 128;
1715         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1716         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1717         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1718         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1719         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1720         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1721         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1722         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1723         if (FAILED(hr)) goto out;
1724
1725         /* Check the number of created mipmaps */
1726         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1727         ddsd.dwSize = sizeof(ddsd);
1728         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1729         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1730         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1731         if (U2(ddsd).dwMipMapCount != 8) goto out;
1732
1733         for (i1 = 1; i1 < 8; i1++)
1734         {
1735             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1736             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1737             if (FAILED(hr)) goto out;
1738         }
1739     }
1740
1741     for (i1 = 0; i1 < 8; i1++)
1742     {
1743         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1744         ddsd.dwSize = sizeof(ddsd);
1745         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1746         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1747         if (FAILED(hr)) goto out;
1748
1749         for (y = 0 ; y < ddsd.dwHeight; y++)
1750         {
1751             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1752
1753             for (x = 0; x < ddsd.dwWidth;  x++)
1754             {
1755                 /* x stored in green component, y in blue. */
1756                 DWORD color = 0xff0000 | (x << 8)  | y;
1757                 *textureRow++ = color;
1758             }
1759         }
1760
1761         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1762         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1763     }
1764
1765     for (i1 = 0; i1 < 8; i1++)
1766     {
1767         memset(&ddbltfx, 0, sizeof(ddbltfx));
1768         ddbltfx.dwSize = sizeof(ddbltfx);
1769         U5(ddbltfx).dwFillColor = 0;
1770         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1771         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1772     }
1773
1774     /* First test some broken coordinates. */
1775     loadpoint.x = loadpoint.y = 0;
1776     loadrect.left = 0;
1777     loadrect.top = 0;
1778     loadrect.right = 0;
1779     loadrect.bottom = 0;
1780     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1781     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1782
1783     loadpoint.x = loadpoint.y = 50;
1784     loadrect.left = 0;
1785     loadrect.top = 0;
1786     loadrect.right = 100;
1787     loadrect.bottom = 100;
1788     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1789     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1790
1791     /* Test actual loading. */
1792     loadpoint.x = loadpoint.y = 31;
1793     loadrect.left = 30;
1794     loadrect.top = 20;
1795     loadrect.right = 93;
1796     loadrect.bottom = 52;
1797
1798     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1799     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1800
1801     for (i1 = 0; i1 < 8; i1++)
1802     {
1803         diff_count = 0;
1804         diff_count2 = 0;
1805
1806         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1807         ddsd.dwSize = sizeof(ddsd);
1808         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1809         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1810         if (FAILED(hr)) goto out;
1811
1812         for (y = 0 ; y < ddsd.dwHeight; y++)
1813         {
1814             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1815
1816             for (x = 0; x < ddsd.dwWidth;  x++)
1817             {
1818                 DWORD color = *textureRow++;
1819
1820                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1821                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1822                 {
1823                     if (color & 0xffffff) diff_count++;
1824                 }
1825                 else
1826                 {
1827                     DWORD r = (color & 0xff0000) >> 16;
1828                     DWORD g = (color & 0xff00) >> 8;
1829                     DWORD b = (color & 0xff);
1830
1831                     if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1832                 }
1833
1834                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1835                    technically be correct as it's not precisely defined by docs. */
1836                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1837                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1838                 {
1839                     if (color & 0xffffff) diff_count2++;
1840                 }
1841                 else
1842                 {
1843                     DWORD r = (color & 0xff0000) >> 16;
1844                     DWORD g = (color & 0xff00) >> 8;
1845                     DWORD b = (color & 0xff);
1846
1847                     if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1848                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1849                 }
1850             }
1851         }
1852
1853         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1854         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1855
1856         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1857                 MIN(diff_count, diff_count2), i1);
1858
1859         loadpoint.x /= 2;
1860         loadpoint.y /= 2;
1861         loadrect.top /= 2;
1862         loadrect.left /= 2;
1863         loadrect.right = (loadrect.right + 1) / 2;
1864         loadrect.bottom = (loadrect.bottom + 1) / 2;
1865     }
1866
1867     /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1868      * qemu Win98 / directx7 / RGB software rasterizer):
1869      * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1870     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1871     */
1872
1873     /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1874     for (i = 0; i < 2; i++)
1875     {
1876         for (i1 = 7; i1 >= 0; i1--)
1877         {
1878             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1879         }
1880     }
1881     memset(texture_levels, 0, sizeof(texture_levels));
1882
1883     /* Test texture size mismatch. */
1884     for (i = 0; i < 2; i++)
1885     {
1886         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1887         ddsd.dwSize = sizeof(ddsd);
1888         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1889         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1890         ddsd.dwWidth = i ? 256 : 128;
1891         ddsd.dwHeight = 128;
1892         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1893         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1894         if (FAILED(hr)) goto out;
1895     }
1896
1897     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1898     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1899
1900     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1901     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1902
1903     IDirectDrawSurface7_Release(texture_levels[0][0]);
1904     IDirectDrawSurface7_Release(texture_levels[1][0]);
1905     memset(texture_levels, 0, sizeof(texture_levels));
1906
1907     memset(&d3dcaps, 0, sizeof(d3dcaps));
1908     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1909     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1910
1911     if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1912     {
1913         skip("No cubemap support\n");
1914     }
1915     else
1916     {
1917         /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1918         for (i = 0; i < 2; i++)
1919         {
1920             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1921             ddsd.dwSize = sizeof(ddsd);
1922             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1923             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1924             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1925             ddsd.dwWidth = 128;
1926             ddsd.dwHeight = 128;
1927             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1928             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1929             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1930             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1931             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1932             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1933             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1934             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1935             if (FAILED(hr)) goto out;
1936
1937             flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1938             for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1939             {
1940                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1941                 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1942                 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1943                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1944                 if (FAILED(hr)) goto out;
1945             }
1946
1947             for (i1 = 0; i1 < 6; i1++)
1948             {
1949                 /* Check the number of created mipmaps */
1950                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1951                 ddsd.dwSize = sizeof(ddsd);
1952                 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1953                 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1954                 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1955                 if (U2(ddsd).dwMipMapCount != 8) goto out;
1956
1957                 for (i2 = 1; i2 < 8; i2++)
1958                 {
1959                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1960                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1961                     hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1962                     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1963                     if (FAILED(hr)) goto out;
1964                 }
1965             }
1966         }
1967
1968         for (i = 0; i < 6; i++)
1969             for (i1 = 0; i1 < 8; i1++)
1970             {
1971                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1972                 ddsd.dwSize = sizeof(ddsd);
1973                 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1974                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1975                 if (FAILED(hr)) goto out;
1976
1977                 for (y = 0 ; y < ddsd.dwHeight; y++)
1978                 {
1979                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1980
1981                     for (x = 0; x < ddsd.dwWidth;  x++)
1982                     {
1983                         /* face number in low 4 bits of red, x stored in green component, y in blue. */
1984                         DWORD color = 0xf00000 | (i << 16) | (x << 8)  | y;
1985                         *textureRow++ = color;
1986                     }
1987                 }
1988
1989                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1990                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1991             }
1992
1993         for (i = 0; i < 6; i++)
1994             for (i1 = 0; i1 < 8; i1++)
1995             {
1996                 memset(&ddbltfx, 0, sizeof(ddbltfx));
1997                 ddbltfx.dwSize = sizeof(ddbltfx);
1998                 U5(ddbltfx).dwFillColor = 0;
1999                 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2000                 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2001             }
2002
2003         loadpoint.x = loadpoint.y = 10;
2004         loadrect.left = 30;
2005         loadrect.top = 20;
2006         loadrect.right = 93;
2007         loadrect.bottom = 52;
2008
2009         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2010                                         DDSCAPS2_CUBEMAP_ALLFACES);
2011         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2012
2013         for (i = 0; i < 6; i++)
2014         {
2015             loadpoint.x = loadpoint.y = 10;
2016             loadrect.left = 30;
2017             loadrect.top = 20;
2018             loadrect.right = 93;
2019             loadrect.bottom = 52;
2020
2021             for (i1 = 0; i1 < 8; i1++)
2022             {
2023                 diff_count = 0;
2024                 diff_count2 = 0;
2025
2026                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2027                 ddsd.dwSize = sizeof(ddsd);
2028                 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2029                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2030                 if (FAILED(hr)) goto out;
2031
2032                 for (y = 0 ; y < ddsd.dwHeight; y++)
2033                 {
2034                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2035
2036                     for (x = 0; x < ddsd.dwWidth;  x++)
2037                     {
2038                         DWORD color = *textureRow++;
2039
2040                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2041                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2042                         {
2043                             if (color & 0xffffff) diff_count++;
2044                         }
2045                         else
2046                         {
2047                             DWORD r = (color & 0xff0000) >> 16;
2048                             DWORD g = (color & 0xff00) >> 8;
2049                             DWORD b = (color & 0xff);
2050
2051                             if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2052                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2053                         }
2054
2055                         /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2056                         technically be correct as it's not precisely defined by docs. */
2057                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2058                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2059                         {
2060                             if (color & 0xffffff) diff_count2++;
2061                         }
2062                         else
2063                         {
2064                             DWORD r = (color & 0xff0000) >> 16;
2065                             DWORD g = (color & 0xff00) >> 8;
2066                             DWORD b = (color & 0xff);
2067
2068                             if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2069                                 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2070                         }
2071                     }
2072                 }
2073
2074                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2075                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2076
2077                 ok(diff_count == 0 || diff_count2 == 0,
2078                     "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2079                     MIN(diff_count, diff_count2), i, i1);
2080
2081                 loadpoint.x /= 2;
2082                 loadpoint.y /= 2;
2083                 loadrect.top /= 2;
2084                 loadrect.left /= 2;
2085                 loadrect.right = (loadrect.right + 1) / 2;
2086                 loadrect.bottom = (loadrect.bottom + 1) / 2;
2087             }
2088         }
2089
2090         for (i = 0; i < 2; i++)
2091             for (i1 = 5; i1 >= 0; i1--)
2092                 for (i2 = 7; i2 >= 0; i2--)
2093                 {
2094                     if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2095                 }
2096         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2097
2098         /* Test cubemap loading from regular texture. */
2099         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2100         ddsd.dwSize = sizeof(ddsd);
2101         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2102         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2103         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2104         ddsd.dwWidth = 128;
2105         ddsd.dwHeight = 128;
2106         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2107         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2108         if (FAILED(hr)) goto out;
2109
2110         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2111         ddsd.dwSize = sizeof(ddsd);
2112         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2113         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2114         ddsd.dwWidth = 128;
2115         ddsd.dwHeight = 128;
2116         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2117         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2118         if (FAILED(hr)) goto out;
2119
2120         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2121                                         DDSCAPS2_CUBEMAP_ALLFACES);
2122         ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2123
2124         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2125         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2126         IDirectDrawSurface7_Release(texture_levels[0][0]);
2127         memset(texture_levels, 0, sizeof(texture_levels));
2128
2129         /* Test cubemap loading from cubemap with different number of faces. */
2130         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2131         ddsd.dwSize = sizeof(ddsd);
2132         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2133         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2134         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2135         ddsd.dwWidth = 128;
2136         ddsd.dwHeight = 128;
2137         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2138         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2139         if (FAILED(hr)) goto out;
2140
2141         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2142         ddsd.dwSize = sizeof(ddsd);
2143         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2144         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2145         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2146         ddsd.dwWidth = 128;
2147         ddsd.dwHeight = 128;
2148         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2149         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2150         if (FAILED(hr)) goto out;
2151
2152         /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2153             (the above created cubemaps will have all faces. */
2154         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2155                                         DDSCAPS2_CUBEMAP_ALLFACES);
2156         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2157
2158         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2159                                         DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2160         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2161
2162         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2163                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2164         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2165
2166         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2167                                         DDSCAPS2_CUBEMAP_ALLFACES);
2168         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2169
2170         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2171                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2172         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2173
2174         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2175                                         DDSCAPS2_CUBEMAP_POSITIVEZ);
2176         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2177
2178         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2179         IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2180         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2181     }
2182
2183     /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2184     for (i = 0; i < 2; i++)
2185     {
2186         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2187         ddsd.dwSize = sizeof(ddsd);
2188         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2189         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2190         ddsd.dwWidth = 128;
2191         ddsd.dwHeight = 128;
2192         U2(ddsd).dwMipMapCount = i ? 4 : 8;
2193         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2194         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2195         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2196         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2197         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2198         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2199         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2200         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2201         if (FAILED(hr)) goto out;
2202
2203         /* Check the number of created mipmaps */
2204         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2205         ddsd.dwSize = sizeof(ddsd);
2206         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2207         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2208         ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2209         if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2210
2211         for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2212         {
2213             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2214             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2215             if (FAILED(hr)) goto out;
2216         }
2217     }
2218
2219     for (i1 = 0; i1 < 8; i1++)
2220     {
2221         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2222         ddsd.dwSize = sizeof(ddsd);
2223         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2224         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2225         if (FAILED(hr)) goto out;
2226
2227         for (y = 0 ; y < ddsd.dwHeight; y++)
2228         {
2229             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2230
2231             for (x = 0; x < ddsd.dwWidth;  x++)
2232             {
2233                 /* x stored in green component, y in blue. */
2234                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2235                 *textureRow++ = color;
2236             }
2237         }
2238
2239         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2240         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2241     }
2242
2243     for (i1 = 0; i1 < 4; i1++)
2244     {
2245         memset(&ddbltfx, 0, sizeof(ddbltfx));
2246         ddbltfx.dwSize = sizeof(ddbltfx);
2247         U5(ddbltfx).dwFillColor = 0;
2248         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2249         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2250     }
2251
2252     loadpoint.x = loadpoint.y = 31;
2253     loadrect.left = 30;
2254     loadrect.top = 20;
2255     loadrect.right = 93;
2256     loadrect.bottom = 52;
2257
2258     /* Destination mip levels are a subset of source mip levels. */
2259     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2260     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2261
2262     for (i1 = 0; i1 < 4; i1++)
2263     {
2264         diff_count = 0;
2265         diff_count2 = 0;
2266
2267         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2268         ddsd.dwSize = sizeof(ddsd);
2269         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2270         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2271         if (FAILED(hr)) goto out;
2272
2273         for (y = 0 ; y < ddsd.dwHeight; y++)
2274         {
2275             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2276
2277             for (x = 0; x < ddsd.dwWidth;  x++)
2278             {
2279                 DWORD color = *textureRow++;
2280
2281                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2282                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2283                 {
2284                     if (color & 0xffffff) diff_count++;
2285                 }
2286                 else
2287                 {
2288                     DWORD r = (color & 0xff0000) >> 16;
2289                     DWORD g = (color & 0xff00) >> 8;
2290                     DWORD b = (color & 0xff);
2291
2292                     if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2293                         b != y + loadrect.top - loadpoint.y) diff_count++;
2294                 }
2295
2296                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2297                 technically be correct as it's not precisely defined by docs. */
2298                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2299                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2300                 {
2301                     if (color & 0xffffff) diff_count2++;
2302                 }
2303                 else
2304                 {
2305                     DWORD r = (color & 0xff0000) >> 16;
2306                     DWORD g = (color & 0xff00) >> 8;
2307                     DWORD b = (color & 0xff);
2308
2309                     if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2310                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2311                 }
2312             }
2313         }
2314
2315         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2316         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2317
2318         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2319              MIN(diff_count, diff_count2), i1);
2320
2321         loadpoint.x /= 2;
2322         loadpoint.y /= 2;
2323         loadrect.top /= 2;
2324         loadrect.left /= 2;
2325         loadrect.right = (loadrect.right + 1) / 2;
2326         loadrect.bottom = (loadrect.bottom + 1) / 2;
2327     }
2328
2329     /* Destination mip levels are a superset of source mip levels (should fail). */
2330     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2331     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2332
2333     for (i = 0; i < 2; i++)
2334     {
2335         for (i1 = 7; i1 >= 0; i1--)
2336         {
2337             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2338         }
2339     }
2340     memset(texture_levels, 0, sizeof(texture_levels));
2341
2342     /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2343     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2344     ddsd.dwSize = sizeof(ddsd);
2345     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2346     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2347     ddsd.dwWidth = 128;
2348     ddsd.dwHeight = 128;
2349     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2350     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2351     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2352     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2353     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2354     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2355     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2356     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2357     if (FAILED(hr)) goto out;
2358
2359     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2360     ddsd.dwSize = sizeof(ddsd);
2361     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2362     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2363     ddsd.dwWidth = 32;
2364     ddsd.dwHeight = 32;
2365     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2366     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2367     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2368     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2369     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2370     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2371     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2372     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2373     if (FAILED(hr)) goto out;
2374
2375     for (i1 = 1; i1 < 8; i1++)
2376     {
2377         hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2378         ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2379         if (FAILED(hr)) goto out;
2380     }
2381
2382     for (i1 = 0; i1 < 8; i1++)
2383     {
2384         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2385         ddsd.dwSize = sizeof(ddsd);
2386         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2387         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2388         if (FAILED(hr)) goto out;
2389
2390         for (y = 0 ; y < ddsd.dwHeight; y++)
2391         {
2392             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2393
2394             for (x = 0; x < ddsd.dwWidth;  x++)
2395             {
2396                 /* x stored in green component, y in blue. */
2397                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2398                 *textureRow++ = color;
2399             }
2400         }
2401
2402         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2403         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2404     }
2405
2406     memset(&ddbltfx, 0, sizeof(ddbltfx));
2407     ddbltfx.dwSize = sizeof(ddbltfx);
2408     U5(ddbltfx).dwFillColor = 0;
2409     hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2410     ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2411
2412     loadpoint.x = loadpoint.y = 32;
2413     loadrect.left = 32;
2414     loadrect.top = 32;
2415     loadrect.right = 96;
2416     loadrect.bottom = 96;
2417
2418     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2419     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2420
2421     loadpoint.x /= 4;
2422     loadpoint.y /= 4;
2423     loadrect.top /= 4;
2424     loadrect.left /= 4;
2425     loadrect.right = (loadrect.right + 3) / 4;
2426     loadrect.bottom = (loadrect.bottom + 3) / 4;
2427
2428     /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2429      * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2430      * copied subrectangles divided more than needed, without apparent logic. But it works
2431      * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2432      * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2433      * The following code attempts to detect broken results, actual tests will then be skipped
2434      */
2435     load_mip_subset_broken = TRUE;
2436     diff_count = 0;
2437
2438     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2439     ddsd.dwSize = sizeof(ddsd);
2440     hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2441     ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2442     if (FAILED(hr)) goto out;
2443
2444     for (y = 0 ; y < ddsd.dwHeight; y++)
2445     {
2446         DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2447
2448         for (x = 0; x < ddsd.dwWidth;  x++)
2449         {
2450             DWORD color = *textureRow++;
2451
2452             if (x < 2 || x >= 2 + 4 ||
2453                 y < 2 || y >= 2 + 4)
2454             {
2455                 if (color & 0xffffff) diff_count++;
2456             }
2457             else
2458             {
2459                 DWORD r = (color & 0xff0000) >> 16;
2460
2461                 if ((r & (0xf0)) != 0xf0) diff_count++;
2462             }
2463         }
2464     }
2465
2466     if (diff_count) load_mip_subset_broken = FALSE;
2467
2468     if (load_mip_subset_broken) {
2469         skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2470     } else {
2471         diff_count = 0;
2472
2473         for (y = 0 ; y < ddsd.dwHeight; y++)
2474         {
2475             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2476
2477             for (x = 0; x < ddsd.dwWidth;  x++)
2478             {
2479                 DWORD color = *textureRow++;
2480
2481                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2482                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2483                 {
2484                     if (color & 0xffffff) diff_count++;
2485                 }
2486                 else
2487                 {
2488                     DWORD r = (color & 0xff0000) >> 16;
2489                     DWORD g = (color & 0xff00) >> 8;
2490                     DWORD b = (color & 0xff);
2491
2492                     if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2493                         b != y + loadrect.top - loadpoint.y) diff_count++;
2494                 }
2495             }
2496         }
2497     }
2498
2499     hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2500     ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2501
2502     ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2503
2504     for (i = 0; i < 2; i++)
2505     {
2506         for (i1 = 7; i1 >= 0; i1--)
2507         {
2508             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2509         }
2510     }
2511     memset(texture_levels, 0, sizeof(texture_levels));
2512
2513     if (!load_mip_subset_broken)
2514     {
2515         /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2516         * surface (than first source mip level)
2517         */
2518         for (i = 0; i < 2; i++)
2519         {
2520             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2521             ddsd.dwSize = sizeof(ddsd);
2522             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2523             if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2524             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2525             ddsd.dwWidth = i ? 32 : 128;
2526             ddsd.dwHeight = i ? 32 : 128;
2527             if (i) U2(ddsd).dwMipMapCount = 4;
2528             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2529             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2530             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2531             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2532             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2533             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2534             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2535             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2536             if (FAILED(hr)) goto out;
2537
2538             /* Check the number of created mipmaps */
2539             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2540             ddsd.dwSize = sizeof(ddsd);
2541             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2542             ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2543             ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2544             if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2545
2546             for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2547             {
2548                 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2549                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2550                 if (FAILED(hr)) goto out;
2551             }
2552         }
2553
2554         for (i1 = 0; i1 < 8; i1++)
2555         {
2556             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2557             ddsd.dwSize = sizeof(ddsd);
2558             hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2559             ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2560             if (FAILED(hr)) goto out;
2561
2562             for (y = 0 ; y < ddsd.dwHeight; y++)
2563             {
2564                 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2565
2566                 for (x = 0; x < ddsd.dwWidth;  x++)
2567                 {
2568                     /* x stored in green component, y in blue. */
2569                     DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2570                     *textureRow++ = color;
2571                 }
2572             }
2573
2574             hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2575             ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2576         }
2577
2578         for (i1 = 0; i1 < 4; i1++)
2579         {
2580             memset(&ddbltfx, 0, sizeof(ddbltfx));
2581             ddbltfx.dwSize = sizeof(ddbltfx);
2582             U5(ddbltfx).dwFillColor = 0;
2583             hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2584             ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2585         }
2586
2587         loadpoint.x = loadpoint.y = 0;
2588         loadrect.left = 0;
2589         loadrect.top = 0;
2590         loadrect.right = 64;
2591         loadrect.bottom = 64;
2592
2593         hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2594         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2595
2596         i = 0;
2597         for (i1 = 0; i1 < 8 && i < 4; i1++)
2598         {
2599             DDSURFACEDESC2 ddsd2;
2600
2601             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2602             ddsd.dwSize = sizeof(ddsd);
2603             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2604
2605             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2606             ddsd2.dwSize = sizeof(ddsd2);
2607             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2608
2609             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2610             {
2611                 diff_count = 0;
2612
2613                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2614                 ddsd.dwSize = sizeof(ddsd);
2615                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2616                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2617                 if (FAILED(hr)) goto out;
2618
2619                 for (y = 0 ; y < ddsd.dwHeight; y++)
2620                 {
2621                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2622
2623                     for (x = 0; x < ddsd.dwWidth;  x++)
2624                     {
2625                         DWORD color = *textureRow++;
2626
2627                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2628                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2629                         {
2630                             if (color & 0xffffff) diff_count++;
2631                         }
2632                         else
2633                         {
2634                             DWORD r = (color & 0xff0000) >> 16;
2635                             DWORD g = (color & 0xff00) >> 8;
2636                             DWORD b = (color & 0xff);
2637
2638                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2639                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2640                         }
2641                     }
2642                 }
2643
2644                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2645                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2646
2647                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2648
2649                 i++;
2650             }
2651
2652             loadpoint.x /= 2;
2653             loadpoint.y /= 2;
2654             loadrect.top /= 2;
2655             loadrect.left /= 2;
2656             loadrect.right = (loadrect.right + 1) / 2;
2657             loadrect.bottom = (loadrect.bottom + 1) / 2;
2658         }
2659
2660         for (i = 0; i < 2; i++)
2661         {
2662             for (i1 = 7; i1 >= 0; i1--)
2663             {
2664                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2665             }
2666         }
2667         memset(texture_levels, 0, sizeof(texture_levels));
2668     }
2669
2670     /* Test palette copying. */
2671     for (i = 0; i < 2; i++)
2672     {
2673         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2674         ddsd.dwSize = sizeof(ddsd);
2675         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2676         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2677         ddsd.dwWidth = 128;
2678         ddsd.dwHeight = 128;
2679         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2680         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2681         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2682         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2683         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2684         if (FAILED(hr)) goto out;
2685
2686         /* Check the number of created mipmaps */
2687         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2688         ddsd.dwSize = sizeof(ddsd);
2689         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2690         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2691         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2692         if (U2(ddsd).dwMipMapCount != 8) goto out;
2693
2694         for (i1 = 1; i1 < 8; i1++)
2695         {
2696             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2697             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2698             if (FAILED(hr)) goto out;
2699         }
2700     }
2701
2702     memset(table1, 0, sizeof(table1));
2703     for (i = 0; i < 3; i++)
2704     {
2705         table1[0].peBlue = i + 1;
2706         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2707         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2708         if (FAILED(hr))
2709         {
2710             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2711             goto out;
2712         }
2713     }
2714
2715     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2716     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2717
2718     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2719     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2720
2721     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2722     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2723
2724     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2725     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2726     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2727     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2728
2729     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2730     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2731
2732     memset(table1, 0, sizeof(table1));
2733     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2734     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2735     if (SUCCEEDED(hr))
2736     {
2737         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2738         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2739         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2740     }
2741
2742     /* Test colorkey copying. */
2743     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2744     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2745     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2746     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2747     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2748
2749     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2750     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2751
2752     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2753     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2754
2755     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2756     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2757     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2758         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2759
2760     out:
2761
2762     for (i = 0; i < 5; i++)
2763     {
2764         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2765     }
2766
2767     for (i = 0; i < 2; i++)
2768     {
2769         for (i1 = 7; i1 >= 0; i1--)
2770         {
2771             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2772         }
2773     }
2774
2775     for (i = 0; i < 2; i++)
2776         for (i1 = 5; i1 >= 0; i1--)
2777             for (i2 = 7; i2 >= 0; i2--)
2778             {
2779                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2780             }
2781 }
2782
2783 static void SetMaterialTest(void)
2784 {
2785     HRESULT rc;
2786
2787     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2788     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2789 }
2790
2791 static void ComputeSphereVisibility(void)
2792 {
2793     D3DMATRIX proj, view, world;
2794     D3DVALUE radius[3];
2795     D3DVECTOR center[3];
2796     DWORD result[3];
2797     HRESULT rc;
2798
2799     world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2800     world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2801     world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2802     world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2803
2804     view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2805     view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2806     view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2807     view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2808
2809     proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2810     proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2811     proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2812     proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2813
2814     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2815     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2816     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2817
2818     U1(center[0]).x=11.461533;
2819     U2(center[0]).y=-4.761727;
2820     U3(center[0]).z=-1.171646;
2821
2822     radius[0]=38.252632;
2823
2824     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2825
2826     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2827     ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2828
2829     U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
2830     radius[0]=4.354097;
2831     U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
2832     radius[1]=12.500704;
2833     U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
2834     radius[2]=17.251318;
2835
2836     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2837
2838     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2839     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2840     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2841     ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2842     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2843     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2844
2845     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2846     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2847     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2848     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2849
2850     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2851     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2852     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2853     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2854
2855     U1(center[0]).x=0.0;
2856     U2(center[0]).y=0.0;
2857     U3(center[0]).z=0.05;
2858
2859     radius[0]=0.04;
2860
2861     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2862     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2863
2864     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2865
2866     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2867     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2868
2869     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2870     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2871     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2872     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2873
2874     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2875
2876     U1(center[0]).x=0.0;
2877     U2(center[0]).y=0.0;
2878     U3(center[0]).z=0.5;
2879
2880     radius[0]=0.5;
2881
2882     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2883
2884     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2885     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2886
2887     U1(center[0]).x=0.0;
2888     U2(center[0]).y=0.0;
2889     U3(center[0]).z=0.0;
2890
2891     radius[0]=0.0;
2892
2893     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2894
2895     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2896     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2897
2898     U1(center[0]).x=-1.0;
2899     U2(center[0]).y=-1.0;
2900     U3(center[0]).z=0.50;
2901
2902     radius[0]=0.25;
2903
2904     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2905
2906     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2907     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
2908
2909     U1(center[0]).x=-20.0;
2910     U2(center[0]).y=0.0;
2911     U3(center[0]).z=0.50;
2912
2913     radius[0]=3.0;
2914
2915     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2916
2917     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2918     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2919
2920     U1(center[0]).x=20.0;
2921     U2(center[0]).y=0.0;
2922     U3(center[0]).z=0.50;
2923
2924     radius[0]=3.0f;
2925
2926     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2927
2928     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2929     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
2930
2931     U1(center[0]).x=0.0;
2932     U2(center[0]).y=-20.0;
2933     U3(center[0]).z=0.50;
2934
2935     radius[0]=3.0;
2936
2937     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2938
2939     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2940     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
2941
2942     U1(center[0]).x=0.0;
2943     U2(center[0]).y=20.0;
2944     U3(center[0]).z=0.5;
2945
2946     radius[0]=3.0;
2947
2948     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2949
2950     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2951     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
2952
2953     U1(center[0]).x=0.0;
2954     U2(center[0]).y=0.0;
2955     U3(center[0]).z=-20;
2956
2957     radius[0]=3.0;
2958
2959     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2960
2961     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2962     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
2963
2964     U1(center[0]).x=0.0;
2965     U2(center[0]).y=0.0;
2966     U3(center[0]).z=20.0;
2967
2968     radius[0]=3.0;
2969
2970     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2971
2972     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2973     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
2974 }
2975
2976 START_TEST(d3d)
2977 {
2978     init_function_pointers();
2979     if(!pDirectDrawCreateEx) {
2980         win_skip("function DirectDrawCreateEx not available\n");
2981         return;
2982     }
2983
2984     if(!CreateDirect3D()) {
2985         skip("Skipping d3d7 tests\n");
2986     } else {
2987         LightTest();
2988         ProcessVerticesTest();
2989         StateTest();
2990         SceneTest();
2991         LimitTest();
2992         D3D7EnumTest();
2993         SetMaterialTest();
2994         ComputeSphereVisibility();
2995         CapsTest();
2996         VertexBufferDescTest();
2997         D3D7_OldRenderStateTest();
2998         DeviceLoadTest();
2999         ReleaseDirect3D();
3000     }
3001
3002     if (!D3D1_createObjects()) {
3003         skip("Skipping d3d1 tests\n");
3004     } else {
3005         Direct3D1Test();
3006         TextureLoadTest();
3007         D3D1_releaseObjects();
3008     }
3009 }