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