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