ole32: Fix memory leaks in the storage test.
[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     IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
964     if (!Surface1) {
965         skip("DDSCAPS_3DDEVICE surface not available\n");
966         return FALSE;
967     }
968
969     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
970     ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
971     if(!Direct3DDevice1) {
972         return FALSE;
973     }
974
975     memset(&desc, 0, sizeof(desc));
976     desc.dwSize = sizeof(desc);
977     desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
978     desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
979     desc.dwBufferSize = 128;
980     desc.lpData = NULL;
981     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
982     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
983     if(!ExecuteBuffer) {
984         return FALSE;
985     }
986
987     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
988     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
989     if(!Viewport) {
990         return FALSE;
991     }
992
993     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
994     ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
995
996     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
997     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
998     vp_data.dwSize = sizeof(vp_data);
999     vp_data.dwX = 0;
1000     vp_data.dwY = 0;
1001     vp_data.dwWidth = 256;
1002     vp_data.dwHeight = 256;
1003     vp_data.dvScaleX = 1;
1004     vp_data.dvScaleY = 1;
1005     vp_data.dvMaxX = 256;
1006     vp_data.dvMaxY = 256;
1007     vp_data.dvMinZ = 0;
1008     vp_data.dvMaxZ = 1;
1009     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1010     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1011
1012     hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1013     ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1014     if (!Light)
1015         return FALSE;
1016
1017     return TRUE;
1018 }
1019
1020 static void D3D1_releaseObjects(void)
1021 {
1022     if (Light) IDirect3DLight_Release(Light);
1023     if (Viewport) IDirect3DViewport_Release(Viewport);
1024     if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1025     if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1026     if (Surface1) IDirectDrawSurface_Release(Surface1);
1027     if (Direct3D1) IDirect3D_Release(Direct3D1);
1028     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1029 }
1030
1031 #define SET_VP_DATA(vp_data) \
1032     vp_data.dwSize = sizeof(vp_data); \
1033     vp_data.dwX = 0; \
1034     vp_data.dwY = 0; \
1035     vp_data.dwWidth = 256; \
1036     vp_data.dwHeight = 256; \
1037     vp_data.dvMaxX = 256; \
1038     vp_data.dvMaxY = 256; \
1039     vp_data.dvScaleX = 5; \
1040     vp_data.dvScaleY = 5; \
1041     vp_data.dvMinZ = -25; \
1042     vp_data.dvMaxZ = 60;
1043
1044 static void Direct3D1Test(void)
1045 {
1046     HRESULT hr;
1047     D3DEXECUTEBUFFERDESC desc;
1048     D3DVIEWPORT vp_data;
1049     D3DINSTRUCTION *instr;
1050     D3DBRANCH *branch;
1051     IDirect3D *Direct3D_alt;
1052     IDirect3DLight *d3dlight;
1053     ULONG refcount;
1054     unsigned int idx = 0;
1055     static struct v_in testverts[] = {
1056         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
1057         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1058     };
1059     static struct v_in cliptest[] = {
1060         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
1061         {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1062     };
1063     static struct v_in offscreentest[] = {
1064         {128.1, 0.0, 0.0},
1065     };
1066     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1067     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1068     D3DTRANSFORMDATA transformdata;
1069     DWORD i = FALSE;
1070
1071     /* Interface consistency check. */
1072     hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1073     ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1074     if (hr == D3D_OK)
1075         ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1076
1077     memset(&desc, 0, sizeof(desc));
1078     desc.dwSize = sizeof(desc);
1079     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1080     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1081
1082     memset(desc.lpData, 0, 128);
1083     instr = desc.lpData;
1084     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1085     instr[idx].bSize = sizeof(*branch);
1086     instr[idx].wCount = 1;
1087     idx++;
1088     branch = (D3DBRANCH *) &instr[idx];
1089     branch->dwMask = 0x0;
1090     branch->dwValue = 1;
1091     branch->bNegate = TRUE;
1092     branch->dwOffset = 0;
1093     idx += (sizeof(*branch) / sizeof(*instr));
1094     instr[idx].bOpcode = D3DOP_EXIT;
1095     instr[idx].bSize = 0;
1096     instr[idx].wCount = 0;
1097     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1098     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1099
1100     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1101     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1102
1103     memset(&desc, 0, sizeof(desc));
1104     desc.dwSize = sizeof(desc);
1105
1106     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1107     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1108
1109     memset(desc.lpData, 0, 128);
1110     instr = desc.lpData;
1111     idx = 0;
1112     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1113     instr[idx].bSize = sizeof(*branch);
1114     instr[idx].wCount = 1;
1115     idx++;
1116     branch = (D3DBRANCH *) &instr[idx];
1117     branch->dwMask = 0x0;
1118     branch->dwValue = 1;
1119     branch->bNegate = TRUE;
1120     branch->dwOffset = 64;
1121     instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1122     instr[0].bOpcode = D3DOP_EXIT;
1123     instr[0].bSize = 0;
1124     instr[0].wCount = 0;
1125     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1126     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1127
1128     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1129     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1130
1131     /* Test rendering 0 triangles */
1132     memset(&desc, 0, sizeof(desc));
1133     desc.dwSize = sizeof(desc);
1134
1135     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1136     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1137
1138     memset(desc.lpData, 0, 128);
1139     instr = desc.lpData;
1140     idx = 0;
1141
1142     instr->bOpcode = D3DOP_TRIANGLE;
1143     instr->bSize = sizeof(D3DOP_TRIANGLE);
1144     instr->wCount = 0;
1145     instr++;
1146     instr->bOpcode = D3DOP_EXIT;
1147     instr->bSize = 0;
1148     instr->wCount = 0;
1149     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1150     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1151
1152     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1153     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1154
1155     memset(&transformdata, 0, sizeof(transformdata));
1156     transformdata.dwSize = sizeof(transformdata);
1157     transformdata.lpIn = testverts;
1158     transformdata.dwInSize = sizeof(testverts[0]);
1159     transformdata.lpOut = out;
1160     transformdata.dwOutSize = sizeof(out[0]);
1161
1162     transformdata.lpHOut = NULL;
1163     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1164                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1165                                              &i);
1166     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1167
1168     transformdata.lpHOut = outH;
1169     memset(outH, 0xcc, sizeof(outH));
1170     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1171                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1172                                              &i);
1173     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1174     ok(i == 0, "Offscreen is %d\n", i);
1175
1176     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1177         static const struct v_out cmp[] = {
1178             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1179             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1180         };
1181
1182         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1183            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1184            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1185            out[i].x, out[i].y, out[i].z, out[i].rhw,
1186            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1187     }
1188     for(i = 0; i < sizeof(outH); i++) {
1189         if(((unsigned char *) outH)[i] != 0xcc) {
1190             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1191             break;
1192         }
1193     }
1194
1195     SET_VP_DATA(vp_data);
1196     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1197     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1198     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1199                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1200                                              &i);
1201     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1202     ok(i == 0, "Offscreen is %d\n", i);
1203
1204     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1205         static const struct v_out cmp[] = {
1206             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1207             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1208         };
1209         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1210            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1211            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1212            out[i].x, out[i].y, out[i].z, out[i].rhw,
1213            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1214     }
1215
1216     SET_VP_DATA(vp_data);
1217     vp_data.dwX = 10;
1218     vp_data.dwY = 20;
1219     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1220     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1221     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1222                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1223                                              &i);
1224     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1225     ok(i == 0, "Offscreen is %d\n", i);
1226     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1227         static const struct v_out cmp[] = {
1228             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1229             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1230         };
1231         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1232            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1233            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1234            out[i].x, out[i].y, out[i].z, out[i].rhw,
1235            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1236     }
1237
1238     memset(out, 0xcc, sizeof(out));
1239     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1240                                              &transformdata, D3DTRANSFORM_CLIPPED,
1241                                              &i);
1242     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1243     ok(i == 0, "Offscreen is %d\n", i);
1244     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1245         static const D3DHVERTEX cmpH[] = {
1246             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1247             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1248             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1249         };
1250         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1251            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1252            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1253            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1254            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1255
1256         /* No scheme has been found behind those return values. It seems to be
1257          * whatever data windows has when throwing the vertex away. Modify the
1258          * input test vertices to test this more. Depending on the input data
1259          * it can happen that the z coord gets written into y, or similar things
1260          */
1261         if(0)
1262         {
1263             static const struct v_out cmp[] = {
1264                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1265                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1266             };
1267             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1268                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1269                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1270                out[i].x, out[i].y, out[i].z, out[i].rhw,
1271                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1272         }
1273     }
1274     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1275         ok(((DWORD *) out)[i] != 0xcccccccc,
1276                 "Regular output DWORD %d remained untouched\n", i);
1277     }
1278
1279     transformdata.lpIn = cliptest;
1280     transformdata.dwInSize = sizeof(cliptest[0]);
1281     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1282                                              &transformdata, D3DTRANSFORM_CLIPPED,
1283                                              &i);
1284     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1285     ok(i == 0, "Offscreen is %d\n", i);
1286     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1287         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1288         {
1289             0,
1290             0,
1291             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1292             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1293         };
1294         ok(Flags[i] == outH[i].dwFlags,
1295            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1296            outH[i].dwFlags, Flags[i]);
1297     }
1298
1299     SET_VP_DATA(vp_data);
1300     vp_data.dwWidth = 10;
1301     vp_data.dwHeight = 1000;
1302     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1303     i = 10;
1304     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1305     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1306                                              &transformdata, D3DTRANSFORM_CLIPPED,
1307                                              &i);
1308     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1309     ok(i == 0, "Offscreen is %d\n", i);
1310     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1311         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1312         {
1313             D3DCLIP_RIGHT,
1314             D3DCLIP_LEFT,
1315             D3DCLIP_RIGHT | D3DCLIP_BACK,
1316             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1317         };
1318         ok(Flags[i] == outH[i].dwFlags,
1319            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1320            outH[i].dwFlags, Flags[i]);
1321     }
1322
1323     SET_VP_DATA(vp_data);
1324     vp_data.dwWidth = 256;
1325     vp_data.dwHeight = 256;
1326     vp_data.dvScaleX = 1;
1327     vp_data.dvScaleY = 1;
1328     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1329     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1330     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1331                                              &transformdata, D3DTRANSFORM_CLIPPED,
1332                                              &i);
1333     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1334     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1335     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1336         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1337         {
1338             0,
1339             0,
1340             D3DCLIP_BACK,
1341             D3DCLIP_FRONT,
1342         };
1343         ok(Flags[i] == outH[i].dwFlags,
1344            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1345            outH[i].dwFlags, Flags[i]);
1346     }
1347
1348     /* Finally try to figure out how the DWORD dwOffscreen works.
1349      * Apparently no vertex is offscreen with clipping off,
1350      * and with clipping on the offscreen flag is set if only one vertex
1351      * is transformed, and this vertex is offscreen.
1352      */
1353     SET_VP_DATA(vp_data);
1354     vp_data.dwWidth = 5;
1355     vp_data.dwHeight = 5;
1356     vp_data.dvScaleX = 10000;
1357     vp_data.dvScaleY = 10000;
1358     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1359     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1360     transformdata.lpIn = cliptest;
1361     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1362                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1363                                              &i);
1364     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1365     ok(i == 0, "Offscreen is %d\n", i);
1366     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1367                                              &transformdata, D3DTRANSFORM_CLIPPED,
1368                                              &i);
1369     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1370     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1371     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1372                                              &transformdata, D3DTRANSFORM_CLIPPED,
1373                                              &i);
1374     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1375     ok(i == 0, "Offscreen is %d\n", i);
1376     transformdata.lpIn = cliptest + 1;
1377     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1378                                              &transformdata, D3DTRANSFORM_CLIPPED,
1379                                              &i);
1380     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1381     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1382
1383     transformdata.lpIn = offscreentest;
1384     transformdata.dwInSize = sizeof(offscreentest[0]);
1385     SET_VP_DATA(vp_data);
1386     vp_data.dwWidth = 257;
1387     vp_data.dwHeight = 257;
1388     vp_data.dvScaleX = 1;
1389     vp_data.dvScaleY = 1;
1390     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1391     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1392     i = 12345;
1393     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1394                                              &transformdata, D3DTRANSFORM_CLIPPED,
1395                                              &i);
1396     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1397     ok(i == 0, "Offscreen is %d\n", i);
1398     vp_data.dwWidth = 256;
1399     vp_data.dwHeight = 256;
1400     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1401     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1402     i = 12345;
1403     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1404                                              &transformdata, D3DTRANSFORM_CLIPPED,
1405                                              &i);
1406     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1407     ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1408
1409     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1410                                              &transformdata, 0,
1411                                              &i);
1412     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1413
1414     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1415     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1416
1417     hr = IDirect3DViewport_AddLight(Viewport, Light);
1418     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1419     refcount = getRefcount((IUnknown*) Light);
1420     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1421
1422     hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1423     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1424     ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1425     refcount = getRefcount((IUnknown*) Light);
1426     ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1427
1428     hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1429     ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1430     refcount = getRefcount((IUnknown*) Light);
1431     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1432
1433     IDirect3DLight_Release(Light);
1434 }
1435
1436 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1437 {
1438     int i;
1439
1440     for (i = 0; i < 256; i++) {
1441        if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1442            table1[i].peBlue != table2[i].peBlue) return FALSE;
1443     }
1444
1445     return TRUE;
1446 }
1447
1448 /* test palette handling in IDirect3DTexture_Load */
1449 static void TextureLoadTest(void)
1450 {
1451     IDirectDrawSurface *TexSurface = NULL;
1452     IDirect3DTexture *Texture = NULL;
1453     IDirectDrawSurface *TexSurface2 = NULL;
1454     IDirect3DTexture *Texture2 = NULL;
1455     IDirectDrawPalette *palette = NULL;
1456     IDirectDrawPalette *palette2 = NULL;
1457     IDirectDrawPalette *palette_tmp = NULL;
1458     PALETTEENTRY table1[256], table2[256], table_tmp[256];
1459     HRESULT hr;
1460     DDSURFACEDESC ddsd;
1461     int i;
1462
1463     memset (&ddsd, 0, sizeof (ddsd));
1464     ddsd.dwSize = sizeof (ddsd);
1465     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1466     ddsd.dwHeight = 128;
1467     ddsd.dwWidth = 128;
1468     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1469     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1470     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1471     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1472
1473     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1474     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1475     if (FAILED(hr)) {
1476         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1477         goto cleanup;
1478     }
1479
1480     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1481                 (void *)&Texture);
1482     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1483     if (FAILED(hr)) {
1484         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1485         goto cleanup;
1486     }
1487
1488     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1489     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1490     if (FAILED(hr)) {
1491         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1492         goto cleanup;
1493     }
1494
1495     hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1496                 (void *)&Texture2);
1497     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1498     if (FAILED(hr)) {
1499         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1500         goto cleanup;
1501     }
1502
1503     /* test load of Texture to Texture */
1504     hr = IDirect3DTexture_Load(Texture, Texture);
1505     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1506
1507     /* test Load when both textures have no palette */
1508     hr = IDirect3DTexture_Load(Texture2, Texture);
1509     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1510
1511     for (i = 0; i < 256; i++) {
1512         table1[i].peRed = i;
1513         table1[i].peGreen = i;
1514         table1[i].peBlue = i;
1515         table1[i].peFlags = 0;
1516     }
1517
1518     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1519     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1520     if (FAILED(hr)) {
1521         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1522         goto cleanup;
1523     }
1524
1525     /* test Load when source texture has palette and destination has no palette */
1526     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1527     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1528     hr = IDirect3DTexture_Load(Texture2, Texture);
1529     ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1530
1531     for (i = 0; i < 256; i++) {
1532         table2[i].peRed = 255 - i;
1533         table2[i].peGreen = 255 - i;
1534         table2[i].peBlue = 255 - i;
1535         table2[i].peFlags = 0;
1536     }
1537
1538     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1539     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1540     if (FAILED(hr)) {
1541         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1542         goto cleanup;
1543     }
1544
1545     /* test Load when source has no palette and destination has a palette */
1546     hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1547     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1548     hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1549     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1550     hr = IDirect3DTexture_Load(Texture2, Texture);
1551     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1552     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1553     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1554     if (!palette_tmp) {
1555         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1556         goto cleanup;
1557     } else {
1558         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1559         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1560         ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1561         IDirectDrawPalette_Release(palette_tmp);
1562     }
1563
1564     /* test Load when both textures have palettes */
1565     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1566     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1567     hr = IDirect3DTexture_Load(Texture2, Texture);
1568     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1569     hr = IDirect3DTexture_Load(Texture2, Texture);
1570     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1571     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1572     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1573     if (!palette_tmp) {
1574         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1575         goto cleanup;
1576     } else {
1577         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1578         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1579         ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1580         IDirectDrawPalette_Release(palette_tmp);
1581     }
1582
1583     cleanup:
1584
1585     if (palette) IDirectDrawPalette_Release(palette);
1586     if (palette2) IDirectDrawPalette_Release(palette2);
1587     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1588     if (Texture) IDirect3DTexture_Release(Texture);
1589     if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1590     if (Texture2) IDirect3DTexture_Release(Texture2);
1591 }
1592
1593 static void VertexBufferDescTest(void)
1594 {
1595     HRESULT rc;
1596     D3DVERTEXBUFFERDESC desc;
1597     union mem_t
1598     {
1599         D3DVERTEXBUFFERDESC desc2;
1600         unsigned char buffer[512];
1601     } mem;
1602
1603     memset(&desc, 0, sizeof(desc));
1604     desc.dwSize = sizeof(desc);
1605     desc.dwCaps = 0;
1606     desc.dwFVF = D3DFVF_XYZ;
1607     desc.dwNumVertices = 1;
1608     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1609     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1610     if (!lpVBufSrc)
1611     {
1612         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1613         goto out;
1614     }
1615
1616     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1617     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1618     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1619     if(rc != D3D_OK)
1620         skip("GetVertexBuffer Failed!\n");
1621     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1622     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1623     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1624     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1625     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1626
1627     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1628     mem.desc2.dwSize = 0;
1629     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1630     if(rc != D3D_OK)
1631         skip("GetVertexBuffer Failed!\n");
1632     ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1633     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1634     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1635     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1636     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1637
1638     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1639     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1640     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1641     if(rc != D3D_OK)
1642         skip("GetVertexBuffer Failed!\n");
1643     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1644     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1645     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1646     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1647     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1648
1649 out:
1650     IDirect3DVertexBuffer7_Release(lpVBufSrc);
1651 }
1652
1653 static void D3D7_OldRenderStateTest(void)
1654 {
1655     HRESULT rc;
1656     DWORD val;
1657
1658     /* Test reaction to some deprecated states in D3D7.
1659
1660      * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1661      * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1662      * need not to be handled in D3D7.
1663      */
1664     todo_wine {
1665         rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1666         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1667
1668         rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1669         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1670
1671         rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1672         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1673
1674         rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1675         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1676     }
1677 }
1678
1679 #define IS_VALUE_NEAR(a, b)    ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1680 #define MIN(a, b)    ((a) < (b) ? (a) : (b))
1681
1682 static void DeviceLoadTest(void)
1683 {
1684     DDSURFACEDESC2 ddsd;
1685     IDirectDrawSurface7 *texture_levels[2][8];
1686     IDirectDrawSurface7 *cube_face_levels[2][6][8];
1687     DWORD flags;
1688     HRESULT hr;
1689     DDBLTFX ddbltfx;
1690     RECT loadrect;
1691     POINT loadpoint;
1692     int i, i1, i2;
1693     unsigned diff_count = 0, diff_count2 = 0;
1694     unsigned x, y;
1695     BOOL load_mip_subset_broken = FALSE;
1696     IDirectDrawPalette *palettes[5];
1697     PALETTEENTRY table1[256];
1698     DDCOLORKEY ddckey;
1699     D3DDEVICEDESC7 d3dcaps;
1700
1701     /* Test loading of texture subrectangle with a mipmap surface. */
1702     memset(texture_levels, 0, sizeof(texture_levels));
1703     memset(cube_face_levels, 0, sizeof(cube_face_levels));
1704     memset(palettes, 0, sizeof(palettes));
1705
1706     for (i = 0; i < 2; i++)
1707     {
1708         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1709         ddsd.dwSize = sizeof(ddsd);
1710         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1711         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1712         ddsd.dwWidth = 128;
1713         ddsd.dwHeight = 128;
1714         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1715         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1716         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1717         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1718         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1719         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1720         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1721         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1722         if (FAILED(hr)) goto out;
1723
1724         /* Check the number of created mipmaps */
1725         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1726         ddsd.dwSize = sizeof(ddsd);
1727         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1728         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1729         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1730         if (U2(ddsd).dwMipMapCount != 8) goto out;
1731
1732         for (i1 = 1; i1 < 8; i1++)
1733         {
1734             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1735             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1736             if (FAILED(hr)) goto out;
1737         }
1738     }
1739
1740     for (i1 = 0; i1 < 8; i1++)
1741     {
1742         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1743         ddsd.dwSize = sizeof(ddsd);
1744         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1745         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1746         if (FAILED(hr)) goto out;
1747
1748         for (y = 0 ; y < ddsd.dwHeight; y++)
1749         {
1750             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1751
1752             for (x = 0; x < ddsd.dwWidth;  x++)
1753             {
1754                 /* x stored in green component, y in blue. */
1755                 DWORD color = 0xff0000 | (x << 8)  | y;
1756                 *textureRow++ = color;
1757             }
1758         }
1759
1760         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1761         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1762     }
1763
1764     for (i1 = 0; i1 < 8; i1++)
1765     {
1766         memset(&ddbltfx, 0, sizeof(ddbltfx));
1767         ddbltfx.dwSize = sizeof(ddbltfx);
1768         U5(ddbltfx).dwFillColor = 0;
1769         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1770         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1771     }
1772
1773     /* First test some broken coordinates. */
1774     loadpoint.x = loadpoint.y = 0;
1775     loadrect.left = 0;
1776     loadrect.top = 0;
1777     loadrect.right = 0;
1778     loadrect.bottom = 0;
1779     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1780     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1781
1782     loadpoint.x = loadpoint.y = 50;
1783     loadrect.left = 0;
1784     loadrect.top = 0;
1785     loadrect.right = 100;
1786     loadrect.bottom = 100;
1787     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1788     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1789
1790     /* Test actual loading. */
1791     loadpoint.x = loadpoint.y = 31;
1792     loadrect.left = 30;
1793     loadrect.top = 20;
1794     loadrect.right = 93;
1795     loadrect.bottom = 52;
1796
1797     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1798     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1799
1800     for (i1 = 0; i1 < 8; i1++)
1801     {
1802         diff_count = 0;
1803         diff_count2 = 0;
1804
1805         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1806         ddsd.dwSize = sizeof(ddsd);
1807         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1808         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1809         if (FAILED(hr)) goto out;
1810
1811         for (y = 0 ; y < ddsd.dwHeight; y++)
1812         {
1813             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1814
1815             for (x = 0; x < ddsd.dwWidth;  x++)
1816             {
1817                 DWORD color = *textureRow++;
1818
1819                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1820                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1821                 {
1822                     if (color & 0xffffff) diff_count++;
1823                 }
1824                 else
1825                 {
1826                     DWORD r = (color & 0xff0000) >> 16;
1827                     DWORD g = (color & 0xff00) >> 8;
1828                     DWORD b = (color & 0xff);
1829
1830                     if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1831                 }
1832
1833                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1834                    technically be correct as it's not precisely defined by docs. */
1835                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1836                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1837                 {
1838                     if (color & 0xffffff) diff_count2++;
1839                 }
1840                 else
1841                 {
1842                     DWORD r = (color & 0xff0000) >> 16;
1843                     DWORD g = (color & 0xff00) >> 8;
1844                     DWORD b = (color & 0xff);
1845
1846                     if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1847                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1848                 }
1849             }
1850         }
1851
1852         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1853         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1854
1855         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1856                 MIN(diff_count, diff_count2), i1);
1857
1858         loadpoint.x /= 2;
1859         loadpoint.y /= 2;
1860         loadrect.top /= 2;
1861         loadrect.left /= 2;
1862         loadrect.right = (loadrect.right + 1) / 2;
1863         loadrect.bottom = (loadrect.bottom + 1) / 2;
1864     }
1865
1866     /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1867      * qemu Win98 / directx7 / RGB software rasterizer):
1868      * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1869     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1870     */
1871
1872     /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1873     for (i = 0; i < 2; i++)
1874     {
1875         for (i1 = 7; i1 >= 0; i1--)
1876         {
1877             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1878         }
1879     }
1880     memset(texture_levels, 0, sizeof(texture_levels));
1881
1882     /* Test texture size mismatch. */
1883     for (i = 0; i < 2; i++)
1884     {
1885         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1886         ddsd.dwSize = sizeof(ddsd);
1887         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1888         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1889         ddsd.dwWidth = i ? 256 : 128;
1890         ddsd.dwHeight = 128;
1891         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1892         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1893         if (FAILED(hr)) goto out;
1894     }
1895
1896     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1897     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1898
1899     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1900     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1901
1902     IDirectDrawSurface7_Release(texture_levels[0][0]);
1903     IDirectDrawSurface7_Release(texture_levels[1][0]);
1904     memset(texture_levels, 0, sizeof(texture_levels));
1905
1906     memset(&d3dcaps, 0, sizeof(d3dcaps));
1907     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1908     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1909
1910     if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1911     {
1912         skip("No cubemap support\n");
1913     }
1914     else
1915     {
1916         /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1917         for (i = 0; i < 2; i++)
1918         {
1919             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1920             ddsd.dwSize = sizeof(ddsd);
1921             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1922             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1923             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1924             ddsd.dwWidth = 128;
1925             ddsd.dwHeight = 128;
1926             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1927             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1928             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1929             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1930             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1931             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1932             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1933             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1934             if (FAILED(hr)) goto out;
1935
1936             flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1937             for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1938             {
1939                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1940                 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1941                 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1942                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1943                 if (FAILED(hr)) goto out;
1944             }
1945
1946             for (i1 = 0; i1 < 6; i1++)
1947             {
1948                 /* Check the number of created mipmaps */
1949                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1950                 ddsd.dwSize = sizeof(ddsd);
1951                 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1952                 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1953                 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1954                 if (U2(ddsd).dwMipMapCount != 8) goto out;
1955
1956                 for (i2 = 1; i2 < 8; i2++)
1957                 {
1958                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1959                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1960                     hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1961                     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1962                     if (FAILED(hr)) goto out;
1963                 }
1964             }
1965         }
1966
1967         for (i = 0; i < 6; i++)
1968             for (i1 = 0; i1 < 8; i1++)
1969             {
1970                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1971                 ddsd.dwSize = sizeof(ddsd);
1972                 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1973                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1974                 if (FAILED(hr)) goto out;
1975
1976                 for (y = 0 ; y < ddsd.dwHeight; y++)
1977                 {
1978                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1979
1980                     for (x = 0; x < ddsd.dwWidth;  x++)
1981                     {
1982                         /* face number in low 4 bits of red, x stored in green component, y in blue. */
1983                         DWORD color = 0xf00000 | (i << 16) | (x << 8)  | y;
1984                         *textureRow++ = color;
1985                     }
1986                 }
1987
1988                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1989                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1990             }
1991
1992         for (i = 0; i < 6; i++)
1993             for (i1 = 0; i1 < 8; i1++)
1994             {
1995                 memset(&ddbltfx, 0, sizeof(ddbltfx));
1996                 ddbltfx.dwSize = sizeof(ddbltfx);
1997                 U5(ddbltfx).dwFillColor = 0;
1998                 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1999                 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2000             }
2001
2002         loadpoint.x = loadpoint.y = 10;
2003         loadrect.left = 30;
2004         loadrect.top = 20;
2005         loadrect.right = 93;
2006         loadrect.bottom = 52;
2007
2008         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2009                                         DDSCAPS2_CUBEMAP_ALLFACES);
2010         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2011
2012         for (i = 0; i < 6; i++)
2013         {
2014             loadpoint.x = loadpoint.y = 10;
2015             loadrect.left = 30;
2016             loadrect.top = 20;
2017             loadrect.right = 93;
2018             loadrect.bottom = 52;
2019
2020             for (i1 = 0; i1 < 8; i1++)
2021             {
2022                 diff_count = 0;
2023                 diff_count2 = 0;
2024
2025                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2026                 ddsd.dwSize = sizeof(ddsd);
2027                 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2028                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2029                 if (FAILED(hr)) goto out;
2030
2031                 for (y = 0 ; y < ddsd.dwHeight; y++)
2032                 {
2033                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2034
2035                     for (x = 0; x < ddsd.dwWidth;  x++)
2036                     {
2037                         DWORD color = *textureRow++;
2038
2039                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2040                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2041                         {
2042                             if (color & 0xffffff) diff_count++;
2043                         }
2044                         else
2045                         {
2046                             DWORD r = (color & 0xff0000) >> 16;
2047                             DWORD g = (color & 0xff00) >> 8;
2048                             DWORD b = (color & 0xff);
2049
2050                             if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2051                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2052                         }
2053
2054                         /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2055                         technically be correct as it's not precisely defined by docs. */
2056                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2057                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2058                         {
2059                             if (color & 0xffffff) diff_count2++;
2060                         }
2061                         else
2062                         {
2063                             DWORD r = (color & 0xff0000) >> 16;
2064                             DWORD g = (color & 0xff00) >> 8;
2065                             DWORD b = (color & 0xff);
2066
2067                             if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2068                                 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2069                         }
2070                     }
2071                 }
2072
2073                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2074                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2075
2076                 ok(diff_count == 0 || diff_count2 == 0,
2077                     "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2078                     MIN(diff_count, diff_count2), i, i1);
2079
2080                 loadpoint.x /= 2;
2081                 loadpoint.y /= 2;
2082                 loadrect.top /= 2;
2083                 loadrect.left /= 2;
2084                 loadrect.right = (loadrect.right + 1) / 2;
2085                 loadrect.bottom = (loadrect.bottom + 1) / 2;
2086             }
2087         }
2088
2089         for (i = 0; i < 2; i++)
2090             for (i1 = 5; i1 >= 0; i1--)
2091                 for (i2 = 7; i2 >= 0; i2--)
2092                 {
2093                     if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2094                 }
2095         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2096
2097         /* Test cubemap loading from regular texture. */
2098         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2099         ddsd.dwSize = sizeof(ddsd);
2100         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2101         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2102         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2103         ddsd.dwWidth = 128;
2104         ddsd.dwHeight = 128;
2105         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2106         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2107         if (FAILED(hr)) goto out;
2108
2109         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2110         ddsd.dwSize = sizeof(ddsd);
2111         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2112         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2113         ddsd.dwWidth = 128;
2114         ddsd.dwHeight = 128;
2115         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2116         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2117         if (FAILED(hr)) goto out;
2118
2119         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2120                                         DDSCAPS2_CUBEMAP_ALLFACES);
2121         ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2122
2123         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2124         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2125         IDirectDrawSurface7_Release(texture_levels[0][0]);
2126         memset(texture_levels, 0, sizeof(texture_levels));
2127
2128         /* Test cubemap loading from cubemap with different number of faces. */
2129         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2130         ddsd.dwSize = sizeof(ddsd);
2131         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2132         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2133         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2134         ddsd.dwWidth = 128;
2135         ddsd.dwHeight = 128;
2136         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2137         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2138         if (FAILED(hr)) goto out;
2139
2140         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2141         ddsd.dwSize = sizeof(ddsd);
2142         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2143         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2144         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2145         ddsd.dwWidth = 128;
2146         ddsd.dwHeight = 128;
2147         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2148         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2149         if (FAILED(hr)) goto out;
2150
2151         /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2152             (the above created cubemaps will have all faces. */
2153         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2154                                         DDSCAPS2_CUBEMAP_ALLFACES);
2155         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2156
2157         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2158                                         DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2159         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2160
2161         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2162                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2163         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2164
2165         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2166                                         DDSCAPS2_CUBEMAP_ALLFACES);
2167         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2168
2169         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2170                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2171         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2172
2173         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2174                                         DDSCAPS2_CUBEMAP_POSITIVEZ);
2175         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2176
2177         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2178         IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2179         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2180     }
2181
2182     /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2183     for (i = 0; i < 2; i++)
2184     {
2185         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2186         ddsd.dwSize = sizeof(ddsd);
2187         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2188         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2189         ddsd.dwWidth = 128;
2190         ddsd.dwHeight = 128;
2191         U2(ddsd).dwMipMapCount = i ? 4 : 8;
2192         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2193         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2194         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2195         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2196         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2197         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2198         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2199         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2200         if (FAILED(hr)) goto out;
2201
2202         /* Check the number of created mipmaps */
2203         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2204         ddsd.dwSize = sizeof(ddsd);
2205         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2206         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2207         ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2208         if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2209
2210         for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2211         {
2212             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2213             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2214             if (FAILED(hr)) goto out;
2215         }
2216     }
2217
2218     for (i1 = 0; i1 < 8; i1++)
2219     {
2220         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2221         ddsd.dwSize = sizeof(ddsd);
2222         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2223         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2224         if (FAILED(hr)) goto out;
2225
2226         for (y = 0 ; y < ddsd.dwHeight; y++)
2227         {
2228             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2229
2230             for (x = 0; x < ddsd.dwWidth;  x++)
2231             {
2232                 /* x stored in green component, y in blue. */
2233                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2234                 *textureRow++ = color;
2235             }
2236         }
2237
2238         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2239         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2240     }
2241
2242     for (i1 = 0; i1 < 4; i1++)
2243     {
2244         memset(&ddbltfx, 0, sizeof(ddbltfx));
2245         ddbltfx.dwSize = sizeof(ddbltfx);
2246         U5(ddbltfx).dwFillColor = 0;
2247         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2248         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2249     }
2250
2251     loadpoint.x = loadpoint.y = 31;
2252     loadrect.left = 30;
2253     loadrect.top = 20;
2254     loadrect.right = 93;
2255     loadrect.bottom = 52;
2256
2257     /* Destination mip levels are a subset of source mip levels. */
2258     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2259     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2260
2261     for (i1 = 0; i1 < 4; i1++)
2262     {
2263         diff_count = 0;
2264         diff_count2 = 0;
2265
2266         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2267         ddsd.dwSize = sizeof(ddsd);
2268         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2269         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2270         if (FAILED(hr)) goto out;
2271
2272         for (y = 0 ; y < ddsd.dwHeight; y++)
2273         {
2274             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2275
2276             for (x = 0; x < ddsd.dwWidth;  x++)
2277             {
2278                 DWORD color = *textureRow++;
2279
2280                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2281                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2282                 {
2283                     if (color & 0xffffff) diff_count++;
2284                 }
2285                 else
2286                 {
2287                     DWORD r = (color & 0xff0000) >> 16;
2288                     DWORD g = (color & 0xff00) >> 8;
2289                     DWORD b = (color & 0xff);
2290
2291                     if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2292                         b != y + loadrect.top - loadpoint.y) diff_count++;
2293                 }
2294
2295                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2296                 technically be correct as it's not precisely defined by docs. */
2297                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2298                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2299                 {
2300                     if (color & 0xffffff) diff_count2++;
2301                 }
2302                 else
2303                 {
2304                     DWORD r = (color & 0xff0000) >> 16;
2305                     DWORD g = (color & 0xff00) >> 8;
2306                     DWORD b = (color & 0xff);
2307
2308                     if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2309                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2310                 }
2311             }
2312         }
2313
2314         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2315         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2316
2317         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2318              MIN(diff_count, diff_count2), i1);
2319
2320         loadpoint.x /= 2;
2321         loadpoint.y /= 2;
2322         loadrect.top /= 2;
2323         loadrect.left /= 2;
2324         loadrect.right = (loadrect.right + 1) / 2;
2325         loadrect.bottom = (loadrect.bottom + 1) / 2;
2326     }
2327
2328     /* Destination mip levels are a superset of source mip levels (should fail). */
2329     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2330     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2331
2332     for (i = 0; i < 2; i++)
2333     {
2334         for (i1 = 7; i1 >= 0; i1--)
2335         {
2336             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2337         }
2338     }
2339     memset(texture_levels, 0, sizeof(texture_levels));
2340
2341     /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2342     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2343     ddsd.dwSize = sizeof(ddsd);
2344     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2345     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2346     ddsd.dwWidth = 128;
2347     ddsd.dwHeight = 128;
2348     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2349     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2350     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2351     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2352     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2353     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2354     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2355     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2356     if (FAILED(hr)) goto out;
2357
2358     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2359     ddsd.dwSize = sizeof(ddsd);
2360     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2361     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2362     ddsd.dwWidth = 32;
2363     ddsd.dwHeight = 32;
2364     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2365     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2366     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2367     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2368     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2369     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2370     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2371     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2372     if (FAILED(hr)) goto out;
2373
2374     for (i1 = 1; i1 < 8; i1++)
2375     {
2376         hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2377         ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2378         if (FAILED(hr)) goto out;
2379     }
2380
2381     for (i1 = 0; i1 < 8; i1++)
2382     {
2383         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2384         ddsd.dwSize = sizeof(ddsd);
2385         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2386         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2387         if (FAILED(hr)) goto out;
2388
2389         for (y = 0 ; y < ddsd.dwHeight; y++)
2390         {
2391             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2392
2393             for (x = 0; x < ddsd.dwWidth;  x++)
2394             {
2395                 /* x stored in green component, y in blue. */
2396                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2397                 *textureRow++ = color;
2398             }
2399         }
2400
2401         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2402         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2403     }
2404
2405     memset(&ddbltfx, 0, sizeof(ddbltfx));
2406     ddbltfx.dwSize = sizeof(ddbltfx);
2407     U5(ddbltfx).dwFillColor = 0;
2408     hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2409     ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2410
2411     loadpoint.x = loadpoint.y = 32;
2412     loadrect.left = 32;
2413     loadrect.top = 32;
2414     loadrect.right = 96;
2415     loadrect.bottom = 96;
2416
2417     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2418     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2419
2420     loadpoint.x /= 4;
2421     loadpoint.y /= 4;
2422     loadrect.top /= 4;
2423     loadrect.left /= 4;
2424     loadrect.right = (loadrect.right + 3) / 4;
2425     loadrect.bottom = (loadrect.bottom + 3) / 4;
2426
2427     /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2428      * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2429      * copied subrectangles divided more than needed, without apparent logic. But it works
2430      * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2431      * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2432      * The following code attempts to detect broken results, actual tests will then be skipped
2433      */
2434     load_mip_subset_broken = TRUE;
2435     diff_count = 0;
2436
2437     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2438     ddsd.dwSize = sizeof(ddsd);
2439     hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2440     ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2441     if (FAILED(hr)) goto out;
2442
2443     for (y = 0 ; y < ddsd.dwHeight; y++)
2444     {
2445         DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2446
2447         for (x = 0; x < ddsd.dwWidth;  x++)
2448         {
2449             DWORD color = *textureRow++;
2450
2451             if (x < 2 || x >= 2 + 4 ||
2452                 y < 2 || y >= 2 + 4)
2453             {
2454                 if (color & 0xffffff) diff_count++;
2455             }
2456             else
2457             {
2458                 DWORD r = (color & 0xff0000) >> 16;
2459
2460                 if ((r & (0xf0)) != 0xf0) diff_count++;
2461             }
2462         }
2463     }
2464
2465     if (diff_count) load_mip_subset_broken = FALSE;
2466
2467     if (load_mip_subset_broken) {
2468         skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2469     } else {
2470         diff_count = 0;
2471
2472         for (y = 0 ; y < ddsd.dwHeight; y++)
2473         {
2474             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2475
2476             for (x = 0; x < ddsd.dwWidth;  x++)
2477             {
2478                 DWORD color = *textureRow++;
2479
2480                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2481                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2482                 {
2483                     if (color & 0xffffff) diff_count++;
2484                 }
2485                 else
2486                 {
2487                     DWORD r = (color & 0xff0000) >> 16;
2488                     DWORD g = (color & 0xff00) >> 8;
2489                     DWORD b = (color & 0xff);
2490
2491                     if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2492                         b != y + loadrect.top - loadpoint.y) diff_count++;
2493                 }
2494             }
2495         }
2496     }
2497
2498     hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2499     ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2500
2501     ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2502
2503     for (i = 0; i < 2; i++)
2504     {
2505         for (i1 = 7; i1 >= 0; i1--)
2506         {
2507             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2508         }
2509     }
2510     memset(texture_levels, 0, sizeof(texture_levels));
2511
2512     if (!load_mip_subset_broken)
2513     {
2514         /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2515         * surface (than first source mip level)
2516         */
2517         for (i = 0; i < 2; i++)
2518         {
2519             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2520             ddsd.dwSize = sizeof(ddsd);
2521             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2522             if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2523             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2524             ddsd.dwWidth = i ? 32 : 128;
2525             ddsd.dwHeight = i ? 32 : 128;
2526             if (i) U2(ddsd).dwMipMapCount = 4;
2527             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2528             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2529             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2530             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2531             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2532             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2533             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2534             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2535             if (FAILED(hr)) goto out;
2536
2537             /* Check the number of created mipmaps */
2538             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2539             ddsd.dwSize = sizeof(ddsd);
2540             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2541             ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2542             ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2543             if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2544
2545             for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2546             {
2547                 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2548                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2549                 if (FAILED(hr)) goto out;
2550             }
2551         }
2552
2553         for (i1 = 0; i1 < 8; i1++)
2554         {
2555             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2556             ddsd.dwSize = sizeof(ddsd);
2557             hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2558             ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2559             if (FAILED(hr)) goto out;
2560
2561             for (y = 0 ; y < ddsd.dwHeight; y++)
2562             {
2563                 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2564
2565                 for (x = 0; x < ddsd.dwWidth;  x++)
2566                 {
2567                     /* x stored in green component, y in blue. */
2568                     DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2569                     *textureRow++ = color;
2570                 }
2571             }
2572
2573             hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2574             ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2575         }
2576
2577         for (i1 = 0; i1 < 4; i1++)
2578         {
2579             memset(&ddbltfx, 0, sizeof(ddbltfx));
2580             ddbltfx.dwSize = sizeof(ddbltfx);
2581             U5(ddbltfx).dwFillColor = 0;
2582             hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2583             ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2584         }
2585
2586         loadpoint.x = loadpoint.y = 0;
2587         loadrect.left = 0;
2588         loadrect.top = 0;
2589         loadrect.right = 64;
2590         loadrect.bottom = 64;
2591
2592         hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2593         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2594
2595         i = 0;
2596         for (i1 = 0; i1 < 8 && i < 4; i1++)
2597         {
2598             DDSURFACEDESC2 ddsd2;
2599
2600             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2601             ddsd.dwSize = sizeof(ddsd);
2602             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2603             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2604
2605             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2606             ddsd2.dwSize = sizeof(ddsd2);
2607             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2608             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2609
2610             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2611             {
2612                 diff_count = 0;
2613
2614                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2615                 ddsd.dwSize = sizeof(ddsd);
2616                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2617                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2618                 if (FAILED(hr)) goto out;
2619
2620                 for (y = 0 ; y < ddsd.dwHeight; y++)
2621                 {
2622                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2623
2624                     for (x = 0; x < ddsd.dwWidth;  x++)
2625                     {
2626                         DWORD color = *textureRow++;
2627
2628                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2629                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2630                         {
2631                             if (color & 0xffffff) diff_count++;
2632                         }
2633                         else
2634                         {
2635                             DWORD r = (color & 0xff0000) >> 16;
2636                             DWORD g = (color & 0xff00) >> 8;
2637                             DWORD b = (color & 0xff);
2638
2639                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2640                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2641                         }
2642                     }
2643                 }
2644
2645                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2646                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2647
2648                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2649
2650                 i++;
2651             }
2652
2653             loadpoint.x /= 2;
2654             loadpoint.y /= 2;
2655             loadrect.top /= 2;
2656             loadrect.left /= 2;
2657             loadrect.right = (loadrect.right + 1) / 2;
2658             loadrect.bottom = (loadrect.bottom + 1) / 2;
2659         }
2660
2661         for (i = 0; i < 2; i++)
2662         {
2663             for (i1 = 7; i1 >= 0; i1--)
2664             {
2665                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2666             }
2667         }
2668         memset(texture_levels, 0, sizeof(texture_levels));
2669     }
2670
2671     /* Test palette copying. */
2672     for (i = 0; i < 2; i++)
2673     {
2674         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2675         ddsd.dwSize = sizeof(ddsd);
2676         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2677         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2678         ddsd.dwWidth = 128;
2679         ddsd.dwHeight = 128;
2680         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2681         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2682         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2683         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2684         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2685         if (FAILED(hr)) goto out;
2686
2687         /* Check the number of created mipmaps */
2688         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2689         ddsd.dwSize = sizeof(ddsd);
2690         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2691         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2692         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2693         if (U2(ddsd).dwMipMapCount != 8) goto out;
2694
2695         for (i1 = 1; i1 < 8; i1++)
2696         {
2697             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2698             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2699             if (FAILED(hr)) goto out;
2700         }
2701     }
2702
2703     memset(table1, 0, sizeof(table1));
2704     for (i = 0; i < 3; i++)
2705     {
2706         table1[0].peBlue = i + 1;
2707         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2708         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2709         if (FAILED(hr))
2710         {
2711             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2712             goto out;
2713         }
2714     }
2715
2716     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2717     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2718
2719     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2720     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2721
2722     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2723     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2724
2725     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2726     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2727     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2728     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2729
2730     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2731     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2732
2733     memset(table1, 0, sizeof(table1));
2734     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2735     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2736     if (SUCCEEDED(hr))
2737     {
2738         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2739         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2740         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2741     }
2742
2743     /* Test colorkey copying. */
2744     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2745     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2746     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2747     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2748     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2749
2750     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2751     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2752
2753     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2754     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2755
2756     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2757     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2758     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2759         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2760
2761     out:
2762
2763     for (i = 0; i < 5; i++)
2764     {
2765         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2766     }
2767
2768     for (i = 0; i < 2; i++)
2769     {
2770         for (i1 = 7; i1 >= 0; i1--)
2771         {
2772             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2773         }
2774     }
2775
2776     for (i = 0; i < 2; i++)
2777         for (i1 = 5; i1 >= 0; i1--)
2778             for (i2 = 7; i2 >= 0; i2--)
2779             {
2780                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2781             }
2782 }
2783
2784 static void SetMaterialTest(void)
2785 {
2786     HRESULT rc;
2787
2788     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2789     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2790 }
2791
2792 static void ComputeSphereVisibility(void)
2793 {
2794     D3DMATRIX proj, view, world;
2795     D3DVALUE radius[3];
2796     D3DVECTOR center[3];
2797     DWORD result[3];
2798     HRESULT rc;
2799
2800     world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2801     world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2802     world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2803     world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2804
2805     view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2806     view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2807     view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2808     view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2809
2810     proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2811     proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2812     proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2813     proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2814
2815     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2816     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2817     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2818
2819     U1(center[0]).x=11.461533;
2820     U2(center[0]).y=-4.761727;
2821     U3(center[0]).z=-1.171646;
2822
2823     radius[0]=38.252632;
2824
2825     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2826
2827     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2828     ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2829
2830     U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
2831     radius[0]=4.354097;
2832     U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
2833     radius[1]=12.500704;
2834     U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
2835     radius[2]=17.251318;
2836
2837     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2838
2839     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2840     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2841     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2842     ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2843     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2844     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2845
2846     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2847     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2848     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2849     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2850
2851     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2852     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2853     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2854     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2855
2856     U1(center[0]).x=0.0;
2857     U2(center[0]).y=0.0;
2858     U3(center[0]).z=0.05;
2859
2860     radius[0]=0.04;
2861
2862     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2863     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2864
2865     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2866
2867     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2868     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2869
2870     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2871     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2872     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2873     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2874
2875     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2876
2877     U1(center[0]).x=0.0;
2878     U2(center[0]).y=0.0;
2879     U3(center[0]).z=0.5;
2880
2881     radius[0]=0.5;
2882
2883     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2884
2885     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2886     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2887
2888     U1(center[0]).x=0.0;
2889     U2(center[0]).y=0.0;
2890     U3(center[0]).z=0.0;
2891
2892     radius[0]=0.0;
2893
2894     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2895
2896     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2897     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2898
2899     U1(center[0]).x=-1.0;
2900     U2(center[0]).y=-1.0;
2901     U3(center[0]).z=0.50;
2902
2903     radius[0]=0.25;
2904
2905     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2906
2907     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2908     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
2909
2910     U1(center[0]).x=-20.0;
2911     U2(center[0]).y=0.0;
2912     U3(center[0]).z=0.50;
2913
2914     radius[0]=3.0;
2915
2916     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2917
2918     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2919     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2920
2921     U1(center[0]).x=20.0;
2922     U2(center[0]).y=0.0;
2923     U3(center[0]).z=0.50;
2924
2925     radius[0]=3.0f;
2926
2927     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2928
2929     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2930     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
2931
2932     U1(center[0]).x=0.0;
2933     U2(center[0]).y=-20.0;
2934     U3(center[0]).z=0.50;
2935
2936     radius[0]=3.0;
2937
2938     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2939
2940     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2941     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
2942
2943     U1(center[0]).x=0.0;
2944     U2(center[0]).y=20.0;
2945     U3(center[0]).z=0.5;
2946
2947     radius[0]=3.0;
2948
2949     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2950
2951     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2952     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
2953
2954     U1(center[0]).x=0.0;
2955     U2(center[0]).y=0.0;
2956     U3(center[0]).z=-20;
2957
2958     radius[0]=3.0;
2959
2960     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2961
2962     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2963     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
2964
2965     U1(center[0]).x=0.0;
2966     U2(center[0]).y=0.0;
2967     U3(center[0]).z=20.0;
2968
2969     radius[0]=3.0;
2970
2971     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2972
2973     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2974     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
2975 }
2976
2977 static void SetRenderTargetTest(void)
2978 {
2979     HRESULT hr;
2980     IDirectDrawSurface7 *newrt, *oldrt;
2981     D3DVIEWPORT7 vp;
2982     DDSURFACEDESC2 ddsd;
2983     DWORD stateblock;
2984
2985     memset(&ddsd, 0, sizeof(ddsd));
2986     ddsd.dwSize = sizeof(ddsd);
2987     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2988     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
2989     ddsd.dwWidth = 64;
2990     ddsd.dwHeight = 64;
2991     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
2992     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
2993     if(FAILED(hr))
2994     {
2995         skip("Skipping SetRenderTarget test\n");
2996         return;
2997     }
2998
2999     memset(&vp, 0, sizeof(vp));
3000     vp.dwX = 10;
3001     vp.dwY = 10;
3002     vp.dwWidth = 246;
3003     vp.dwHeight = 246;
3004     vp.dvMinZ = 0.25;
3005     vp.dvMaxZ = 0.75;
3006     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3007     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3008
3009     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3010     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3011
3012     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3013     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3014     memset(&vp, 0xff, sizeof(vp));
3015     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3016     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3017     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3018     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3019     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3020     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3021     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.1\n", vp.dvMinZ);
3022     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.9\n", vp.dvMaxZ);
3023
3024     memset(&vp, 0, sizeof(vp));
3025     vp.dwX = 0;
3026     vp.dwY = 0;
3027     vp.dwWidth = 64;
3028     vp.dwHeight = 64;
3029     vp.dvMinZ = 0.0;
3030     vp.dvMaxZ = 1.0;
3031     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3032     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3033
3034     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3035     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3036     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3037     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3038
3039     /* Check this twice, before and after ending the stateblock */
3040     memset(&vp, 0xff, sizeof(vp));
3041     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3042     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3043     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3044     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3045     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3046     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3047     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3048     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3049
3050     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3051     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3052
3053     memset(&vp, 0xff, sizeof(vp));
3054     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3055     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3056     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3057     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3058     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3059     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3060     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3061     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3062
3063     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3064     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3065
3066     memset(&vp, 0, sizeof(vp));
3067     vp.dwX = 0;
3068     vp.dwY = 0;
3069     vp.dwWidth = 256;
3070     vp.dwHeight = 256;
3071     vp.dvMinZ = 0.0;
3072     vp.dvMaxZ = 0.0;
3073     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3074     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3075
3076     IDirectDrawSurface7_Release(oldrt);
3077     IDirectDrawSurface7_Release(newrt);
3078 }
3079
3080 static UINT expect_message;
3081
3082 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3083 {
3084     if (expect_message && message == expect_message) expect_message = 0;
3085
3086     return DefWindowProcA(hwnd, message, wparam, lparam);
3087 }
3088
3089 static void test_wndproc(void)
3090 {
3091     IDirectDraw7 *ddraw7;
3092     WNDCLASSA wc = {0};
3093     LONG_PTR proc;
3094     HWND window;
3095     HRESULT hr;
3096     ULONG ref;
3097
3098     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3099     if (FAILED(hr))
3100     {
3101         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3102         return;
3103     }
3104
3105     wc.lpfnWndProc = test_proc;
3106     wc.lpszClassName = "d3d7_test_wndproc_wc";
3107     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3108
3109     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test",
3110             WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3111
3112     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3113     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3114             (LONG_PTR)test_proc, proc);
3115
3116     expect_message = WM_SETFOCUS;
3117
3118     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3119     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3120     if (FAILED(hr))
3121     {
3122         IDirectDraw7_Release(ddraw7);
3123         goto done;
3124     }
3125
3126     todo_wine ok(!expect_message, "Expected message %#x, but didn't receive it.\n", expect_message);
3127
3128     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3129     todo_wine ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3130             (LONG_PTR)test_proc, proc);
3131
3132     ref = IDirectDraw7_Release(ddraw7);
3133     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3134
3135     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3136     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3137             (LONG_PTR)test_proc, proc);
3138
3139     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3140     if (FAILED(hr))
3141     {
3142         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3143         return;
3144     }
3145
3146     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3147     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3148             (LONG_PTR)test_proc, proc);
3149
3150     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3151     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3152     if (FAILED(hr))
3153     {
3154         IDirectDraw7_Release(ddraw7);
3155         goto done;
3156     }
3157
3158     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3159     todo_wine ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3160             (LONG_PTR)test_proc, proc);
3161
3162     ref = IDirectDraw7_Release(ddraw7);
3163     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3164
3165     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3166     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3167             (LONG_PTR)DefWindowProcA, proc);
3168
3169 done:
3170     expect_message = 0;
3171     DestroyWindow(window);
3172     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
3173 }
3174
3175 START_TEST(d3d)
3176 {
3177     init_function_pointers();
3178     if(!pDirectDrawCreateEx) {
3179         win_skip("function DirectDrawCreateEx not available\n");
3180         return;
3181     }
3182
3183     if(!CreateDirect3D()) {
3184         skip("Skipping d3d7 tests\n");
3185     } else {
3186         LightTest();
3187         ProcessVerticesTest();
3188         StateTest();
3189         SceneTest();
3190         LimitTest();
3191         D3D7EnumTest();
3192         SetMaterialTest();
3193         ComputeSphereVisibility();
3194         CapsTest();
3195         VertexBufferDescTest();
3196         D3D7_OldRenderStateTest();
3197         DeviceLoadTest();
3198         SetRenderTargetTest();
3199         ReleaseDirect3D();
3200     }
3201
3202     if (!D3D1_createObjects()) {
3203         skip("Skipping d3d1 tests\n");
3204     } else {
3205         Direct3D1Test();
3206         TextureLoadTest();
3207         D3D1_releaseObjects();
3208     }
3209
3210     test_wndproc();
3211 }