jscript: Added break statement implementation.
[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 (!SUCCEEDED(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 (!SUCCEEDED(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 (!SUCCEEDED(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 = (D3D7ETest*)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, (LPVOID) &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     unsigned int idx = 0;
1037     static struct v_in testverts[] = {
1038         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
1039         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1040     };
1041     static struct v_in cliptest[] = {
1042         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
1043         {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1044     };
1045     static struct v_in offscreentest[] = {
1046         {128.1, 0.0, 0.0},
1047     };
1048     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1049     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1050     D3DTRANSFORMDATA transformdata;
1051     DWORD i = FALSE;
1052
1053     memset(&desc, 0, sizeof(desc));
1054     desc.dwSize = sizeof(desc);
1055     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1056     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1057
1058     memset(desc.lpData, 0, 128);
1059     instr = desc.lpData;
1060     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1061     instr[idx].bSize = sizeof(*branch);
1062     instr[idx].wCount = 1;
1063     idx++;
1064     branch = (D3DBRANCH *) &instr[idx];
1065     branch->dwMask = 0x0;
1066     branch->dwValue = 1;
1067     branch->bNegate = TRUE;
1068     branch->dwOffset = 0;
1069     idx += (sizeof(*branch) / sizeof(*instr));
1070     instr[idx].bOpcode = D3DOP_EXIT;
1071     instr[idx].bSize = 0;
1072     instr[idx].wCount = 0;
1073     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1074     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1075
1076     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1077     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1078
1079     memset(&desc, 0, sizeof(desc));
1080     desc.dwSize = sizeof(desc);
1081
1082     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1083     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1084
1085     memset(desc.lpData, 0, 128);
1086     instr = desc.lpData;
1087     idx = 0;
1088     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1089     instr[idx].bSize = sizeof(*branch);
1090     instr[idx].wCount = 1;
1091     idx++;
1092     branch = (D3DBRANCH *) &instr[idx];
1093     branch->dwMask = 0x0;
1094     branch->dwValue = 1;
1095     branch->bNegate = TRUE;
1096     branch->dwOffset = 64;
1097     instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1098     instr[0].bOpcode = D3DOP_EXIT;
1099     instr[0].bSize = 0;
1100     instr[0].wCount = 0;
1101     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1102     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1103
1104     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1105     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1106
1107     /* Test rendering 0 triangles */
1108     memset(&desc, 0, sizeof(desc));
1109     desc.dwSize = sizeof(desc);
1110
1111     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1112     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1113
1114     memset(desc.lpData, 0, 128);
1115     instr = desc.lpData;
1116     idx = 0;
1117
1118     instr->bOpcode = D3DOP_TRIANGLE;
1119     instr->bSize = sizeof(D3DOP_TRIANGLE);
1120     instr->wCount = 0;
1121     instr = ((D3DINSTRUCTION*)(instr))+1;
1122     instr->bOpcode = D3DOP_EXIT;
1123     instr->bSize = 0;
1124     instr->wCount = 0;
1125     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1126     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1127
1128     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1129     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1130
1131     memset(&transformdata, 0, sizeof(transformdata));
1132     transformdata.dwSize = sizeof(transformdata);
1133     transformdata.lpIn = (void *) testverts;
1134     transformdata.dwInSize = sizeof(testverts[0]);
1135     transformdata.lpOut = out;
1136     transformdata.dwOutSize = sizeof(out[0]);
1137
1138     transformdata.lpHOut = NULL;
1139     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1140                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1141                                              &i);
1142     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1143
1144     transformdata.lpHOut = outH;
1145     memset(outH, 0xcc, sizeof(outH));
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     ok(i == 0, "Offscreen is %d\n", i);
1151
1152     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1153         static const struct v_out cmp[] = {
1154             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1155             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1156         };
1157
1158         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1159            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1160            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1161            out[i].x, out[i].y, out[i].z, out[i].rhw,
1162            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1163     }
1164     for(i = 0; i < sizeof(outH); i++) {
1165         if(((unsigned char *) outH)[i] != 0xcc) {
1166             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1167             break;
1168         }
1169     }
1170
1171     SET_VP_DATA(vp_data);
1172     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1173     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1174     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1175                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1176                                              &i);
1177     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1178     ok(i == 0, "Offscreen is %d\n", i);
1179
1180     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1181         static const struct v_out cmp[] = {
1182             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1183             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1184         };
1185         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1186            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1187            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1188            out[i].x, out[i].y, out[i].z, out[i].rhw,
1189            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1190     }
1191
1192     SET_VP_DATA(vp_data);
1193     vp_data.dwX = 10;
1194     vp_data.dwY = 20;
1195     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1196     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1197     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1198                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1199                                              &i);
1200     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1201     ok(i == 0, "Offscreen is %d\n", i);
1202     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1203         static const struct v_out cmp[] = {
1204             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1205             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1206         };
1207         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1208            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1209            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1210            out[i].x, out[i].y, out[i].z, out[i].rhw,
1211            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1212     }
1213
1214     memset(out, 0xcc, sizeof(out));
1215     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1216                                              &transformdata, D3DTRANSFORM_CLIPPED,
1217                                              &i);
1218     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1219     ok(i == 0, "Offscreen is %d\n", i);
1220     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1221         static const D3DHVERTEX cmpH[] = {
1222             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1223             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1224             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1225         };
1226         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1227            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1228            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1229            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1230            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1231
1232         /* No scheme has been found behind those return values. It seems to be
1233          * whatever data windows has when throwing the vertex away. Modify the
1234          * input test vertices to test this more. Depending on the input data
1235          * it can happen that the z coord gets written into y, or similar things
1236          */
1237         if(0)
1238         {
1239             static const struct v_out cmp[] = {
1240                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1241                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1242             };
1243             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1244                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1245                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1246                out[i].x, out[i].y, out[i].z, out[i].rhw,
1247                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1248         }
1249     }
1250     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1251         ok(((DWORD *) out)[i] != 0xcccccccc,
1252                 "Regular output DWORD %d remained untouched\n", i);
1253     }
1254
1255     transformdata.lpIn = (void *) cliptest;
1256     transformdata.dwInSize = sizeof(cliptest[0]);
1257     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1258                                              &transformdata, D3DTRANSFORM_CLIPPED,
1259                                              &i);
1260     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1261     ok(i == 0, "Offscreen is %d\n", i);
1262     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1263         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1264         {
1265             0,
1266             0,
1267             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1268             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1269         };
1270         ok(Flags[i] == outH[i].dwFlags,
1271            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1272            outH[i].dwFlags, Flags[i]);
1273     }
1274
1275     SET_VP_DATA(vp_data);
1276     vp_data.dwWidth = 10;
1277     vp_data.dwHeight = 1000;
1278     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1279     i = 10;
1280     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1281     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1282                                              &transformdata, D3DTRANSFORM_CLIPPED,
1283                                              &i);
1284     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1285     ok(i == 0, "Offscreen is %d\n", i);
1286     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1287         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1288         {
1289             D3DCLIP_RIGHT,
1290             D3DCLIP_LEFT,
1291             D3DCLIP_RIGHT | D3DCLIP_BACK,
1292             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1293         };
1294         ok(Flags[i] == outH[i].dwFlags,
1295            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1296            outH[i].dwFlags, Flags[i]);
1297     }
1298
1299     SET_VP_DATA(vp_data);
1300     vp_data.dwWidth = 256;
1301     vp_data.dwHeight = 256;
1302     vp_data.dvScaleX = 1;
1303     vp_data.dvScaleY = 1;
1304     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1305     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1306     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1307                                              &transformdata, D3DTRANSFORM_CLIPPED,
1308                                              &i);
1309     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1310     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1311     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1312         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1313         {
1314             0,
1315             0,
1316             D3DCLIP_BACK,
1317             D3DCLIP_FRONT,
1318         };
1319         ok(Flags[i] == outH[i].dwFlags,
1320            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1321            outH[i].dwFlags, Flags[i]);
1322     }
1323
1324     /* Finally try to figure out how the DWORD dwOffscreen works.
1325      * Apparently no vertex is offscreen with clipping off,
1326      * and with clipping on the offscreen flag is set if only one vertex
1327      * is transformed, and this vertex is offscreen.
1328      */
1329     SET_VP_DATA(vp_data);
1330     vp_data.dwWidth = 5;
1331     vp_data.dwHeight = 5;
1332     vp_data.dvScaleX = 10000;
1333     vp_data.dvScaleY = 10000;
1334     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1335     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1336     transformdata.lpIn = cliptest;
1337     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1338                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1339                                              &i);
1340     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1341     ok(i == 0, "Offscreen is %d\n", i);
1342     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1343                                              &transformdata, D3DTRANSFORM_CLIPPED,
1344                                              &i);
1345     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1346     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1347     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1348                                              &transformdata, D3DTRANSFORM_CLIPPED,
1349                                              &i);
1350     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1351     ok(i == 0, "Offscreen is %d\n", i);
1352     transformdata.lpIn = cliptest + 1;
1353     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1354                                              &transformdata, D3DTRANSFORM_CLIPPED,
1355                                              &i);
1356     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1357     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1358
1359     transformdata.lpIn = (void *) offscreentest;
1360     transformdata.dwInSize = sizeof(offscreentest[0]);
1361     SET_VP_DATA(vp_data);
1362     vp_data.dwWidth = 257;
1363     vp_data.dwHeight = 257;
1364     vp_data.dvScaleX = 1;
1365     vp_data.dvScaleY = 1;
1366     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1367     i = 12345;
1368     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1369                                              &transformdata, D3DTRANSFORM_CLIPPED,
1370                                              &i);
1371     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1372     ok(i == 0, "Offscreen is %d\n", i);
1373     vp_data.dwWidth = 256;
1374     vp_data.dwHeight = 256;
1375     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1376     i = 12345;
1377     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1378                                              &transformdata, D3DTRANSFORM_CLIPPED,
1379                                              &i);
1380     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1381     ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1382
1383     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1384                                              &transformdata, 0,
1385                                              &i);
1386     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1387
1388     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1389     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1390 }
1391
1392 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1393 {
1394     int i;
1395
1396     for (i = 0; i < 256; i++) {
1397        if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1398            table1[i].peBlue != table2[i].peBlue) return FALSE;
1399     }
1400
1401     return TRUE;
1402 }
1403
1404 /* test palette handling in IDirect3DTexture_Load */
1405 static void TextureLoadTest(void)
1406 {
1407     IDirectDrawSurface *TexSurface = NULL;
1408     IDirect3DTexture *Texture = NULL;
1409     IDirectDrawSurface *TexSurface2 = NULL;
1410     IDirect3DTexture *Texture2 = NULL;
1411     IDirectDrawPalette *palette = NULL;
1412     IDirectDrawPalette *palette2 = NULL;
1413     IDirectDrawPalette *palette_tmp = NULL;
1414     PALETTEENTRY table1[256], table2[256], table_tmp[256];
1415     HRESULT hr;
1416     DDSURFACEDESC ddsd;
1417     int i;
1418
1419     memset (&ddsd, 0, sizeof (ddsd));
1420     ddsd.dwSize = sizeof (ddsd);
1421     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1422     ddsd.dwHeight = 128;
1423     ddsd.dwWidth = 128;
1424     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1425     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1426     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1427     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1428
1429     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1430     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1431     if (FAILED(hr)) {
1432         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1433         goto cleanup;
1434     }
1435
1436     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1437                 (void *)&Texture);
1438     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1439     if (FAILED(hr)) {
1440         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1441         goto cleanup;
1442     }
1443
1444     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1445     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1446     if (FAILED(hr)) {
1447         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1448         goto cleanup;
1449     }
1450
1451     hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1452                 (void *)&Texture2);
1453     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1454     if (FAILED(hr)) {
1455         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1456         goto cleanup;
1457     }
1458
1459     /* test load of Texture to Texture */
1460     hr = IDirect3DTexture_Load(Texture, Texture);
1461     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1462
1463     /* test Load when both textures have no palette */
1464     hr = IDirect3DTexture_Load(Texture2, Texture);
1465     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1466
1467     for (i = 0; i < 256; i++) {
1468         table1[i].peRed = i;
1469         table1[i].peGreen = i;
1470         table1[i].peBlue = i;
1471         table1[i].peFlags = 0;
1472     }
1473
1474     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1475     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1476     if (FAILED(hr)) {
1477         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1478         goto cleanup;
1479     }
1480
1481     /* test Load when source texture has palette and destination has no palette */
1482     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1483     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1484     hr = IDirect3DTexture_Load(Texture2, Texture);
1485     ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1486
1487     for (i = 0; i < 256; i++) {
1488         table2[i].peRed = 255 - i;
1489         table2[i].peGreen = 255 - i;
1490         table2[i].peBlue = 255 - i;
1491         table2[i].peFlags = 0;
1492     }
1493
1494     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1495     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1496     if (FAILED(hr)) {
1497         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1498         goto cleanup;
1499     }
1500
1501     /* test Load when source has no palette and destination has a palette */
1502     hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1503     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1504     hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1505     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1506     hr = IDirect3DTexture_Load(Texture2, Texture);
1507     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1508     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1509     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1510     if (!palette_tmp) {
1511         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1512         goto cleanup;
1513     } else {
1514         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1515         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1516         ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1517         IDirectDrawPalette_Release(palette_tmp);
1518     }
1519
1520     /* test Load when both textures have palettes */
1521     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1522     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1523     hr = IDirect3DTexture_Load(Texture2, Texture);
1524     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1525     hr = IDirect3DTexture_Load(Texture2, Texture);
1526     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1527     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1528     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1529     if (!palette_tmp) {
1530         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1531         goto cleanup;
1532     } else {
1533         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1534         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1535         ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1536         IDirectDrawPalette_Release(palette_tmp);
1537     }
1538
1539     cleanup:
1540
1541     if (palette) IDirectDrawPalette_Release(palette);
1542     if (palette2) IDirectDrawPalette_Release(palette2);
1543     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1544     if (Texture) IDirect3DTexture_Release(Texture);
1545     if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1546     if (Texture2) IDirect3DTexture_Release(Texture2);
1547 }
1548
1549 static void VertexBufferDescTest(void)
1550 {
1551     HRESULT rc;
1552     D3DVERTEXBUFFERDESC desc;
1553     union mem_t
1554     {
1555         D3DVERTEXBUFFERDESC desc2;
1556         unsigned char buffer[512];
1557     } mem;
1558
1559     memset(&desc, 0, sizeof(desc));
1560     desc.dwSize = sizeof(desc);
1561     desc.dwCaps = 0;
1562     desc.dwFVF = D3DFVF_XYZ;
1563     desc.dwNumVertices = 1;
1564     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1565     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1566     if (!lpVBufSrc)
1567     {
1568         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1569         goto out;
1570     }
1571
1572     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1573     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1574     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1575     if(rc != D3D_OK)
1576         skip("GetVertexBuffer Failed!\n");
1577     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1578     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1579     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1580     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1581     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1582
1583     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1584     mem.desc2.dwSize = 0;
1585     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1586     if(rc != D3D_OK)
1587         skip("GetVertexBuffer Failed!\n");
1588     ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1589     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1590     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1591     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1592     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1593
1594     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1595     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1596     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1597     if(rc != D3D_OK)
1598         skip("GetVertexBuffer Failed!\n");
1599     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1600     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1601     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1602     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1603     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1604
1605 out:
1606     IDirect3DVertexBuffer7_Release(lpVBufSrc);
1607 }
1608
1609 static void D3D7_OldRenderStateTest(void)
1610 {
1611     HRESULT rc;
1612     DWORD val;
1613
1614     /* Test reaction to some deprecated states in D3D7.
1615
1616      * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1617      * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1618      * need not to be handled in D3D7.
1619      */
1620     todo_wine {
1621         rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1622         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1623
1624         rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1625         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1626
1627         rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1628         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1629
1630         rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1631         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1632     }
1633 }
1634
1635 #define IS_VALUE_NEAR(a, b)    ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1636 #define MIN(a, b)    ((a) < (b) ? (a) : (b))
1637
1638 static void DeviceLoadTest()
1639 {
1640     DDSURFACEDESC2 ddsd;
1641     IDirectDrawSurface7 *texture_levels[2][8];
1642     IDirectDrawSurface7 *cube_face_levels[2][6][8];
1643     DWORD flags;
1644     HRESULT hr;
1645     DDBLTFX ddbltfx;
1646     RECT loadrect;
1647     POINT loadpoint;
1648     int i, i1, i2;
1649     unsigned diff_count = 0, diff_count2 = 0;
1650     unsigned x, y;
1651     BOOL load_mip_subset_broken = FALSE;
1652     IDirectDrawPalette *palettes[5];
1653     PALETTEENTRY table1[256];
1654     DDCOLORKEY ddckey;
1655     D3DDEVICEDESC7 d3dcaps;
1656
1657     /* Test loading of texture subrectangle with a mipmap surface. */
1658     memset(texture_levels, 0, sizeof(texture_levels));
1659     memset(cube_face_levels, 0, sizeof(cube_face_levels));
1660     memset(palettes, 0, sizeof(palettes));
1661
1662     for (i = 0; i < 2; i++)
1663     {
1664         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1665         ddsd.dwSize = sizeof(ddsd);
1666         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1667         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1668         ddsd.dwWidth = 128;
1669         ddsd.dwHeight = 128;
1670         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1671         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1672         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1673         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1674         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1675         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1676         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1677         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1678         if (FAILED(hr)) goto out;
1679
1680         /* Check the number of created mipmaps */
1681         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1682         ddsd.dwSize = sizeof(ddsd);
1683         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1684         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1685         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1686         if (U2(ddsd).dwMipMapCount != 8) goto out;
1687
1688         for (i1 = 1; i1 < 8; i1++)
1689         {
1690             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1691             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1692             if (FAILED(hr)) goto out;
1693         }
1694     }
1695
1696     for (i1 = 0; i1 < 8; i1++)
1697     {
1698         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1699         ddsd.dwSize = sizeof(ddsd);
1700         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1701         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1702         if (FAILED(hr)) goto out;
1703
1704         for (y = 0 ; y < ddsd.dwHeight; y++)
1705         {
1706             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1707
1708             for (x = 0; x < ddsd.dwWidth;  x++)
1709             {
1710                 /* x stored in green component, y in blue. */
1711                 DWORD color = 0xff0000 | (x << 8)  | y;
1712                 *textureRow++ = color;
1713             }
1714         }
1715
1716         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1717         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1718     }
1719
1720     for (i1 = 0; i1 < 8; i1++)
1721     {
1722         memset(&ddbltfx, 0, sizeof(ddbltfx));
1723         ddbltfx.dwSize = sizeof(ddbltfx);
1724         U5(ddbltfx).dwFillColor = 0;
1725         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1726         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1727     }
1728
1729     /* First test some broken coordinates. */
1730     loadpoint.x = loadpoint.y = 0;
1731     loadrect.left = 0;
1732     loadrect.top = 0;
1733     loadrect.right = 0;
1734     loadrect.bottom = 0;
1735     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1736     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1737
1738     loadpoint.x = loadpoint.y = 50;
1739     loadrect.left = 0;
1740     loadrect.top = 0;
1741     loadrect.right = 100;
1742     loadrect.bottom = 100;
1743     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1744     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1745
1746     /* Test actual loading. */
1747     loadpoint.x = loadpoint.y = 31;
1748     loadrect.left = 30;
1749     loadrect.top = 20;
1750     loadrect.right = 93;
1751     loadrect.bottom = 52;
1752
1753     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1754     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1755
1756     for (i1 = 0; i1 < 8; i1++)
1757     {
1758         diff_count = 0;
1759         diff_count2 = 0;
1760
1761         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1762         ddsd.dwSize = sizeof(ddsd);
1763         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1764         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1765         if (FAILED(hr)) goto out;
1766
1767         for (y = 0 ; y < ddsd.dwHeight; y++)
1768         {
1769             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1770
1771             for (x = 0; x < ddsd.dwWidth;  x++)
1772             {
1773                 DWORD color = *textureRow++;
1774
1775                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1776                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1777                 {
1778                     if (color & 0xffffff) diff_count++;
1779                 }
1780                 else
1781                 {
1782                     DWORD r = (color & 0xff0000) >> 16;
1783                     DWORD g = (color & 0xff00) >> 8;
1784                     DWORD b = (color & 0xff);
1785
1786                     if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1787                 }
1788
1789                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1790                    technically be correct as it's not precisely defined by docs. */
1791                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1792                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1793                 {
1794                     if (color & 0xffffff) diff_count2++;
1795                 }
1796                 else
1797                 {
1798                     DWORD r = (color & 0xff0000) >> 16;
1799                     DWORD g = (color & 0xff00) >> 8;
1800                     DWORD b = (color & 0xff);
1801
1802                     if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1803                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1804                 }
1805             }
1806         }
1807
1808         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1809         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1810
1811         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1812                 MIN(diff_count, diff_count2), i1);
1813
1814         loadpoint.x /= 2;
1815         loadpoint.y /= 2;
1816         loadrect.top /= 2;
1817         loadrect.left /= 2;
1818         loadrect.right = (loadrect.right + 1) / 2;
1819         loadrect.bottom = (loadrect.bottom + 1) / 2;
1820     }
1821
1822     /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1823      * qemu Win98 / directx7 / RGB software rasterizer):
1824      * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1825     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1826     */
1827
1828     /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1829     for (i = 0; i < 2; i++)
1830     {
1831         for (i1 = 7; i1 >= 0; i1--)
1832         {
1833             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1834         }
1835     }
1836     memset(texture_levels, 0, sizeof(texture_levels));
1837
1838     /* Test texture size mismatch. */
1839     for (i = 0; i < 2; i++)
1840     {
1841         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1842         ddsd.dwSize = sizeof(ddsd);
1843         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1844         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1845         ddsd.dwWidth = i ? 256 : 128;
1846         ddsd.dwHeight = 128;
1847         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1848         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1849         if (FAILED(hr)) goto out;
1850     }
1851
1852     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1853     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1854
1855     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1856     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1857
1858     IDirectDrawSurface7_Release(texture_levels[0][0]);
1859     IDirectDrawSurface7_Release(texture_levels[1][0]);
1860     memset(texture_levels, 0, sizeof(texture_levels));
1861
1862     memset(&d3dcaps, 0, sizeof(d3dcaps));
1863     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1864     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1865
1866     if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1867     {
1868         skip("No cubemap support\n");
1869     }
1870     else
1871     {
1872         /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1873         for (i = 0; i < 2; i++)
1874         {
1875             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1876             ddsd.dwSize = sizeof(ddsd);
1877             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1878             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1879             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1880             ddsd.dwWidth = 128;
1881             ddsd.dwHeight = 128;
1882             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1883             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1884             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1885             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1886             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1887             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1888             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1889             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1890             if (FAILED(hr)) goto out;
1891
1892             flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1893             for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1894             {
1895                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1896                 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1897                 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1898                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1899                 if (FAILED(hr)) goto out;
1900             }
1901
1902             for (i1 = 0; i1 < 6; i1++)
1903             {
1904                 /* Check the number of created mipmaps */
1905                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1906                 ddsd.dwSize = sizeof(ddsd);
1907                 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1908                 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1909                 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1910                 if (U2(ddsd).dwMipMapCount != 8) goto out;
1911
1912                 for (i2 = 1; i2 < 8; i2++)
1913                 {
1914                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1915                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1916                     hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1917                     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1918                     if (FAILED(hr)) goto out;
1919                 }
1920             }
1921         }
1922
1923         for (i = 0; i < 6; i++)
1924             for (i1 = 0; i1 < 8; i1++)
1925             {
1926                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1927                 ddsd.dwSize = sizeof(ddsd);
1928                 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1929                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1930                 if (FAILED(hr)) goto out;
1931
1932                 for (y = 0 ; y < ddsd.dwHeight; y++)
1933                 {
1934                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1935
1936                     for (x = 0; x < ddsd.dwWidth;  x++)
1937                     {
1938                         /* face number in low 4 bits of red, x stored in green component, y in blue. */
1939                         DWORD color = 0xf00000 | (i << 16) | (x << 8)  | y;
1940                         *textureRow++ = color;
1941                     }
1942                 }
1943
1944                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1945                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1946             }
1947
1948         for (i = 0; i < 6; i++)
1949             for (i1 = 0; i1 < 8; i1++)
1950             {
1951                 memset(&ddbltfx, 0, sizeof(ddbltfx));
1952                 ddbltfx.dwSize = sizeof(ddbltfx);
1953                 U5(ddbltfx).dwFillColor = 0;
1954                 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1955                 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1956             }
1957
1958         loadpoint.x = loadpoint.y = 10;
1959         loadrect.left = 30;
1960         loadrect.top = 20;
1961         loadrect.right = 93;
1962         loadrect.bottom = 52;
1963
1964         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
1965                                         DDSCAPS2_CUBEMAP_ALLFACES);
1966         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1967
1968         for (i = 0; i < 6; i++)
1969         {
1970             loadpoint.x = loadpoint.y = 10;
1971             loadrect.left = 30;
1972             loadrect.top = 20;
1973             loadrect.right = 93;
1974             loadrect.bottom = 52;
1975
1976             for (i1 = 0; i1 < 8; i1++)
1977             {
1978                 diff_count = 0;
1979                 diff_count2 = 0;
1980
1981                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1982                 ddsd.dwSize = sizeof(ddsd);
1983                 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1984                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1985                 if (FAILED(hr)) goto out;
1986
1987                 for (y = 0 ; y < ddsd.dwHeight; y++)
1988                 {
1989                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1990
1991                     for (x = 0; x < ddsd.dwWidth;  x++)
1992                     {
1993                         DWORD color = *textureRow++;
1994
1995                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1996                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1997                         {
1998                             if (color & 0xffffff) diff_count++;
1999                         }
2000                         else
2001                         {
2002                             DWORD r = (color & 0xff0000) >> 16;
2003                             DWORD g = (color & 0xff00) >> 8;
2004                             DWORD b = (color & 0xff);
2005
2006                             if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2007                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2008                         }
2009
2010                         /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2011                         technically be correct as it's not precisely defined by docs. */
2012                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2013                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2014                         {
2015                             if (color & 0xffffff) diff_count2++;
2016                         }
2017                         else
2018                         {
2019                             DWORD r = (color & 0xff0000) >> 16;
2020                             DWORD g = (color & 0xff00) >> 8;
2021                             DWORD b = (color & 0xff);
2022
2023                             if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2024                                 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2025                         }
2026                     }
2027                 }
2028
2029                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2030                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2031
2032                 ok(diff_count == 0 || diff_count2 == 0,
2033                     "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2034                     MIN(diff_count, diff_count2), i, i1);
2035
2036                 loadpoint.x /= 2;
2037                 loadpoint.y /= 2;
2038                 loadrect.top /= 2;
2039                 loadrect.left /= 2;
2040                 loadrect.right = (loadrect.right + 1) / 2;
2041                 loadrect.bottom = (loadrect.bottom + 1) / 2;
2042             }
2043         }
2044
2045         for (i = 0; i < 2; i++)
2046             for (i1 = 5; i1 >= 0; i1--)
2047                 for (i2 = 7; i2 >= 0; i2--)
2048                 {
2049                     if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2050                 }
2051         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2052
2053         /* Test cubemap loading from regular texture. */
2054         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2055         ddsd.dwSize = sizeof(ddsd);
2056         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2057         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2058         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2059         ddsd.dwWidth = 128;
2060         ddsd.dwHeight = 128;
2061         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2062         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2063         if (FAILED(hr)) goto out;
2064
2065         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2066         ddsd.dwSize = sizeof(ddsd);
2067         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2068         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2069         ddsd.dwWidth = 128;
2070         ddsd.dwHeight = 128;
2071         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2072         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2073         if (FAILED(hr)) goto out;
2074
2075         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2076                                         DDSCAPS2_CUBEMAP_ALLFACES);
2077         ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2078
2079         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2080         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2081         IDirectDrawSurface7_Release(texture_levels[0][0]);
2082         memset(texture_levels, 0, sizeof(texture_levels));
2083
2084         /* Test cubemap loading from cubemap with different number of faces. */
2085         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2086         ddsd.dwSize = sizeof(ddsd);
2087         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2088         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2089         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2090         ddsd.dwWidth = 128;
2091         ddsd.dwHeight = 128;
2092         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2093         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2094         if (FAILED(hr)) goto out;
2095
2096         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2097         ddsd.dwSize = sizeof(ddsd);
2098         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2099         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2100         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2101         ddsd.dwWidth = 128;
2102         ddsd.dwHeight = 128;
2103         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2104         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2105         if (FAILED(hr)) goto out;
2106
2107         /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2108             (the above created cubemaps will have all faces. */
2109         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2110                                         DDSCAPS2_CUBEMAP_ALLFACES);
2111         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2112
2113         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2114                                         DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2115         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2116
2117         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2118                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2119         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2120
2121         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2122                                         DDSCAPS2_CUBEMAP_ALLFACES);
2123         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2124
2125         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2126                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2127         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2128
2129         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2130                                         DDSCAPS2_CUBEMAP_POSITIVEZ);
2131         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2132
2133         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2134         IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2135         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2136     }
2137
2138     /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2139     for (i = 0; i < 2; i++)
2140     {
2141         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2142         ddsd.dwSize = sizeof(ddsd);
2143         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2144         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2145         ddsd.dwWidth = 128;
2146         ddsd.dwHeight = 128;
2147         U2(ddsd).dwMipMapCount = i ? 4 : 8;
2148         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2149         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2150         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2151         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2152         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2153         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2154         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2155         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2156         if (FAILED(hr)) goto out;
2157
2158         /* Check the number of created mipmaps */
2159         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2160         ddsd.dwSize = sizeof(ddsd);
2161         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2162         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2163         ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2164         if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2165
2166         for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2167         {
2168             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2169             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2170             if (FAILED(hr)) goto out;
2171         }
2172     }
2173
2174     for (i1 = 0; i1 < 8; i1++)
2175     {
2176         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2177         ddsd.dwSize = sizeof(ddsd);
2178         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2179         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2180         if (FAILED(hr)) goto out;
2181
2182         for (y = 0 ; y < ddsd.dwHeight; y++)
2183         {
2184             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2185
2186             for (x = 0; x < ddsd.dwWidth;  x++)
2187             {
2188                 /* x stored in green component, y in blue. */
2189                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2190                 *textureRow++ = color;
2191             }
2192         }
2193
2194         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2195         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2196     }
2197
2198     for (i1 = 0; i1 < 4; i1++)
2199     {
2200         memset(&ddbltfx, 0, sizeof(ddbltfx));
2201         ddbltfx.dwSize = sizeof(ddbltfx);
2202         U5(ddbltfx).dwFillColor = 0;
2203         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2204         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2205     }
2206
2207     loadpoint.x = loadpoint.y = 31;
2208     loadrect.left = 30;
2209     loadrect.top = 20;
2210     loadrect.right = 93;
2211     loadrect.bottom = 52;
2212
2213     /* Destination mip levels are a subset of source mip levels. */
2214     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2215     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2216
2217     for (i1 = 0; i1 < 4; i1++)
2218     {
2219         diff_count = 0;
2220         diff_count2 = 0;
2221
2222         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2223         ddsd.dwSize = sizeof(ddsd);
2224         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2225         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2226         if (FAILED(hr)) goto out;
2227
2228         for (y = 0 ; y < ddsd.dwHeight; y++)
2229         {
2230             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2231
2232             for (x = 0; x < ddsd.dwWidth;  x++)
2233             {
2234                 DWORD color = *textureRow++;
2235
2236                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2237                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2238                 {
2239                     if (color & 0xffffff) diff_count++;
2240                 }
2241                 else
2242                 {
2243                     DWORD r = (color & 0xff0000) >> 16;
2244                     DWORD g = (color & 0xff00) >> 8;
2245                     DWORD b = (color & 0xff);
2246
2247                     if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2248                         b != y + loadrect.top - loadpoint.y) diff_count++;
2249                 }
2250
2251                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2252                 technically be correct as it's not precisely defined by docs. */
2253                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2254                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2255                 {
2256                     if (color & 0xffffff) diff_count2++;
2257                 }
2258                 else
2259                 {
2260                     DWORD r = (color & 0xff0000) >> 16;
2261                     DWORD g = (color & 0xff00) >> 8;
2262                     DWORD b = (color & 0xff);
2263
2264                     if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2265                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2266                 }
2267             }
2268         }
2269
2270         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2271         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2272
2273         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2274              MIN(diff_count, diff_count2), i1);
2275
2276         loadpoint.x /= 2;
2277         loadpoint.y /= 2;
2278         loadrect.top /= 2;
2279         loadrect.left /= 2;
2280         loadrect.right = (loadrect.right + 1) / 2;
2281         loadrect.bottom = (loadrect.bottom + 1) / 2;
2282     }
2283
2284     /* Destination mip levels are a superset of source mip levels (should fail). */
2285     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2286     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2287
2288     for (i = 0; i < 2; i++)
2289     {
2290         for (i1 = 7; i1 >= 0; i1--)
2291         {
2292             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2293         }
2294     }
2295     memset(texture_levels, 0, sizeof(texture_levels));
2296
2297     /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2298     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2299     ddsd.dwSize = sizeof(ddsd);
2300     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2301     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2302     ddsd.dwWidth = 128;
2303     ddsd.dwHeight = 128;
2304     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2305     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2306     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2307     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2308     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2309     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2310     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2311     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2312     if (FAILED(hr)) goto out;
2313
2314     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2315     ddsd.dwSize = sizeof(ddsd);
2316     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2317     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2318     ddsd.dwWidth = 32;
2319     ddsd.dwHeight = 32;
2320     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2321     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2322     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2323     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2324     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2325     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2326     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2327     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2328     if (FAILED(hr)) goto out;
2329
2330     for (i1 = 1; i1 < 8; i1++)
2331     {
2332         hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2333         ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2334         if (FAILED(hr)) goto out;
2335     }
2336
2337     for (i1 = 0; i1 < 8; i1++)
2338     {
2339         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2340         ddsd.dwSize = sizeof(ddsd);
2341         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2342         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2343         if (FAILED(hr)) goto out;
2344
2345         for (y = 0 ; y < ddsd.dwHeight; y++)
2346         {
2347             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2348
2349             for (x = 0; x < ddsd.dwWidth;  x++)
2350             {
2351                 /* x stored in green component, y in blue. */
2352                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2353                 *textureRow++ = color;
2354             }
2355         }
2356
2357         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2358         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2359     }
2360
2361     memset(&ddbltfx, 0, sizeof(ddbltfx));
2362     ddbltfx.dwSize = sizeof(ddbltfx);
2363     U5(ddbltfx).dwFillColor = 0;
2364     hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2365     ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2366
2367     loadpoint.x = loadpoint.y = 32;
2368     loadrect.left = 32;
2369     loadrect.top = 32;
2370     loadrect.right = 96;
2371     loadrect.bottom = 96;
2372
2373     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2374     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2375
2376     loadpoint.x /= 4;
2377     loadpoint.y /= 4;
2378     loadrect.top /= 4;
2379     loadrect.left /= 4;
2380     loadrect.right = (loadrect.right + 3) / 4;
2381     loadrect.bottom = (loadrect.bottom + 3) / 4;
2382
2383     /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2384      * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2385      * copied subrectangles divided more than needed, without apparent logic. But it works
2386      * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2387      * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2388      * The following code attempts to detect broken results, actual tests will then be skipped
2389      */
2390     load_mip_subset_broken = TRUE;
2391     diff_count = 0;
2392
2393     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2394     ddsd.dwSize = sizeof(ddsd);
2395     hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2396     ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2397     if (FAILED(hr)) goto out;
2398
2399     for (y = 0 ; y < ddsd.dwHeight; y++)
2400     {
2401         DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2402
2403         for (x = 0; x < ddsd.dwWidth;  x++)
2404         {
2405             DWORD color = *textureRow++;
2406
2407             if (x < 2 || x >= 2 + 4 ||
2408                 y < 2 || y >= 2 + 4)
2409             {
2410                 if (color & 0xffffff) diff_count++;
2411             }
2412             else
2413             {
2414                 DWORD r = (color & 0xff0000) >> 16;
2415
2416                 if ((r & (0xf0)) != 0xf0) diff_count++;
2417             }
2418         }
2419     }
2420
2421     if (diff_count) load_mip_subset_broken = FALSE;
2422
2423     if (load_mip_subset_broken) {
2424         skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2425     } else {
2426         diff_count = 0;
2427
2428         for (y = 0 ; y < ddsd.dwHeight; y++)
2429         {
2430             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2431
2432             for (x = 0; x < ddsd.dwWidth;  x++)
2433             {
2434                 DWORD color = *textureRow++;
2435
2436                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2437                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2438                 {
2439                     if (color & 0xffffff) diff_count++;
2440                 }
2441                 else
2442                 {
2443                     DWORD r = (color & 0xff0000) >> 16;
2444                     DWORD g = (color & 0xff00) >> 8;
2445                     DWORD b = (color & 0xff);
2446
2447                     if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2448                         b != y + loadrect.top - loadpoint.y) diff_count++;
2449                 }
2450             }
2451         }
2452     }
2453
2454     hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2455     ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2456
2457     ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2458
2459     for (i = 0; i < 2; i++)
2460     {
2461         for (i1 = 7; i1 >= 0; i1--)
2462         {
2463             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2464         }
2465     }
2466     memset(texture_levels, 0, sizeof(texture_levels));
2467
2468     if (!load_mip_subset_broken)
2469     {
2470         /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2471         * surface (than first source mip level)
2472         */
2473         for (i = 0; i < 2; i++)
2474         {
2475             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2476             ddsd.dwSize = sizeof(ddsd);
2477             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2478             if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2479             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2480             ddsd.dwWidth = i ? 32 : 128;
2481             ddsd.dwHeight = i ? 32 : 128;
2482             if (i) U2(ddsd).dwMipMapCount = 4;
2483             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2484             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2485             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2486             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2487             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2488             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2489             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2490             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2491             if (FAILED(hr)) goto out;
2492
2493             /* Check the number of created mipmaps */
2494             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2495             ddsd.dwSize = sizeof(ddsd);
2496             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2497             ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2498             ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2499             if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2500
2501             for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2502             {
2503                 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2504                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2505                 if (FAILED(hr)) goto out;
2506             }
2507         }
2508
2509         for (i1 = 0; i1 < 8; i1++)
2510         {
2511             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2512             ddsd.dwSize = sizeof(ddsd);
2513             hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2514             ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2515             if (FAILED(hr)) goto out;
2516
2517             for (y = 0 ; y < ddsd.dwHeight; y++)
2518             {
2519                 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2520
2521                 for (x = 0; x < ddsd.dwWidth;  x++)
2522                 {
2523                     /* x stored in green component, y in blue. */
2524                     DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2525                     *textureRow++ = color;
2526                 }
2527             }
2528
2529             hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2530             ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2531         }
2532
2533         for (i1 = 0; i1 < 4; i1++)
2534         {
2535             memset(&ddbltfx, 0, sizeof(ddbltfx));
2536             ddbltfx.dwSize = sizeof(ddbltfx);
2537             U5(ddbltfx).dwFillColor = 0;
2538             hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2539             ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2540         }
2541
2542         loadpoint.x = loadpoint.y = 0;
2543         loadrect.left = 0;
2544         loadrect.top = 0;
2545         loadrect.right = 64;
2546         loadrect.bottom = 64;
2547
2548         hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2549         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2550
2551         i = 0;
2552         for (i1 = 0; i1 < 8 && i < 4; i1++)
2553         {
2554             DDSURFACEDESC2 ddsd2;
2555
2556             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2557             ddsd.dwSize = sizeof(ddsd);
2558             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2559
2560             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2561             ddsd2.dwSize = sizeof(ddsd2);
2562             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2563
2564             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2565             {
2566                 diff_count = 0;
2567
2568                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2569                 ddsd.dwSize = sizeof(ddsd);
2570                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2571                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2572                 if (FAILED(hr)) goto out;
2573
2574                 for (y = 0 ; y < ddsd.dwHeight; y++)
2575                 {
2576                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2577
2578                     for (x = 0; x < ddsd.dwWidth;  x++)
2579                     {
2580                         DWORD color = *textureRow++;
2581
2582                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2583                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2584                         {
2585                             if (color & 0xffffff) diff_count++;
2586                         }
2587                         else
2588                         {
2589                             DWORD r = (color & 0xff0000) >> 16;
2590                             DWORD g = (color & 0xff00) >> 8;
2591                             DWORD b = (color & 0xff);
2592
2593                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2594                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2595                         }
2596                     }
2597                 }
2598
2599                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2600                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2601
2602                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2603
2604                 i++;
2605             }
2606
2607             loadpoint.x /= 2;
2608             loadpoint.y /= 2;
2609             loadrect.top /= 2;
2610             loadrect.left /= 2;
2611             loadrect.right = (loadrect.right + 1) / 2;
2612             loadrect.bottom = (loadrect.bottom + 1) / 2;
2613         }
2614
2615         for (i = 0; i < 2; i++)
2616         {
2617             for (i1 = 7; i1 >= 0; i1--)
2618             {
2619                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2620             }
2621         }
2622         memset(texture_levels, 0, sizeof(texture_levels));
2623     }
2624
2625     /* Test palette copying. */
2626     for (i = 0; i < 2; i++)
2627     {
2628         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2629         ddsd.dwSize = sizeof(ddsd);
2630         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2631         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2632         ddsd.dwWidth = 128;
2633         ddsd.dwHeight = 128;
2634         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2635         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2636         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2637         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2638         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2639         if (FAILED(hr)) goto out;
2640
2641         /* Check the number of created mipmaps */
2642         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2643         ddsd.dwSize = sizeof(ddsd);
2644         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2645         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2646         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2647         if (U2(ddsd).dwMipMapCount != 8) goto out;
2648
2649         for (i1 = 1; i1 < 8; i1++)
2650         {
2651             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2652             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2653             if (FAILED(hr)) goto out;
2654         }
2655     }
2656
2657     memset(table1, 0, sizeof(table1));
2658     for (i = 0; i < 3; i++)
2659     {
2660         table1[0].peBlue = i + 1;
2661         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2662         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2663         if (FAILED(hr))
2664         {
2665             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2666             goto out;
2667         }
2668     }
2669
2670     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2671     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2672
2673     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2674     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2675
2676     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2677     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2678
2679     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2680     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2681     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2682     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2683
2684     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2685     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2686
2687     memset(table1, 0, sizeof(table1));
2688     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2689     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2690     if (SUCCEEDED(hr))
2691     {
2692         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2693         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2694         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2695     }
2696
2697     /* Test colorkey copying. */
2698     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2699     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2700     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2701     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2702     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2703
2704     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2705     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2706
2707     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2708     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2709
2710     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2711     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2712     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2713         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2714
2715     out:
2716
2717     for (i = 0; i < 5; i++)
2718     {
2719         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2720     }
2721
2722     for (i = 0; i < 2; i++)
2723     {
2724         for (i1 = 7; i1 >= 0; i1--)
2725         {
2726             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2727         }
2728     }
2729
2730     for (i = 0; i < 2; i++)
2731         for (i1 = 5; i1 >= 0; i1--)
2732             for (i2 = 7; i2 >= 0; i2--)
2733             {
2734                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2735             }
2736 }
2737
2738 static void SetMaterialTest(void)
2739 {
2740     HRESULT rc;
2741
2742     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2743     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2744 }
2745
2746 START_TEST(d3d)
2747 {
2748     init_function_pointers();
2749     if(!pDirectDrawCreateEx) {
2750         skip("function DirectDrawCreateEx not available\n");
2751         return;
2752     }
2753
2754     if(!CreateDirect3D()) {
2755         skip("Skipping d3d7 tests\n");
2756     } else {
2757         LightTest();
2758         ProcessVerticesTest();
2759         StateTest();
2760         SceneTest();
2761         LimitTest();
2762         D3D7EnumTest();
2763         SetMaterialTest();
2764         CapsTest();
2765         VertexBufferDescTest();
2766         D3D7_OldRenderStateTest();
2767         DeviceLoadTest();
2768         ReleaseDirect3D();
2769     }
2770
2771     if (!D3D1_createObjects()) {
2772         skip("Skipping d3d1 tests\n");
2773     } else {
2774         Direct3D1Test();
2775         TextureLoadTest();
2776         D3D1_releaseObjects();
2777     }
2778 }