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