ddraw/tests: Check some more return values (LLVM/Clang).
[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     /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
888     ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
889
890     /* We make two additional assumptions. */
891     ok(d3d7et.rgb, "No RGB Device enumerated.\n");
892
893     if(d3d7et.tnlhal)
894         ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
895 }
896
897 static void CapsTest(void)
898 {
899     IDirect3D3 *d3d3;
900     IDirect3D3 *d3d2;
901     IDirectDraw *dd1;
902     HRESULT hr;
903     UINT ver;
904
905     hr = DirectDrawCreate(NULL, &dd1, NULL);
906     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
907     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
908     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
909     ver = 3;
910     IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
911
912     IDirect3D3_Release(d3d3);
913     IDirectDraw_Release(dd1);
914
915     hr = DirectDrawCreate(NULL, &dd1, NULL);
916     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
917     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
918     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
919     ver = 2;
920     IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
921
922     IDirect3D2_Release(d3d2);
923     IDirectDraw_Release(dd1);
924 }
925
926 struct v_in {
927     float x, y, z;
928 };
929 struct v_out {
930     float x, y, z, rhw;
931 };
932
933 static BOOL D3D1_createObjects(void)
934 {
935     HRESULT hr;
936     DDSURFACEDESC ddsd;
937     D3DEXECUTEBUFFERDESC desc;
938     D3DVIEWPORT vp_data;
939
940     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
941     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
942     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
943     if (!DirectDraw1) {
944         return FALSE;
945     }
946
947     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
948     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
949
950     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
951     if (hr == E_NOINTERFACE) return FALSE;
952     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
953     if (!Direct3D1) {
954         return FALSE;
955     }
956
957     memset(&ddsd, 0, sizeof(ddsd));
958     ddsd.dwSize = sizeof(ddsd);
959     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
960     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
961     ddsd.dwWidth = 256;
962     ddsd.dwHeight = 256;
963     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
964     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface returned %#x.\n", hr);
965     if (!Surface1) {
966         skip("DDSCAPS_3DDEVICE surface not available\n");
967         return FALSE;
968     }
969
970     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
971     ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
972     if(!Direct3DDevice1) {
973         return FALSE;
974     }
975
976     memset(&desc, 0, sizeof(desc));
977     desc.dwSize = sizeof(desc);
978     desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
979     desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
980     desc.dwBufferSize = 128;
981     desc.lpData = NULL;
982     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
983     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
984     if(!ExecuteBuffer) {
985         return FALSE;
986     }
987
988     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
989     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
990     if(!Viewport) {
991         return FALSE;
992     }
993
994     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
995     ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
996
997     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
998     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
999     vp_data.dwSize = sizeof(vp_data);
1000     vp_data.dwX = 0;
1001     vp_data.dwY = 0;
1002     vp_data.dwWidth = 256;
1003     vp_data.dwHeight = 256;
1004     vp_data.dvScaleX = 1;
1005     vp_data.dvScaleY = 1;
1006     vp_data.dvMaxX = 256;
1007     vp_data.dvMaxY = 256;
1008     vp_data.dvMinZ = 0;
1009     vp_data.dvMaxZ = 1;
1010     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1011     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1012
1013     hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1014     ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1015     if (!Light)
1016         return FALSE;
1017
1018     return TRUE;
1019 }
1020
1021 static void D3D1_releaseObjects(void)
1022 {
1023     if (Light) IDirect3DLight_Release(Light);
1024     if (Viewport) IDirect3DViewport_Release(Viewport);
1025     if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1026     if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1027     if (Surface1) IDirectDrawSurface_Release(Surface1);
1028     if (Direct3D1) IDirect3D_Release(Direct3D1);
1029     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1030 }
1031
1032 #define SET_VP_DATA(vp_data) \
1033     vp_data.dwSize = sizeof(vp_data); \
1034     vp_data.dwX = 0; \
1035     vp_data.dwY = 0; \
1036     vp_data.dwWidth = 256; \
1037     vp_data.dwHeight = 256; \
1038     vp_data.dvMaxX = 256; \
1039     vp_data.dvMaxY = 256; \
1040     vp_data.dvScaleX = 5; \
1041     vp_data.dvScaleY = 5; \
1042     vp_data.dvMinZ = -25; \
1043     vp_data.dvMaxZ = 60;
1044
1045 static void Direct3D1Test(void)
1046 {
1047     HRESULT hr;
1048     D3DEXECUTEBUFFERDESC desc;
1049     D3DVIEWPORT vp_data;
1050     D3DINSTRUCTION *instr;
1051     D3DBRANCH *branch;
1052     IDirect3D *Direct3D_alt;
1053     IDirect3DLight *d3dlight;
1054     ULONG refcount;
1055     unsigned int idx = 0;
1056     static struct v_in testverts[] = {
1057         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
1058         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1059     };
1060     static struct v_in cliptest[] = {
1061         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
1062         {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1063     };
1064     static struct v_in offscreentest[] = {
1065         {128.1, 0.0, 0.0},
1066     };
1067     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1068     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1069     D3DTRANSFORMDATA transformdata;
1070     DWORD i = FALSE;
1071
1072     /* Interface consistency check. */
1073     hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1074     ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1075     if (hr == D3D_OK)
1076         ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1077
1078     memset(&desc, 0, sizeof(desc));
1079     desc.dwSize = sizeof(desc);
1080     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1081     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1082
1083     memset(desc.lpData, 0, 128);
1084     instr = desc.lpData;
1085     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1086     instr[idx].bSize = sizeof(*branch);
1087     instr[idx].wCount = 1;
1088     idx++;
1089     branch = (D3DBRANCH *) &instr[idx];
1090     branch->dwMask = 0x0;
1091     branch->dwValue = 1;
1092     branch->bNegate = TRUE;
1093     branch->dwOffset = 0;
1094     idx += (sizeof(*branch) / sizeof(*instr));
1095     instr[idx].bOpcode = D3DOP_EXIT;
1096     instr[idx].bSize = 0;
1097     instr[idx].wCount = 0;
1098     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1099     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1100
1101     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1102     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1103
1104     memset(&desc, 0, sizeof(desc));
1105     desc.dwSize = sizeof(desc);
1106
1107     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1108     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1109
1110     memset(desc.lpData, 0, 128);
1111     instr = desc.lpData;
1112     idx = 0;
1113     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1114     instr[idx].bSize = sizeof(*branch);
1115     instr[idx].wCount = 1;
1116     idx++;
1117     branch = (D3DBRANCH *) &instr[idx];
1118     branch->dwMask = 0x0;
1119     branch->dwValue = 1;
1120     branch->bNegate = TRUE;
1121     branch->dwOffset = 64;
1122     instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1123     instr[0].bOpcode = D3DOP_EXIT;
1124     instr[0].bSize = 0;
1125     instr[0].wCount = 0;
1126     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1127     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1128
1129     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1130     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1131
1132     /* Test rendering 0 triangles */
1133     memset(&desc, 0, sizeof(desc));
1134     desc.dwSize = sizeof(desc);
1135
1136     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1137     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1138
1139     memset(desc.lpData, 0, 128);
1140     instr = desc.lpData;
1141     idx = 0;
1142
1143     instr->bOpcode = D3DOP_TRIANGLE;
1144     instr->bSize = sizeof(D3DOP_TRIANGLE);
1145     instr->wCount = 0;
1146     instr++;
1147     instr->bOpcode = D3DOP_EXIT;
1148     instr->bSize = 0;
1149     instr->wCount = 0;
1150     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1151     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1152
1153     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1154     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1155
1156     memset(&transformdata, 0, sizeof(transformdata));
1157     transformdata.dwSize = sizeof(transformdata);
1158     transformdata.lpIn = testverts;
1159     transformdata.dwInSize = sizeof(testverts[0]);
1160     transformdata.lpOut = out;
1161     transformdata.dwOutSize = sizeof(out[0]);
1162
1163     transformdata.lpHOut = NULL;
1164     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1165                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1166                                              &i);
1167     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1168
1169     transformdata.lpHOut = outH;
1170     memset(outH, 0xcc, sizeof(outH));
1171     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1172                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1173                                              &i);
1174     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1175     ok(i == 0, "Offscreen is %d\n", i);
1176
1177     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1178         static const struct v_out cmp[] = {
1179             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1180             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1181         };
1182
1183         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1184            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1185            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1186            out[i].x, out[i].y, out[i].z, out[i].rhw,
1187            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1188     }
1189     for(i = 0; i < sizeof(outH); i++) {
1190         if(((unsigned char *) outH)[i] != 0xcc) {
1191             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1192             break;
1193         }
1194     }
1195
1196     SET_VP_DATA(vp_data);
1197     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1198     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1199     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1200                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1201                                              &i);
1202     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1203     ok(i == 0, "Offscreen is %d\n", i);
1204
1205     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1206         static const struct v_out cmp[] = {
1207             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1208             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1209         };
1210         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1211            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1212            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1213            out[i].x, out[i].y, out[i].z, out[i].rhw,
1214            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1215     }
1216
1217     SET_VP_DATA(vp_data);
1218     vp_data.dwX = 10;
1219     vp_data.dwY = 20;
1220     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1221     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1222     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1223                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1224                                              &i);
1225     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1226     ok(i == 0, "Offscreen is %d\n", i);
1227     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1228         static const struct v_out cmp[] = {
1229             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1230             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1231         };
1232         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1233            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1234            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1235            out[i].x, out[i].y, out[i].z, out[i].rhw,
1236            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1237     }
1238
1239     memset(out, 0xcc, sizeof(out));
1240     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1241                                              &transformdata, D3DTRANSFORM_CLIPPED,
1242                                              &i);
1243     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1244     ok(i == 0, "Offscreen is %d\n", i);
1245     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1246         static const D3DHVERTEX cmpH[] = {
1247             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1248             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1249             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1250         };
1251         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1252            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1253            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1254            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1255            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1256
1257         /* No scheme has been found behind those return values. It seems to be
1258          * whatever data windows has when throwing the vertex away. Modify the
1259          * input test vertices to test this more. Depending on the input data
1260          * it can happen that the z coord gets written into y, or similar things
1261          */
1262         if(0)
1263         {
1264             static const struct v_out cmp[] = {
1265                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1266                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1267             };
1268             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1269                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1270                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1271                out[i].x, out[i].y, out[i].z, out[i].rhw,
1272                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1273         }
1274     }
1275     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1276         ok(((DWORD *) out)[i] != 0xcccccccc,
1277                 "Regular output DWORD %d remained untouched\n", i);
1278     }
1279
1280     transformdata.lpIn = cliptest;
1281     transformdata.dwInSize = sizeof(cliptest[0]);
1282     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1283                                              &transformdata, D3DTRANSFORM_CLIPPED,
1284                                              &i);
1285     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1286     ok(i == 0, "Offscreen is %d\n", i);
1287     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1288         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1289         {
1290             0,
1291             0,
1292             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1293             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1294         };
1295         ok(Flags[i] == outH[i].dwFlags,
1296            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1297            outH[i].dwFlags, Flags[i]);
1298     }
1299
1300     SET_VP_DATA(vp_data);
1301     vp_data.dwWidth = 10;
1302     vp_data.dwHeight = 1000;
1303     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1304     i = 10;
1305     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1306     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1307                                              &transformdata, D3DTRANSFORM_CLIPPED,
1308                                              &i);
1309     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1310     ok(i == 0, "Offscreen is %d\n", i);
1311     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1312         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1313         {
1314             D3DCLIP_RIGHT,
1315             D3DCLIP_LEFT,
1316             D3DCLIP_RIGHT | D3DCLIP_BACK,
1317             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1318         };
1319         ok(Flags[i] == outH[i].dwFlags,
1320            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1321            outH[i].dwFlags, Flags[i]);
1322     }
1323
1324     SET_VP_DATA(vp_data);
1325     vp_data.dwWidth = 256;
1326     vp_data.dwHeight = 256;
1327     vp_data.dvScaleX = 1;
1328     vp_data.dvScaleY = 1;
1329     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1330     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1331     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1332                                              &transformdata, D3DTRANSFORM_CLIPPED,
1333                                              &i);
1334     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1335     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1336     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1337         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1338         {
1339             0,
1340             0,
1341             D3DCLIP_BACK,
1342             D3DCLIP_FRONT,
1343         };
1344         ok(Flags[i] == outH[i].dwFlags,
1345            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1346            outH[i].dwFlags, Flags[i]);
1347     }
1348
1349     /* Finally try to figure out how the DWORD dwOffscreen works.
1350      * Apparently no vertex is offscreen with clipping off,
1351      * and with clipping on the offscreen flag is set if only one vertex
1352      * is transformed, and this vertex is offscreen.
1353      */
1354     SET_VP_DATA(vp_data);
1355     vp_data.dwWidth = 5;
1356     vp_data.dwHeight = 5;
1357     vp_data.dvScaleX = 10000;
1358     vp_data.dvScaleY = 10000;
1359     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1360     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1361     transformdata.lpIn = cliptest;
1362     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1363                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1364                                              &i);
1365     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1366     ok(i == 0, "Offscreen is %d\n", i);
1367     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1368                                              &transformdata, D3DTRANSFORM_CLIPPED,
1369                                              &i);
1370     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1371     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1372     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1373                                              &transformdata, D3DTRANSFORM_CLIPPED,
1374                                              &i);
1375     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1376     ok(i == 0, "Offscreen is %d\n", i);
1377     transformdata.lpIn = cliptest + 1;
1378     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1379                                              &transformdata, D3DTRANSFORM_CLIPPED,
1380                                              &i);
1381     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1382     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1383
1384     transformdata.lpIn = offscreentest;
1385     transformdata.dwInSize = sizeof(offscreentest[0]);
1386     SET_VP_DATA(vp_data);
1387     vp_data.dwWidth = 257;
1388     vp_data.dwHeight = 257;
1389     vp_data.dvScaleX = 1;
1390     vp_data.dvScaleY = 1;
1391     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1392     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1393     i = 12345;
1394     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1395                                              &transformdata, D3DTRANSFORM_CLIPPED,
1396                                              &i);
1397     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1398     ok(i == 0, "Offscreen is %d\n", i);
1399     vp_data.dwWidth = 256;
1400     vp_data.dwHeight = 256;
1401     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1402     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
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             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2605
2606             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2607             ddsd2.dwSize = sizeof(ddsd2);
2608             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2609             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2610
2611             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2612             {
2613                 diff_count = 0;
2614
2615                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2616                 ddsd.dwSize = sizeof(ddsd);
2617                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2618                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2619                 if (FAILED(hr)) goto out;
2620
2621                 for (y = 0 ; y < ddsd.dwHeight; y++)
2622                 {
2623                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2624
2625                     for (x = 0; x < ddsd.dwWidth;  x++)
2626                     {
2627                         DWORD color = *textureRow++;
2628
2629                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2630                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2631                         {
2632                             if (color & 0xffffff) diff_count++;
2633                         }
2634                         else
2635                         {
2636                             DWORD r = (color & 0xff0000) >> 16;
2637                             DWORD g = (color & 0xff00) >> 8;
2638                             DWORD b = (color & 0xff);
2639
2640                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2641                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2642                         }
2643                     }
2644                 }
2645
2646                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2647                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2648
2649                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2650
2651                 i++;
2652             }
2653
2654             loadpoint.x /= 2;
2655             loadpoint.y /= 2;
2656             loadrect.top /= 2;
2657             loadrect.left /= 2;
2658             loadrect.right = (loadrect.right + 1) / 2;
2659             loadrect.bottom = (loadrect.bottom + 1) / 2;
2660         }
2661
2662         for (i = 0; i < 2; i++)
2663         {
2664             for (i1 = 7; i1 >= 0; i1--)
2665             {
2666                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2667             }
2668         }
2669         memset(texture_levels, 0, sizeof(texture_levels));
2670     }
2671
2672     /* Test palette copying. */
2673     for (i = 0; i < 2; i++)
2674     {
2675         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2676         ddsd.dwSize = sizeof(ddsd);
2677         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2678         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2679         ddsd.dwWidth = 128;
2680         ddsd.dwHeight = 128;
2681         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2682         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2683         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2684         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2685         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2686         if (FAILED(hr)) goto out;
2687
2688         /* Check the number of created mipmaps */
2689         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2690         ddsd.dwSize = sizeof(ddsd);
2691         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2692         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2693         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2694         if (U2(ddsd).dwMipMapCount != 8) goto out;
2695
2696         for (i1 = 1; i1 < 8; i1++)
2697         {
2698             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2699             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2700             if (FAILED(hr)) goto out;
2701         }
2702     }
2703
2704     memset(table1, 0, sizeof(table1));
2705     for (i = 0; i < 3; i++)
2706     {
2707         table1[0].peBlue = i + 1;
2708         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2709         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2710         if (FAILED(hr))
2711         {
2712             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2713             goto out;
2714         }
2715     }
2716
2717     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2718     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2719
2720     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2721     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2722
2723     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2724     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2725
2726     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2727     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2728     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2729     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2730
2731     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2732     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2733
2734     memset(table1, 0, sizeof(table1));
2735     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2736     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2737     if (SUCCEEDED(hr))
2738     {
2739         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2740         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2741         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2742     }
2743
2744     /* Test colorkey copying. */
2745     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2746     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2747     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2748     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2749     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2750
2751     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2752     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2753
2754     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2755     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2756
2757     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2758     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2759     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2760         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2761
2762     out:
2763
2764     for (i = 0; i < 5; i++)
2765     {
2766         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2767     }
2768
2769     for (i = 0; i < 2; i++)
2770     {
2771         for (i1 = 7; i1 >= 0; i1--)
2772         {
2773             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2774         }
2775     }
2776
2777     for (i = 0; i < 2; i++)
2778         for (i1 = 5; i1 >= 0; i1--)
2779             for (i2 = 7; i2 >= 0; i2--)
2780             {
2781                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2782             }
2783 }
2784
2785 static void SetMaterialTest(void)
2786 {
2787     HRESULT rc;
2788
2789     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2790     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2791 }
2792
2793 static void ComputeSphereVisibility(void)
2794 {
2795     D3DMATRIX proj, view, world;
2796     D3DVALUE radius[3];
2797     D3DVECTOR center[3];
2798     DWORD result[3];
2799     HRESULT rc;
2800
2801     world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2802     world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2803     world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2804     world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2805
2806     view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2807     view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2808     view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2809     view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2810
2811     proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2812     proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2813     proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2814     proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2815
2816     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2817     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2818     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2819
2820     U1(center[0]).x=11.461533;
2821     U2(center[0]).y=-4.761727;
2822     U3(center[0]).z=-1.171646;
2823
2824     radius[0]=38.252632;
2825
2826     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2827
2828     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2829     ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2830
2831     U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
2832     radius[0]=4.354097;
2833     U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
2834     radius[1]=12.500704;
2835     U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
2836     radius[2]=17.251318;
2837
2838     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2839
2840     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2841     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2842     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2843     ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2844     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2845     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2846
2847     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2848     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2849     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2850     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2851
2852     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2853     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2854     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2855     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2856
2857     U1(center[0]).x=0.0;
2858     U2(center[0]).y=0.0;
2859     U3(center[0]).z=0.05;
2860
2861     radius[0]=0.04;
2862
2863     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2864     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2865
2866     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2867
2868     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2869     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2870
2871     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2872     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2873     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2874     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2875
2876     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2877
2878     U1(center[0]).x=0.0;
2879     U2(center[0]).y=0.0;
2880     U3(center[0]).z=0.5;
2881
2882     radius[0]=0.5;
2883
2884     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2885
2886     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2887     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2888
2889     U1(center[0]).x=0.0;
2890     U2(center[0]).y=0.0;
2891     U3(center[0]).z=0.0;
2892
2893     radius[0]=0.0;
2894
2895     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2896
2897     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2898     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2899
2900     U1(center[0]).x=-1.0;
2901     U2(center[0]).y=-1.0;
2902     U3(center[0]).z=0.50;
2903
2904     radius[0]=0.25;
2905
2906     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2907
2908     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2909     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
2910
2911     U1(center[0]).x=-20.0;
2912     U2(center[0]).y=0.0;
2913     U3(center[0]).z=0.50;
2914
2915     radius[0]=3.0;
2916
2917     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2918
2919     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2920     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2921
2922     U1(center[0]).x=20.0;
2923     U2(center[0]).y=0.0;
2924     U3(center[0]).z=0.50;
2925
2926     radius[0]=3.0f;
2927
2928     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2929
2930     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2931     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
2932
2933     U1(center[0]).x=0.0;
2934     U2(center[0]).y=-20.0;
2935     U3(center[0]).z=0.50;
2936
2937     radius[0]=3.0;
2938
2939     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2940
2941     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2942     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
2943
2944     U1(center[0]).x=0.0;
2945     U2(center[0]).y=20.0;
2946     U3(center[0]).z=0.5;
2947
2948     radius[0]=3.0;
2949
2950     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2951
2952     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2953     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
2954
2955     U1(center[0]).x=0.0;
2956     U2(center[0]).y=0.0;
2957     U3(center[0]).z=-20;
2958
2959     radius[0]=3.0;
2960
2961     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2962
2963     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2964     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
2965
2966     U1(center[0]).x=0.0;
2967     U2(center[0]).y=0.0;
2968     U3(center[0]).z=20.0;
2969
2970     radius[0]=3.0;
2971
2972     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2973
2974     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2975     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
2976 }
2977
2978 static void SetRenderTargetTest(void)
2979 {
2980     HRESULT hr;
2981     IDirectDrawSurface7 *newrt, *oldrt;
2982     D3DVIEWPORT7 vp;
2983     DDSURFACEDESC2 ddsd;
2984     DWORD stateblock;
2985
2986     memset(&ddsd, 0, sizeof(ddsd));
2987     ddsd.dwSize = sizeof(ddsd);
2988     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2989     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
2990     ddsd.dwWidth = 64;
2991     ddsd.dwHeight = 64;
2992     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
2993     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
2994     if(FAILED(hr))
2995     {
2996         skip("Skipping SetRenderTarget test\n");
2997         return;
2998     }
2999
3000     memset(&vp, 0, sizeof(vp));
3001     vp.dwX = 10;
3002     vp.dwY = 10;
3003     vp.dwWidth = 246;
3004     vp.dwHeight = 246;
3005     vp.dvMinZ = 0.25;
3006     vp.dvMaxZ = 0.75;
3007     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3008     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3009
3010     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3011     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3012
3013     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3014     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3015     memset(&vp, 0xff, sizeof(vp));
3016     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3017     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3018     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3019     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3020     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3021     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3022     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.1\n", vp.dvMinZ);
3023     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.9\n", vp.dvMaxZ);
3024
3025     memset(&vp, 0, sizeof(vp));
3026     vp.dwX = 0;
3027     vp.dwY = 0;
3028     vp.dwWidth = 64;
3029     vp.dwHeight = 64;
3030     vp.dvMinZ = 0.0;
3031     vp.dvMaxZ = 1.0;
3032     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3033     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3034
3035     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3036     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3037     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3038     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3039
3040     /* Check this twice, before and after ending the stateblock */
3041     memset(&vp, 0xff, sizeof(vp));
3042     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3043     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3044     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3045     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3046     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3047     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3048     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3049     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3050
3051     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3052     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3053
3054     memset(&vp, 0xff, sizeof(vp));
3055     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3056     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3057     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3058     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3059     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3060     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3061     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3062     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3063
3064     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3065     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3066
3067     memset(&vp, 0, sizeof(vp));
3068     vp.dwX = 0;
3069     vp.dwY = 0;
3070     vp.dwWidth = 256;
3071     vp.dwHeight = 256;
3072     vp.dvMinZ = 0.0;
3073     vp.dvMaxZ = 0.0;
3074     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3075     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3076
3077     IDirectDrawSurface7_Release(oldrt);
3078     IDirectDrawSurface7_Release(newrt);
3079 }
3080
3081 START_TEST(d3d)
3082 {
3083     init_function_pointers();
3084     if(!pDirectDrawCreateEx) {
3085         win_skip("function DirectDrawCreateEx not available\n");
3086         return;
3087     }
3088
3089     if(!CreateDirect3D()) {
3090         skip("Skipping d3d7 tests\n");
3091     } else {
3092         LightTest();
3093         ProcessVerticesTest();
3094         StateTest();
3095         SceneTest();
3096         LimitTest();
3097         D3D7EnumTest();
3098         SetMaterialTest();
3099         ComputeSphereVisibility();
3100         CapsTest();
3101         VertexBufferDescTest();
3102         D3D7_OldRenderStateTest();
3103         DeviceLoadTest();
3104         SetRenderTargetTest();
3105         ReleaseDirect3D();
3106     }
3107
3108     if (!D3D1_createObjects()) {
3109         skip("Skipping d3d1 tests\n");
3110     } else {
3111         Direct3D1Test();
3112         TextureLoadTest();
3113         D3D1_releaseObjects();
3114     }
3115 }