d3dcompiler: Add argument check in D3DReflect().
[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         trace("HAL Device %d\n", ver);
770     }
771     else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
772     {
773         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
774            "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
775         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
776            "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
777         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
778            "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
779         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
780            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
781
782         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
783            "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
784         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
785            "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
786         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
787            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
788         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
789            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
790     }
791     else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
792     {
793         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
794            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
795         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
796            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
797         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
798            "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
799         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
800            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
801
802         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
803            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
804         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
805            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
806         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
807            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
808         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
809            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
810     }
811     else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
812     {
813         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
814            "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
815         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
816            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
817         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
818            "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
819         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
820            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
821
822         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
823            "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
824         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
825            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
826         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
827            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
828         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
829            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
830     }
831     else
832     {
833         ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
834         if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
835         else trace("hal line does NOT have pow2 set\n");
836         if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
837         else trace("hal tri does NOT have pow2 set\n");
838         if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
839         else trace("hel line does NOT have pow2 set\n");
840         if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
841         else trace("hel tri does NOT have pow2 set\n");
842     }
843     return DDENUMRET_OK;
844 }
845
846 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
847 {
848     D3D7ETest *d3d7et = Context;
849     if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
850         d3d7et->rgb++;
851     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
852         d3d7et->hal++;
853     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
854         d3d7et->tnlhal++;
855     else
856         d3d7et->unk++;
857
858     d3d7et->total++;
859
860     return DDENUMRET_OK;
861 }
862
863
864 /*  Check the deviceGUID of devices enumerated by
865     IDirect3D7_EnumDevices. */
866 static void D3D7EnumTest(void)
867 {
868     D3D7ETest d3d7et;
869
870     if (!lpD3D) {
871         skip("No Direct3D7 interface.\n");
872         return;
873     }
874
875     memset(&d3d7et, 0, sizeof(d3d7et));
876     IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et);
877
878     /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
879     ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
880
881     /* We make two additional assumptions. */
882     ok(d3d7et.rgb, "No RGB Device enumerated.\n");
883
884     if(d3d7et.tnlhal)
885         ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
886 }
887
888 static void CapsTest(void)
889 {
890     IDirect3D3 *d3d3;
891     IDirect3D3 *d3d2;
892     IDirectDraw *dd1;
893     HRESULT hr;
894     UINT ver;
895
896     hr = DirectDrawCreate(NULL, &dd1, NULL);
897     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
898     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
899     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
900     ver = 3;
901     IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
902
903     IDirect3D3_Release(d3d3);
904     IDirectDraw_Release(dd1);
905
906     hr = DirectDrawCreate(NULL, &dd1, NULL);
907     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
908     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
909     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
910     ver = 2;
911     IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
912
913     IDirect3D2_Release(d3d2);
914     IDirectDraw_Release(dd1);
915 }
916
917 struct v_in {
918     float x, y, z;
919 };
920 struct v_out {
921     float x, y, z, rhw;
922 };
923
924 static BOOL D3D1_createObjects(void)
925 {
926     HRESULT hr;
927     DDSURFACEDESC ddsd;
928     D3DEXECUTEBUFFERDESC desc;
929     D3DVIEWPORT vp_data;
930
931     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
932     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
933     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
934     if (!DirectDraw1) {
935         return FALSE;
936     }
937
938     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
939     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
940
941     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
942     if (hr == E_NOINTERFACE) return FALSE;
943     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
944     if (!Direct3D1) {
945         return FALSE;
946     }
947
948     memset(&ddsd, 0, sizeof(ddsd));
949     ddsd.dwSize = sizeof(ddsd);
950     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
951     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
952     ddsd.dwWidth = 256;
953     ddsd.dwHeight = 256;
954     IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
955     if (!Surface1) {
956         skip("DDSCAPS_3DDEVICE surface not available\n");
957         return FALSE;
958     }
959
960     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
961     ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
962     if(!Direct3DDevice1) {
963         return FALSE;
964     }
965
966     memset(&desc, 0, sizeof(desc));
967     desc.dwSize = sizeof(desc);
968     desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
969     desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
970     desc.dwBufferSize = 128;
971     desc.lpData = NULL;
972     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
973     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
974     if(!ExecuteBuffer) {
975         return FALSE;
976     }
977
978     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
979     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
980     if(!Viewport) {
981         return FALSE;
982     }
983
984     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
985     ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
986
987     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
988     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
989     vp_data.dwSize = sizeof(vp_data);
990     vp_data.dwX = 0;
991     vp_data.dwY = 0;
992     vp_data.dwWidth = 256;
993     vp_data.dwHeight = 256;
994     vp_data.dvScaleX = 1;
995     vp_data.dvScaleY = 1;
996     vp_data.dvMaxX = 256;
997     vp_data.dvMaxY = 256;
998     vp_data.dvMinZ = 0;
999     vp_data.dvMaxZ = 1;
1000     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1001     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1002
1003     hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1004     ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1005     if (!Light)
1006         return FALSE;
1007
1008     return TRUE;
1009 }
1010
1011 static void D3D1_releaseObjects(void)
1012 {
1013     if (Light) IDirect3DLight_Release(Light);
1014     if (Viewport) IDirect3DViewport_Release(Viewport);
1015     if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1016     if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1017     if (Surface1) IDirectDrawSurface_Release(Surface1);
1018     if (Direct3D1) IDirect3D_Release(Direct3D1);
1019     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1020 }
1021
1022 static void ViewportTest(void)
1023 {
1024     HRESULT hr;
1025     LPDIRECT3DVIEWPORT2 Viewport2;
1026     D3DVIEWPORT vp1_data, ret_vp1_data;
1027     D3DVIEWPORT2 vp2_data, ret_vp2_data;
1028     float infinity;
1029
1030     *(DWORD*)&infinity = 0x7f800000;
1031
1032     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
1033     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1034
1035     hr = IDirect3DViewport_QueryInterface(Viewport, &IID_IDirect3DViewport2, (void**) &Viewport2);
1036     ok(hr==D3D_OK, "QueryInterface returned: %x\n", hr);
1037
1038     vp1_data.dwSize = sizeof(vp1_data);
1039     vp1_data.dwX = 0;
1040     vp1_data.dwY = 1;
1041     vp1_data.dwWidth = 256;
1042     vp1_data.dwHeight = 257;
1043     vp1_data.dvMaxX = 0;
1044     vp1_data.dvMaxY = 0;
1045     vp1_data.dvScaleX = 0;
1046     vp1_data.dvScaleY = 0;
1047     vp1_data.dvMinZ = 0.25;
1048     vp1_data.dvMaxZ = 0.75;
1049
1050     vp2_data.dwSize = sizeof(vp2_data);
1051     vp2_data.dwX = 2;
1052     vp2_data.dwY = 3;
1053     vp2_data.dwWidth = 258;
1054     vp2_data.dwHeight = 259;
1055     vp2_data.dvClipX = 0;
1056     vp2_data.dvClipY = 0;
1057     vp2_data.dvClipWidth = 0;
1058     vp2_data.dvClipHeight = 0;
1059     vp2_data.dvMinZ = 0.1;
1060     vp2_data.dvMaxZ = 0.9;
1061
1062     hr = IDirect3DViewport2_SetViewport(Viewport2, &vp1_data);
1063     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport returned %08x\n", hr);
1064
1065     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1066     ret_vp1_data.dwSize = sizeof(vp1_data);
1067
1068     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1069     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1070
1071     ok(ret_vp1_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp1_data.dwX);
1072     ok(ret_vp1_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp1_data.dwY);
1073     ok(ret_vp1_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp1_data.dwWidth);
1074     ok(ret_vp1_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp1_data.dwHeight);
1075     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1076     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1077     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1078     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1079     ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1080     ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1081
1082     hr = IDirect3DViewport2_SetViewport2(Viewport2, &vp2_data);
1083     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport2 returned %08x\n", hr);
1084
1085     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1086     ret_vp2_data.dwSize = sizeof(vp2_data);
1087
1088     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1089     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1090
1091     ok(ret_vp2_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp2_data.dwX);
1092     ok(ret_vp2_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp2_data.dwY);
1093     ok(ret_vp2_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp2_data.dwWidth);
1094     ok(ret_vp2_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp2_data.dwHeight);
1095     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1096     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1097     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1098         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1099     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1100         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1101     ok(ret_vp2_data.dvMinZ == vp2_data.dvMinZ, "dvMinZ is %f, expected %f\n", ret_vp2_data.dvMinZ, vp2_data.dvMinZ);
1102     ok(ret_vp2_data.dvMaxZ == vp2_data.dvMaxZ, "dvMaxZ is %f, expected %f\n", ret_vp2_data.dvMaxZ, vp2_data.dvMaxZ);
1103
1104     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1105     ret_vp1_data.dwSize = sizeof(vp1_data);
1106
1107     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1108     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1109
1110     ok(ret_vp1_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp2_data.dwX);
1111     ok(ret_vp1_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp2_data.dwY);
1112     ok(ret_vp1_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp2_data.dwWidth);
1113     ok(ret_vp1_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp2_data.dwHeight);
1114     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1115     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1116     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1117     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1118     todo_wine ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1119     todo_wine ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1120
1121     hr = IDirect3DViewport2_SetViewport2(Viewport2, &vp2_data);
1122     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport2 returned %08x\n", hr);
1123
1124     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1125     ret_vp2_data.dwSize = sizeof(vp2_data);
1126
1127     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1128     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1129
1130     ok(ret_vp2_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp2_data.dwX);
1131     ok(ret_vp2_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp2_data.dwY);
1132     ok(ret_vp2_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp2_data.dwWidth);
1133     ok(ret_vp2_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp2_data.dwHeight);
1134     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1135     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1136     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1137         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1138     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1139         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1140     ok(ret_vp2_data.dvMinZ == vp2_data.dvMinZ, "dvMinZ is %f, expected %f\n", ret_vp2_data.dvMinZ, vp2_data.dvMinZ);
1141     ok(ret_vp2_data.dvMaxZ == vp2_data.dvMaxZ, "dvMaxZ is %f, expected %f\n", ret_vp2_data.dvMaxZ, vp2_data.dvMaxZ);
1142
1143     hr = IDirect3DViewport2_SetViewport(Viewport2, &vp1_data);
1144     ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport returned %08x\n", hr);
1145
1146     memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1147     ret_vp1_data.dwSize = sizeof(vp1_data);
1148
1149     hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1150     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1151
1152     ok(ret_vp1_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp1_data.dwX);
1153     ok(ret_vp1_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp1_data.dwY);
1154     ok(ret_vp1_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp1_data.dwWidth);
1155     ok(ret_vp1_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp1_data.dwHeight);
1156     ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1157     ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1158     todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1159     todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1160     ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1161     ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1162
1163     memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1164     ret_vp2_data.dwSize = sizeof(vp2_data);
1165
1166     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1167     ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1168
1169     ok(ret_vp2_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp1_data.dwX);
1170     ok(ret_vp2_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp1_data.dwY);
1171     ok(ret_vp2_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp1_data.dwWidth);
1172     ok(ret_vp2_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp1_data.dwHeight);
1173     ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1174     ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1175     ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1176         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1177     ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1178         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1179     ok(ret_vp2_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp2_data.dvMinZ);
1180     ok(ret_vp2_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp2_data.dvMaxZ);
1181
1182     IDirect3DViewport2_Release(Viewport2);
1183
1184     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1185     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1186 }
1187
1188 #define SET_VP_DATA(vp_data) \
1189     vp_data.dwSize = sizeof(vp_data); \
1190     vp_data.dwX = 0; \
1191     vp_data.dwY = 0; \
1192     vp_data.dwWidth = 256; \
1193     vp_data.dwHeight = 256; \
1194     vp_data.dvMaxX = 256; \
1195     vp_data.dvMaxY = 256; \
1196     vp_data.dvScaleX = 5; \
1197     vp_data.dvScaleY = 5; \
1198     vp_data.dvMinZ = -25; \
1199     vp_data.dvMaxZ = 60;
1200
1201 static void Direct3D1Test(void)
1202 {
1203     HRESULT hr;
1204     D3DEXECUTEBUFFERDESC desc;
1205     D3DVIEWPORT vp_data;
1206     D3DINSTRUCTION *instr;
1207     D3DBRANCH *branch;
1208     IDirect3D *Direct3D_alt;
1209     IDirect3DLight *d3dlight;
1210     ULONG refcount;
1211     unsigned int idx = 0;
1212     static struct v_in testverts[] = {
1213         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
1214         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1215     };
1216     static struct v_in cliptest[] = {
1217         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
1218         {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1219     };
1220     static struct v_in offscreentest[] = {
1221         {128.1, 0.0, 0.0},
1222     };
1223     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1224     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1225     D3DTRANSFORMDATA transformdata;
1226     DWORD i = FALSE;
1227
1228     /* Interface consistency check. */
1229     hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1230     ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1231     if (hr == D3D_OK)
1232         ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1233
1234     memset(&desc, 0, sizeof(desc));
1235     desc.dwSize = sizeof(desc);
1236     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1237     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1238
1239     memset(desc.lpData, 0, 128);
1240     instr = desc.lpData;
1241     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1242     instr[idx].bSize = sizeof(*branch);
1243     instr[idx].wCount = 1;
1244     idx++;
1245     branch = (D3DBRANCH *) &instr[idx];
1246     branch->dwMask = 0x0;
1247     branch->dwValue = 1;
1248     branch->bNegate = TRUE;
1249     branch->dwOffset = 0;
1250     idx += (sizeof(*branch) / sizeof(*instr));
1251     instr[idx].bOpcode = D3DOP_EXIT;
1252     instr[idx].bSize = 0;
1253     instr[idx].wCount = 0;
1254     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1255     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1256
1257     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1258     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1259
1260     memset(&desc, 0, sizeof(desc));
1261     desc.dwSize = sizeof(desc);
1262
1263     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1264     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1265
1266     memset(desc.lpData, 0, 128);
1267     instr = desc.lpData;
1268     idx = 0;
1269     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1270     instr[idx].bSize = sizeof(*branch);
1271     instr[idx].wCount = 1;
1272     idx++;
1273     branch = (D3DBRANCH *) &instr[idx];
1274     branch->dwMask = 0x0;
1275     branch->dwValue = 1;
1276     branch->bNegate = TRUE;
1277     branch->dwOffset = 64;
1278     instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1279     instr[0].bOpcode = D3DOP_EXIT;
1280     instr[0].bSize = 0;
1281     instr[0].wCount = 0;
1282     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1283     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1284
1285     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1286     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1287
1288     /* Test rendering 0 triangles */
1289     memset(&desc, 0, sizeof(desc));
1290     desc.dwSize = sizeof(desc);
1291
1292     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1293     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1294
1295     memset(desc.lpData, 0, 128);
1296     instr = desc.lpData;
1297
1298     instr->bOpcode = D3DOP_TRIANGLE;
1299     instr->bSize = sizeof(D3DOP_TRIANGLE);
1300     instr->wCount = 0;
1301     instr++;
1302     instr->bOpcode = D3DOP_EXIT;
1303     instr->bSize = 0;
1304     instr->wCount = 0;
1305     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1306     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1307
1308     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1309     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1310
1311     memset(&transformdata, 0, sizeof(transformdata));
1312     transformdata.dwSize = sizeof(transformdata);
1313     transformdata.lpIn = testverts;
1314     transformdata.dwInSize = sizeof(testverts[0]);
1315     transformdata.lpOut = out;
1316     transformdata.dwOutSize = sizeof(out[0]);
1317
1318     transformdata.lpHOut = NULL;
1319     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1320                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1321                                              &i);
1322     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1323
1324     transformdata.lpHOut = outH;
1325     memset(outH, 0xcc, sizeof(outH));
1326     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1327                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1328                                              &i);
1329     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1330     ok(i == 0, "Offscreen is %d\n", i);
1331
1332     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1333         static const struct v_out cmp[] = {
1334             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1335             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1336         };
1337
1338         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1339            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1340            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1341            out[i].x, out[i].y, out[i].z, out[i].rhw,
1342            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1343     }
1344     for(i = 0; i < sizeof(outH); i++) {
1345         if(((unsigned char *) outH)[i] != 0xcc) {
1346             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1347             break;
1348         }
1349     }
1350
1351     SET_VP_DATA(vp_data);
1352     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1353     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1354     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1355                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1356                                              &i);
1357     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1358     ok(i == 0, "Offscreen is %d\n", i);
1359
1360     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1361         static const struct v_out cmp[] = {
1362             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1363             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1364         };
1365         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1366            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1367            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1368            out[i].x, out[i].y, out[i].z, out[i].rhw,
1369            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1370     }
1371
1372     SET_VP_DATA(vp_data);
1373     vp_data.dwX = 10;
1374     vp_data.dwY = 20;
1375     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1376     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1377     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1378                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1379                                              &i);
1380     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1381     ok(i == 0, "Offscreen is %d\n", i);
1382     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1383         static const struct v_out cmp[] = {
1384             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1385             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1386         };
1387         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1388            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1389            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1390            out[i].x, out[i].y, out[i].z, out[i].rhw,
1391            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1392     }
1393
1394     memset(out, 0xcc, sizeof(out));
1395     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1396                                              &transformdata, D3DTRANSFORM_CLIPPED,
1397                                              &i);
1398     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1399     ok(i == 0, "Offscreen is %d\n", i);
1400     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1401         static const D3DHVERTEX cmpH[] = {
1402             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1403             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1404             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1405         };
1406         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1407            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1408            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1409            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1410            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1411
1412         /* No scheme has been found behind those return values. It seems to be
1413          * whatever data windows has when throwing the vertex away. Modify the
1414          * input test vertices to test this more. Depending on the input data
1415          * it can happen that the z coord gets written into y, or similar things
1416          */
1417         if(0)
1418         {
1419             static const struct v_out cmp[] = {
1420                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1421                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1422             };
1423             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1424                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1425                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1426                out[i].x, out[i].y, out[i].z, out[i].rhw,
1427                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1428         }
1429     }
1430     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1431         ok(((DWORD *) out)[i] != 0xcccccccc,
1432                 "Regular output DWORD %d remained untouched\n", i);
1433     }
1434
1435     transformdata.lpIn = cliptest;
1436     transformdata.dwInSize = sizeof(cliptest[0]);
1437     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1438                                              &transformdata, D3DTRANSFORM_CLIPPED,
1439                                              &i);
1440     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1441     ok(i == 0, "Offscreen is %d\n", i);
1442     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1443         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1444         {
1445             0,
1446             0,
1447             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1448             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1449         };
1450         ok(Flags[i] == outH[i].dwFlags,
1451            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1452            outH[i].dwFlags, Flags[i]);
1453     }
1454
1455     SET_VP_DATA(vp_data);
1456     vp_data.dwWidth = 10;
1457     vp_data.dwHeight = 1000;
1458     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1459     i = 10;
1460     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1461     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1462                                              &transformdata, D3DTRANSFORM_CLIPPED,
1463                                              &i);
1464     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1465     ok(i == 0, "Offscreen is %d\n", i);
1466     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1467         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1468         {
1469             D3DCLIP_RIGHT,
1470             D3DCLIP_LEFT,
1471             D3DCLIP_RIGHT | D3DCLIP_BACK,
1472             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1473         };
1474         ok(Flags[i] == outH[i].dwFlags,
1475            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1476            outH[i].dwFlags, Flags[i]);
1477     }
1478
1479     SET_VP_DATA(vp_data);
1480     vp_data.dwWidth = 256;
1481     vp_data.dwHeight = 256;
1482     vp_data.dvScaleX = 1;
1483     vp_data.dvScaleY = 1;
1484     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1485     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1486     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1487                                              &transformdata, D3DTRANSFORM_CLIPPED,
1488                                              &i);
1489     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1490     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1491     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1492         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1493         {
1494             0,
1495             0,
1496             D3DCLIP_BACK,
1497             D3DCLIP_FRONT,
1498         };
1499         ok(Flags[i] == outH[i].dwFlags,
1500            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1501            outH[i].dwFlags, Flags[i]);
1502     }
1503
1504     /* Finally try to figure out how the DWORD dwOffscreen works.
1505      * Apparently no vertex is offscreen with clipping off,
1506      * and with clipping on the offscreen flag is set if only one vertex
1507      * is transformed, and this vertex is offscreen.
1508      */
1509     SET_VP_DATA(vp_data);
1510     vp_data.dwWidth = 5;
1511     vp_data.dwHeight = 5;
1512     vp_data.dvScaleX = 10000;
1513     vp_data.dvScaleY = 10000;
1514     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1515     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1516     transformdata.lpIn = cliptest;
1517     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1518                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1519                                              &i);
1520     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1521     ok(i == 0, "Offscreen is %d\n", i);
1522     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1523                                              &transformdata, D3DTRANSFORM_CLIPPED,
1524                                              &i);
1525     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1526     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1527     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1528                                              &transformdata, D3DTRANSFORM_CLIPPED,
1529                                              &i);
1530     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1531     ok(i == 0, "Offscreen is %d\n", i);
1532     transformdata.lpIn = cliptest + 1;
1533     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1534                                              &transformdata, D3DTRANSFORM_CLIPPED,
1535                                              &i);
1536     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1537     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1538
1539     transformdata.lpIn = offscreentest;
1540     transformdata.dwInSize = sizeof(offscreentest[0]);
1541     SET_VP_DATA(vp_data);
1542     vp_data.dwWidth = 257;
1543     vp_data.dwHeight = 257;
1544     vp_data.dvScaleX = 1;
1545     vp_data.dvScaleY = 1;
1546     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1547     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1548     i = 12345;
1549     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1550                                              &transformdata, D3DTRANSFORM_CLIPPED,
1551                                              &i);
1552     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1553     ok(i == 0, "Offscreen is %d\n", i);
1554     vp_data.dwWidth = 256;
1555     vp_data.dwHeight = 256;
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 == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1564
1565     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1566                                              &transformdata, 0,
1567                                              &i);
1568     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1569
1570     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1571     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1572
1573     hr = IDirect3DViewport_AddLight(Viewport, Light);
1574     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1575     refcount = getRefcount((IUnknown*) Light);
1576     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1577
1578     hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1579     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1580     ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1581     refcount = getRefcount((IUnknown*) Light);
1582     ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1583
1584     hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1585     ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1586     refcount = getRefcount((IUnknown*) Light);
1587     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1588
1589     IDirect3DLight_Release(Light);
1590 }
1591
1592 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1593 {
1594     int i;
1595
1596     for (i = 0; i < 256; i++) {
1597        if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1598            table1[i].peBlue != table2[i].peBlue) return FALSE;
1599     }
1600
1601     return TRUE;
1602 }
1603
1604 /* test palette handling in IDirect3DTexture_Load */
1605 static void TextureLoadTest(void)
1606 {
1607     IDirectDrawSurface *TexSurface = NULL;
1608     IDirect3DTexture *Texture = NULL;
1609     IDirectDrawSurface *TexSurface2 = NULL;
1610     IDirect3DTexture *Texture2 = NULL;
1611     IDirectDrawPalette *palette = NULL;
1612     IDirectDrawPalette *palette2 = NULL;
1613     IDirectDrawPalette *palette_tmp = NULL;
1614     PALETTEENTRY table1[256], table2[256], table_tmp[256];
1615     HRESULT hr;
1616     DDSURFACEDESC ddsd;
1617     int i;
1618
1619     memset (&ddsd, 0, sizeof (ddsd));
1620     ddsd.dwSize = sizeof (ddsd);
1621     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1622     ddsd.dwHeight = 128;
1623     ddsd.dwWidth = 128;
1624     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1625     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1626     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1627     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1628
1629     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1630     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1631     if (FAILED(hr)) {
1632         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1633         goto cleanup;
1634     }
1635
1636     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1637                 (void *)&Texture);
1638     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1639     if (FAILED(hr)) {
1640         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1641         goto cleanup;
1642     }
1643
1644     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1645     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1646     if (FAILED(hr)) {
1647         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1648         goto cleanup;
1649     }
1650
1651     hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1652                 (void *)&Texture2);
1653     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1654     if (FAILED(hr)) {
1655         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1656         goto cleanup;
1657     }
1658
1659     /* test load of Texture to Texture */
1660     hr = IDirect3DTexture_Load(Texture, Texture);
1661     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1662
1663     /* test Load when both textures have no palette */
1664     hr = IDirect3DTexture_Load(Texture2, Texture);
1665     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1666
1667     for (i = 0; i < 256; i++) {
1668         table1[i].peRed = i;
1669         table1[i].peGreen = i;
1670         table1[i].peBlue = i;
1671         table1[i].peFlags = 0;
1672     }
1673
1674     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1675     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1676     if (FAILED(hr)) {
1677         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1678         goto cleanup;
1679     }
1680
1681     /* test Load when source texture has palette and destination has no palette */
1682     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1683     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1684     hr = IDirect3DTexture_Load(Texture2, Texture);
1685     ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1686
1687     for (i = 0; i < 256; i++) {
1688         table2[i].peRed = 255 - i;
1689         table2[i].peGreen = 255 - i;
1690         table2[i].peBlue = 255 - i;
1691         table2[i].peFlags = 0;
1692     }
1693
1694     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1695     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1696     if (FAILED(hr)) {
1697         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1698         goto cleanup;
1699     }
1700
1701     /* test Load when source has no palette and destination has a palette */
1702     hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1703     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1704     hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1705     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1706     hr = IDirect3DTexture_Load(Texture2, Texture);
1707     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1708     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1709     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1710     if (!palette_tmp) {
1711         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1712         goto cleanup;
1713     } else {
1714         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1715         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1716         ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1717         IDirectDrawPalette_Release(palette_tmp);
1718     }
1719
1720     /* test Load when both textures have palettes */
1721     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1722     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1723     hr = IDirect3DTexture_Load(Texture2, Texture);
1724     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1725     hr = IDirect3DTexture_Load(Texture2, Texture);
1726     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1727     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1728     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1729     if (!palette_tmp) {
1730         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1731         goto cleanup;
1732     } else {
1733         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1734         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1735         ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1736         IDirectDrawPalette_Release(palette_tmp);
1737     }
1738
1739     cleanup:
1740
1741     if (palette) IDirectDrawPalette_Release(palette);
1742     if (palette2) IDirectDrawPalette_Release(palette2);
1743     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1744     if (Texture) IDirect3DTexture_Release(Texture);
1745     if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1746     if (Texture2) IDirect3DTexture_Release(Texture2);
1747 }
1748
1749 static void VertexBufferDescTest(void)
1750 {
1751     HRESULT rc;
1752     D3DVERTEXBUFFERDESC desc;
1753     union mem_t
1754     {
1755         D3DVERTEXBUFFERDESC desc2;
1756         unsigned char buffer[512];
1757     } mem;
1758
1759     memset(&desc, 0, sizeof(desc));
1760     desc.dwSize = sizeof(desc);
1761     desc.dwCaps = 0;
1762     desc.dwFVF = D3DFVF_XYZ;
1763     desc.dwNumVertices = 1;
1764     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1765     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1766     if (!lpVBufSrc)
1767     {
1768         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1769         goto out;
1770     }
1771
1772     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1773     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1774     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1775     if(rc != D3D_OK)
1776         skip("GetVertexBuffer Failed!\n");
1777     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1778     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1779     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1780     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1781     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1782
1783     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1784     mem.desc2.dwSize = 0;
1785     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1786     if(rc != D3D_OK)
1787         skip("GetVertexBuffer Failed!\n");
1788     ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1789     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1790     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1791     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1792     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1793
1794     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1795     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1796     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1797     if(rc != D3D_OK)
1798         skip("GetVertexBuffer Failed!\n");
1799     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1800     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1801     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1802     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1803     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1804
1805 out:
1806     IDirect3DVertexBuffer7_Release(lpVBufSrc);
1807 }
1808
1809 static void D3D7_OldRenderStateTest(void)
1810 {
1811     HRESULT hr;
1812     DWORD val;
1813
1814     /* Test reaction to some deprecated states in D3D7. */
1815     hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1816     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1817     hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1818     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1819     hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1820     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1821     hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1822     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1823 }
1824
1825 #define IS_VALUE_NEAR(a, b)    ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1826 #define MIN(a, b)    ((a) < (b) ? (a) : (b))
1827
1828 static void DeviceLoadTest(void)
1829 {
1830     DDSURFACEDESC2 ddsd;
1831     IDirectDrawSurface7 *texture_levels[2][8];
1832     IDirectDrawSurface7 *cube_face_levels[2][6][8];
1833     DWORD flags;
1834     HRESULT hr;
1835     DDBLTFX ddbltfx;
1836     RECT loadrect;
1837     POINT loadpoint;
1838     int i, i1, i2;
1839     unsigned diff_count = 0, diff_count2 = 0;
1840     unsigned x, y;
1841     BOOL load_mip_subset_broken = FALSE;
1842     IDirectDrawPalette *palettes[5];
1843     PALETTEENTRY table1[256];
1844     DDCOLORKEY ddckey;
1845     D3DDEVICEDESC7 d3dcaps;
1846
1847     /* Test loading of texture subrectangle with a mipmap surface. */
1848     memset(texture_levels, 0, sizeof(texture_levels));
1849     memset(cube_face_levels, 0, sizeof(cube_face_levels));
1850     memset(palettes, 0, sizeof(palettes));
1851
1852     for (i = 0; i < 2; i++)
1853     {
1854         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1855         ddsd.dwSize = sizeof(ddsd);
1856         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1857         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1858         ddsd.dwWidth = 128;
1859         ddsd.dwHeight = 128;
1860         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1861         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1862         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1863         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1864         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1865         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1866         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1867         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1868         if (FAILED(hr)) goto out;
1869
1870         /* Check the number of created mipmaps */
1871         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1872         ddsd.dwSize = sizeof(ddsd);
1873         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1874         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1875         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1876         if (U2(ddsd).dwMipMapCount != 8) goto out;
1877
1878         for (i1 = 1; i1 < 8; i1++)
1879         {
1880             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1881             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1882             if (FAILED(hr)) goto out;
1883         }
1884     }
1885
1886     for (i1 = 0; i1 < 8; i1++)
1887     {
1888         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1889         ddsd.dwSize = sizeof(ddsd);
1890         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1891         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1892         if (FAILED(hr)) goto out;
1893
1894         for (y = 0 ; y < ddsd.dwHeight; y++)
1895         {
1896             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1897
1898             for (x = 0; x < ddsd.dwWidth;  x++)
1899             {
1900                 /* x stored in green component, y in blue. */
1901                 DWORD color = 0xff0000 | (x << 8)  | y;
1902                 *textureRow++ = color;
1903             }
1904         }
1905
1906         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1907         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1908     }
1909
1910     for (i1 = 0; i1 < 8; i1++)
1911     {
1912         memset(&ddbltfx, 0, sizeof(ddbltfx));
1913         ddbltfx.dwSize = sizeof(ddbltfx);
1914         U5(ddbltfx).dwFillColor = 0;
1915         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1916         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1917     }
1918
1919     /* First test some broken coordinates. */
1920     loadpoint.x = loadpoint.y = 0;
1921     loadrect.left = 0;
1922     loadrect.top = 0;
1923     loadrect.right = 0;
1924     loadrect.bottom = 0;
1925     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1926     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1927
1928     loadpoint.x = loadpoint.y = 50;
1929     loadrect.left = 0;
1930     loadrect.top = 0;
1931     loadrect.right = 100;
1932     loadrect.bottom = 100;
1933     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1934     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1935
1936     /* Test actual loading. */
1937     loadpoint.x = loadpoint.y = 31;
1938     loadrect.left = 30;
1939     loadrect.top = 20;
1940     loadrect.right = 93;
1941     loadrect.bottom = 52;
1942
1943     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1944     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1945
1946     for (i1 = 0; i1 < 8; i1++)
1947     {
1948         diff_count = 0;
1949         diff_count2 = 0;
1950
1951         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1952         ddsd.dwSize = sizeof(ddsd);
1953         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1954         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1955         if (FAILED(hr)) goto out;
1956
1957         for (y = 0 ; y < ddsd.dwHeight; y++)
1958         {
1959             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1960
1961             for (x = 0; x < ddsd.dwWidth;  x++)
1962             {
1963                 DWORD color = *textureRow++;
1964
1965                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1966                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1967                 {
1968                     if (color & 0xffffff) diff_count++;
1969                 }
1970                 else
1971                 {
1972                     DWORD r = (color & 0xff0000) >> 16;
1973                     DWORD g = (color & 0xff00) >> 8;
1974                     DWORD b = (color & 0xff);
1975
1976                     if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1977                 }
1978
1979                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1980                    technically be correct as it's not precisely defined by docs. */
1981                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1982                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1983                 {
1984                     if (color & 0xffffff) diff_count2++;
1985                 }
1986                 else
1987                 {
1988                     DWORD r = (color & 0xff0000) >> 16;
1989                     DWORD g = (color & 0xff00) >> 8;
1990                     DWORD b = (color & 0xff);
1991
1992                     if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1993                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1994                 }
1995             }
1996         }
1997
1998         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1999         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2000
2001         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2002                 MIN(diff_count, diff_count2), i1);
2003
2004         loadpoint.x /= 2;
2005         loadpoint.y /= 2;
2006         loadrect.top /= 2;
2007         loadrect.left /= 2;
2008         loadrect.right = (loadrect.right + 1) / 2;
2009         loadrect.bottom = (loadrect.bottom + 1) / 2;
2010     }
2011
2012     /* This crashes on native (tested on real windows XP / directx9 / nvidia and
2013      * qemu Win98 / directx7 / RGB software rasterizer):
2014      * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
2015     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
2016     */
2017
2018     /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
2019     for (i = 0; i < 2; i++)
2020     {
2021         for (i1 = 7; i1 >= 0; i1--)
2022         {
2023             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2024         }
2025     }
2026     memset(texture_levels, 0, sizeof(texture_levels));
2027
2028     /* Test texture size mismatch. */
2029     for (i = 0; i < 2; i++)
2030     {
2031         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2032         ddsd.dwSize = sizeof(ddsd);
2033         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2034         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2035         ddsd.dwWidth = i ? 256 : 128;
2036         ddsd.dwHeight = 128;
2037         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2038         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2039         if (FAILED(hr)) goto out;
2040     }
2041
2042     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2043     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2044
2045     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
2046     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2047
2048     IDirectDrawSurface7_Release(texture_levels[0][0]);
2049     IDirectDrawSurface7_Release(texture_levels[1][0]);
2050     memset(texture_levels, 0, sizeof(texture_levels));
2051
2052     memset(&d3dcaps, 0, sizeof(d3dcaps));
2053     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
2054     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
2055
2056     if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
2057     {
2058         skip("No cubemap support\n");
2059     }
2060     else
2061     {
2062         /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
2063         for (i = 0; i < 2; i++)
2064         {
2065             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2066             ddsd.dwSize = sizeof(ddsd);
2067             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2068             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2069             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2070             ddsd.dwWidth = 128;
2071             ddsd.dwHeight = 128;
2072             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2073             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2074             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2075             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2076             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2077             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2078             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
2079             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2080             if (FAILED(hr)) goto out;
2081
2082             flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
2083             for (i1 = 1; i1 < 6; i1++, flags <<= 1)
2084             {
2085                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2086                 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
2087                 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
2088                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2089                 if (FAILED(hr)) goto out;
2090             }
2091
2092             for (i1 = 0; i1 < 6; i1++)
2093             {
2094                 /* Check the number of created mipmaps */
2095                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2096                 ddsd.dwSize = sizeof(ddsd);
2097                 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
2098                 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2099                 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2100                 if (U2(ddsd).dwMipMapCount != 8) goto out;
2101
2102                 for (i2 = 1; i2 < 8; i2++)
2103                 {
2104                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
2105                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
2106                     hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
2107                     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2108                     if (FAILED(hr)) goto out;
2109                 }
2110             }
2111         }
2112
2113         for (i = 0; i < 6; i++)
2114             for (i1 = 0; i1 < 8; i1++)
2115             {
2116                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2117                 ddsd.dwSize = sizeof(ddsd);
2118                 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2119                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2120                 if (FAILED(hr)) goto out;
2121
2122                 for (y = 0 ; y < ddsd.dwHeight; y++)
2123                 {
2124                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2125
2126                     for (x = 0; x < ddsd.dwWidth;  x++)
2127                     {
2128                         /* face number in low 4 bits of red, x stored in green component, y in blue. */
2129                         DWORD color = 0xf00000 | (i << 16) | (x << 8)  | y;
2130                         *textureRow++ = color;
2131                     }
2132                 }
2133
2134                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
2135                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2136             }
2137
2138         for (i = 0; i < 6; i++)
2139             for (i1 = 0; i1 < 8; i1++)
2140             {
2141                 memset(&ddbltfx, 0, sizeof(ddbltfx));
2142                 ddbltfx.dwSize = sizeof(ddbltfx);
2143                 U5(ddbltfx).dwFillColor = 0;
2144                 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2145                 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2146             }
2147
2148         loadpoint.x = loadpoint.y = 10;
2149         loadrect.left = 30;
2150         loadrect.top = 20;
2151         loadrect.right = 93;
2152         loadrect.bottom = 52;
2153
2154         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2155                                         DDSCAPS2_CUBEMAP_ALLFACES);
2156         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2157
2158         for (i = 0; i < 6; i++)
2159         {
2160             loadpoint.x = loadpoint.y = 10;
2161             loadrect.left = 30;
2162             loadrect.top = 20;
2163             loadrect.right = 93;
2164             loadrect.bottom = 52;
2165
2166             for (i1 = 0; i1 < 8; i1++)
2167             {
2168                 diff_count = 0;
2169                 diff_count2 = 0;
2170
2171                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2172                 ddsd.dwSize = sizeof(ddsd);
2173                 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2174                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2175                 if (FAILED(hr)) goto out;
2176
2177                 for (y = 0 ; y < ddsd.dwHeight; y++)
2178                 {
2179                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2180
2181                     for (x = 0; x < ddsd.dwWidth;  x++)
2182                     {
2183                         DWORD color = *textureRow++;
2184
2185                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2186                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2187                         {
2188                             if (color & 0xffffff) diff_count++;
2189                         }
2190                         else
2191                         {
2192                             DWORD r = (color & 0xff0000) >> 16;
2193                             DWORD g = (color & 0xff00) >> 8;
2194                             DWORD b = (color & 0xff);
2195
2196                             if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2197                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2198                         }
2199
2200                         /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2201                         technically be correct as it's not precisely defined by docs. */
2202                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2203                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2204                         {
2205                             if (color & 0xffffff) diff_count2++;
2206                         }
2207                         else
2208                         {
2209                             DWORD r = (color & 0xff0000) >> 16;
2210                             DWORD g = (color & 0xff00) >> 8;
2211                             DWORD b = (color & 0xff);
2212
2213                             if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2214                                 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2215                         }
2216                     }
2217                 }
2218
2219                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2220                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2221
2222                 ok(diff_count == 0 || diff_count2 == 0,
2223                     "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2224                     MIN(diff_count, diff_count2), i, i1);
2225
2226                 loadpoint.x /= 2;
2227                 loadpoint.y /= 2;
2228                 loadrect.top /= 2;
2229                 loadrect.left /= 2;
2230                 loadrect.right = (loadrect.right + 1) / 2;
2231                 loadrect.bottom = (loadrect.bottom + 1) / 2;
2232             }
2233         }
2234
2235         for (i = 0; i < 2; i++)
2236             for (i1 = 5; i1 >= 0; i1--)
2237                 for (i2 = 7; i2 >= 0; i2--)
2238                 {
2239                     if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2240                 }
2241         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2242
2243         /* Test cubemap loading from regular texture. */
2244         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2245         ddsd.dwSize = sizeof(ddsd);
2246         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2247         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2248         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2249         ddsd.dwWidth = 128;
2250         ddsd.dwHeight = 128;
2251         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2252         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2253         if (FAILED(hr)) goto out;
2254
2255         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2256         ddsd.dwSize = sizeof(ddsd);
2257         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2258         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2259         ddsd.dwWidth = 128;
2260         ddsd.dwHeight = 128;
2261         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2262         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2263         if (FAILED(hr)) goto out;
2264
2265         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2266                                         DDSCAPS2_CUBEMAP_ALLFACES);
2267         ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2268
2269         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2270         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2271         IDirectDrawSurface7_Release(texture_levels[0][0]);
2272         memset(texture_levels, 0, sizeof(texture_levels));
2273
2274         /* Test cubemap loading from cubemap with different number of faces. */
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 | DDSCAPS_COMPLEX;
2279         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2280         ddsd.dwWidth = 128;
2281         ddsd.dwHeight = 128;
2282         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2283         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2284         if (FAILED(hr)) goto out;
2285
2286         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2287         ddsd.dwSize = sizeof(ddsd);
2288         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2289         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2290         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2291         ddsd.dwWidth = 128;
2292         ddsd.dwHeight = 128;
2293         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2294         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2295         if (FAILED(hr)) goto out;
2296
2297         /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2298             (the above created cubemaps will have all faces. */
2299         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2300                                         DDSCAPS2_CUBEMAP_ALLFACES);
2301         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2302
2303         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2304                                         DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2305         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2306
2307         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2308                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2309         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2310
2311         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2312                                         DDSCAPS2_CUBEMAP_ALLFACES);
2313         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2314
2315         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2316                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2317         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2318
2319         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2320                                         DDSCAPS2_CUBEMAP_POSITIVEZ);
2321         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2322
2323         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2324         IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2325         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2326     }
2327
2328     /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2329     for (i = 0; i < 2; i++)
2330     {
2331         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2332         ddsd.dwSize = sizeof(ddsd);
2333         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2334         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2335         ddsd.dwWidth = 128;
2336         ddsd.dwHeight = 128;
2337         U2(ddsd).dwMipMapCount = i ? 4 : 8;
2338         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2339         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2340         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2341         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2342         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2343         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2344         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2345         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2346         if (FAILED(hr)) goto out;
2347
2348         /* Check the number of created mipmaps */
2349         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2350         ddsd.dwSize = sizeof(ddsd);
2351         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2352         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2353         ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2354         if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2355
2356         for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2357         {
2358             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2359             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2360             if (FAILED(hr)) goto out;
2361         }
2362     }
2363
2364     for (i1 = 0; i1 < 8; i1++)
2365     {
2366         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2367         ddsd.dwSize = sizeof(ddsd);
2368         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2369         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2370         if (FAILED(hr)) goto out;
2371
2372         for (y = 0 ; y < ddsd.dwHeight; y++)
2373         {
2374             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2375
2376             for (x = 0; x < ddsd.dwWidth;  x++)
2377             {
2378                 /* x stored in green component, y in blue. */
2379                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2380                 *textureRow++ = color;
2381             }
2382         }
2383
2384         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2385         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2386     }
2387
2388     for (i1 = 0; i1 < 4; i1++)
2389     {
2390         memset(&ddbltfx, 0, sizeof(ddbltfx));
2391         ddbltfx.dwSize = sizeof(ddbltfx);
2392         U5(ddbltfx).dwFillColor = 0;
2393         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2394         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2395     }
2396
2397     loadpoint.x = loadpoint.y = 31;
2398     loadrect.left = 30;
2399     loadrect.top = 20;
2400     loadrect.right = 93;
2401     loadrect.bottom = 52;
2402
2403     /* Destination mip levels are a subset of source mip levels. */
2404     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2405     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2406
2407     for (i1 = 0; i1 < 4; i1++)
2408     {
2409         diff_count = 0;
2410         diff_count2 = 0;
2411
2412         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2413         ddsd.dwSize = sizeof(ddsd);
2414         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2415         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2416         if (FAILED(hr)) goto out;
2417
2418         for (y = 0 ; y < ddsd.dwHeight; y++)
2419         {
2420             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2421
2422             for (x = 0; x < ddsd.dwWidth;  x++)
2423             {
2424                 DWORD color = *textureRow++;
2425
2426                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2427                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2428                 {
2429                     if (color & 0xffffff) diff_count++;
2430                 }
2431                 else
2432                 {
2433                     DWORD r = (color & 0xff0000) >> 16;
2434                     DWORD g = (color & 0xff00) >> 8;
2435                     DWORD b = (color & 0xff);
2436
2437                     if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2438                         b != y + loadrect.top - loadpoint.y) diff_count++;
2439                 }
2440
2441                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2442                 technically be correct as it's not precisely defined by docs. */
2443                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2444                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2445                 {
2446                     if (color & 0xffffff) diff_count2++;
2447                 }
2448                 else
2449                 {
2450                     DWORD r = (color & 0xff0000) >> 16;
2451                     DWORD g = (color & 0xff00) >> 8;
2452                     DWORD b = (color & 0xff);
2453
2454                     if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2455                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2456                 }
2457             }
2458         }
2459
2460         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2461         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2462
2463         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2464              MIN(diff_count, diff_count2), i1);
2465
2466         loadpoint.x /= 2;
2467         loadpoint.y /= 2;
2468         loadrect.top /= 2;
2469         loadrect.left /= 2;
2470         loadrect.right = (loadrect.right + 1) / 2;
2471         loadrect.bottom = (loadrect.bottom + 1) / 2;
2472     }
2473
2474     /* Destination mip levels are a superset of source mip levels (should fail). */
2475     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2476     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2477
2478     for (i = 0; i < 2; i++)
2479     {
2480         for (i1 = 7; i1 >= 0; i1--)
2481         {
2482             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2483         }
2484     }
2485     memset(texture_levels, 0, sizeof(texture_levels));
2486
2487     /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2488     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2489     ddsd.dwSize = sizeof(ddsd);
2490     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2491     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2492     ddsd.dwWidth = 128;
2493     ddsd.dwHeight = 128;
2494     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2495     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2496     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2497     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2498     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2499     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2500     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2501     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2502     if (FAILED(hr)) goto out;
2503
2504     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2505     ddsd.dwSize = sizeof(ddsd);
2506     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2507     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2508     ddsd.dwWidth = 32;
2509     ddsd.dwHeight = 32;
2510     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2511     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2512     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2513     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2514     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2515     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2516     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2517     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2518     if (FAILED(hr)) goto out;
2519
2520     for (i1 = 1; i1 < 8; i1++)
2521     {
2522         hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2523         ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2524         if (FAILED(hr)) goto out;
2525     }
2526
2527     for (i1 = 0; i1 < 8; i1++)
2528     {
2529         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2530         ddsd.dwSize = sizeof(ddsd);
2531         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2532         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2533         if (FAILED(hr)) goto out;
2534
2535         for (y = 0 ; y < ddsd.dwHeight; y++)
2536         {
2537             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2538
2539             for (x = 0; x < ddsd.dwWidth;  x++)
2540             {
2541                 /* x stored in green component, y in blue. */
2542                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2543                 *textureRow++ = color;
2544             }
2545         }
2546
2547         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2548         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2549     }
2550
2551     memset(&ddbltfx, 0, sizeof(ddbltfx));
2552     ddbltfx.dwSize = sizeof(ddbltfx);
2553     U5(ddbltfx).dwFillColor = 0;
2554     hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2555     ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2556
2557     loadpoint.x = loadpoint.y = 32;
2558     loadrect.left = 32;
2559     loadrect.top = 32;
2560     loadrect.right = 96;
2561     loadrect.bottom = 96;
2562
2563     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2564     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2565
2566     loadpoint.x /= 4;
2567     loadpoint.y /= 4;
2568     loadrect.top /= 4;
2569     loadrect.left /= 4;
2570     loadrect.right = (loadrect.right + 3) / 4;
2571     loadrect.bottom = (loadrect.bottom + 3) / 4;
2572
2573     /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2574      * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2575      * copied subrectangles divided more than needed, without apparent logic. But it works
2576      * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2577      * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2578      * The following code attempts to detect broken results, actual tests will then be skipped
2579      */
2580     load_mip_subset_broken = TRUE;
2581     diff_count = 0;
2582
2583     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2584     ddsd.dwSize = sizeof(ddsd);
2585     hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2586     ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2587     if (FAILED(hr)) goto out;
2588
2589     for (y = 0 ; y < ddsd.dwHeight; y++)
2590     {
2591         DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2592
2593         for (x = 0; x < ddsd.dwWidth;  x++)
2594         {
2595             DWORD color = *textureRow++;
2596
2597             if (x < 2 || x >= 2 + 4 ||
2598                 y < 2 || y >= 2 + 4)
2599             {
2600                 if (color & 0xffffff) diff_count++;
2601             }
2602             else
2603             {
2604                 DWORD r = (color & 0xff0000) >> 16;
2605
2606                 if ((r & (0xf0)) != 0xf0) diff_count++;
2607             }
2608         }
2609     }
2610
2611     if (diff_count) load_mip_subset_broken = FALSE;
2612
2613     if (load_mip_subset_broken) {
2614         skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2615     } else {
2616         diff_count = 0;
2617
2618         for (y = 0 ; y < ddsd.dwHeight; y++)
2619         {
2620             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2621
2622             for (x = 0; x < ddsd.dwWidth;  x++)
2623             {
2624                 DWORD color = *textureRow++;
2625
2626                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2627                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2628                 {
2629                     if (color & 0xffffff) diff_count++;
2630                 }
2631                 else
2632                 {
2633                     DWORD r = (color & 0xff0000) >> 16;
2634                     DWORD g = (color & 0xff00) >> 8;
2635                     DWORD b = (color & 0xff);
2636
2637                     if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2638                         b != y + loadrect.top - loadpoint.y) diff_count++;
2639                 }
2640             }
2641         }
2642     }
2643
2644     hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2645     ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2646
2647     ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2648
2649     for (i = 0; i < 2; i++)
2650     {
2651         for (i1 = 7; i1 >= 0; i1--)
2652         {
2653             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2654         }
2655     }
2656     memset(texture_levels, 0, sizeof(texture_levels));
2657
2658     if (!load_mip_subset_broken)
2659     {
2660         /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2661         * surface (than first source mip level)
2662         */
2663         for (i = 0; i < 2; i++)
2664         {
2665             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2666             ddsd.dwSize = sizeof(ddsd);
2667             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2668             if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2669             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2670             ddsd.dwWidth = i ? 32 : 128;
2671             ddsd.dwHeight = i ? 32 : 128;
2672             if (i) U2(ddsd).dwMipMapCount = 4;
2673             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2674             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2675             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2676             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2677             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2678             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2679             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2680             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2681             if (FAILED(hr)) goto out;
2682
2683             /* Check the number of created mipmaps */
2684             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2685             ddsd.dwSize = sizeof(ddsd);
2686             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2687             ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2688             ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2689             if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2690
2691             for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2692             {
2693                 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2694                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2695                 if (FAILED(hr)) goto out;
2696             }
2697         }
2698
2699         for (i1 = 0; i1 < 8; i1++)
2700         {
2701             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2702             ddsd.dwSize = sizeof(ddsd);
2703             hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2704             ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2705             if (FAILED(hr)) goto out;
2706
2707             for (y = 0 ; y < ddsd.dwHeight; y++)
2708             {
2709                 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2710
2711                 for (x = 0; x < ddsd.dwWidth;  x++)
2712                 {
2713                     /* x stored in green component, y in blue. */
2714                     DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2715                     *textureRow++ = color;
2716                 }
2717             }
2718
2719             hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2720             ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2721         }
2722
2723         for (i1 = 0; i1 < 4; i1++)
2724         {
2725             memset(&ddbltfx, 0, sizeof(ddbltfx));
2726             ddbltfx.dwSize = sizeof(ddbltfx);
2727             U5(ddbltfx).dwFillColor = 0;
2728             hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2729             ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2730         }
2731
2732         loadpoint.x = loadpoint.y = 0;
2733         loadrect.left = 0;
2734         loadrect.top = 0;
2735         loadrect.right = 64;
2736         loadrect.bottom = 64;
2737
2738         hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2739         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2740
2741         i = 0;
2742         for (i1 = 0; i1 < 8 && i < 4; i1++)
2743         {
2744             DDSURFACEDESC2 ddsd2;
2745
2746             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2747             ddsd.dwSize = sizeof(ddsd);
2748             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2749             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2750
2751             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2752             ddsd2.dwSize = sizeof(ddsd2);
2753             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2754             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2755
2756             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2757             {
2758                 diff_count = 0;
2759
2760                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2761                 ddsd.dwSize = sizeof(ddsd);
2762                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2763                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2764                 if (FAILED(hr)) goto out;
2765
2766                 for (y = 0 ; y < ddsd.dwHeight; y++)
2767                 {
2768                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2769
2770                     for (x = 0; x < ddsd.dwWidth;  x++)
2771                     {
2772                         DWORD color = *textureRow++;
2773
2774                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2775                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2776                         {
2777                             if (color & 0xffffff) diff_count++;
2778                         }
2779                         else
2780                         {
2781                             DWORD r = (color & 0xff0000) >> 16;
2782                             DWORD g = (color & 0xff00) >> 8;
2783                             DWORD b = (color & 0xff);
2784
2785                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2786                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2787                         }
2788                     }
2789                 }
2790
2791                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2792                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2793
2794                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2795
2796                 i++;
2797             }
2798
2799             loadpoint.x /= 2;
2800             loadpoint.y /= 2;
2801             loadrect.top /= 2;
2802             loadrect.left /= 2;
2803             loadrect.right = (loadrect.right + 1) / 2;
2804             loadrect.bottom = (loadrect.bottom + 1) / 2;
2805         }
2806
2807         for (i = 0; i < 2; i++)
2808         {
2809             for (i1 = 7; i1 >= 0; i1--)
2810             {
2811                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2812             }
2813         }
2814         memset(texture_levels, 0, sizeof(texture_levels));
2815     }
2816
2817     /* Test palette copying. */
2818     for (i = 0; i < 2; i++)
2819     {
2820         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2821         ddsd.dwSize = sizeof(ddsd);
2822         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2823         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2824         ddsd.dwWidth = 128;
2825         ddsd.dwHeight = 128;
2826         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2827         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2828         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2829         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2830         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2831         if (FAILED(hr)) goto out;
2832
2833         /* Check the number of created mipmaps */
2834         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2835         ddsd.dwSize = sizeof(ddsd);
2836         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2837         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2838         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2839         if (U2(ddsd).dwMipMapCount != 8) goto out;
2840
2841         for (i1 = 1; i1 < 8; i1++)
2842         {
2843             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2844             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2845             if (FAILED(hr)) goto out;
2846         }
2847     }
2848
2849     memset(table1, 0, sizeof(table1));
2850     for (i = 0; i < 3; i++)
2851     {
2852         table1[0].peBlue = i + 1;
2853         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2854         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2855         if (FAILED(hr))
2856         {
2857             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2858             goto out;
2859         }
2860     }
2861
2862     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2863     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2864
2865     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2866     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2867
2868     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2869     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2870
2871     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2872     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2873     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2874     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2875
2876     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2877     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2878
2879     memset(table1, 0, sizeof(table1));
2880     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2881     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2882     if (SUCCEEDED(hr))
2883     {
2884         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2885         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2886         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2887     }
2888
2889     /* Test colorkey copying. */
2890     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2891     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2892     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2893     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2894     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2895
2896     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2897     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2898
2899     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2900     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2901
2902     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2903     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2904     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2905         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2906
2907     out:
2908
2909     for (i = 0; i < 5; i++)
2910     {
2911         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2912     }
2913
2914     for (i = 0; i < 2; i++)
2915     {
2916         for (i1 = 7; i1 >= 0; i1--)
2917         {
2918             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2919         }
2920     }
2921
2922     for (i = 0; i < 2; i++)
2923         for (i1 = 5; i1 >= 0; i1--)
2924             for (i2 = 7; i2 >= 0; i2--)
2925             {
2926                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2927             }
2928 }
2929
2930 static void SetMaterialTest(void)
2931 {
2932     HRESULT rc;
2933
2934     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2935     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2936 }
2937
2938 static void ComputeSphereVisibility(void)
2939 {
2940     D3DMATRIX proj, view, world;
2941     D3DVALUE radius[3];
2942     D3DVECTOR center[3];
2943     DWORD result[3];
2944     HRESULT rc;
2945
2946     world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2947     world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2948     world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2949     world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2950
2951     view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2952     view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2953     view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2954     view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2955
2956     proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2957     proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2958     proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2959     proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2960
2961     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2962     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2963     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2964
2965     U1(center[0]).x=11.461533;
2966     U2(center[0]).y=-4.761727;
2967     U3(center[0]).z=-1.171646;
2968
2969     radius[0]=38.252632;
2970
2971     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2972
2973     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2974     ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2975
2976     U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
2977     radius[0]=4.354097;
2978     U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
2979     radius[1]=12.500704;
2980     U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
2981     radius[2]=17.251318;
2982
2983     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2984
2985     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2986     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2987     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2988     ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2989     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2990     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2991
2992     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2993     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2994     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2995     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2996
2997     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2998     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2999     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
3000     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
3001
3002     U1(center[0]).x=0.0;
3003     U2(center[0]).y=0.0;
3004     U3(center[0]).z=0.05;
3005
3006     radius[0]=0.04;
3007
3008     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
3009     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3010
3011     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3012
3013     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3014     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3015
3016     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
3017     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
3018     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
3019     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
3020
3021     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3022
3023     U1(center[0]).x=0.0;
3024     U2(center[0]).y=0.0;
3025     U3(center[0]).z=0.5;
3026
3027     radius[0]=0.5;
3028
3029     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3030
3031     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3032     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3033
3034     U1(center[0]).x=0.0;
3035     U2(center[0]).y=0.0;
3036     U3(center[0]).z=0.0;
3037
3038     radius[0]=0.0;
3039
3040     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3041
3042     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3043     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3044
3045     U1(center[0]).x=-1.0;
3046     U2(center[0]).y=-1.0;
3047     U3(center[0]).z=0.50;
3048
3049     radius[0]=0.25;
3050
3051     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3052
3053     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3054     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
3055
3056     U1(center[0]).x=-20.0;
3057     U2(center[0]).y=0.0;
3058     U3(center[0]).z=0.50;
3059
3060     radius[0]=3.0;
3061
3062     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3063
3064     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3065     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
3066
3067     U1(center[0]).x=20.0;
3068     U2(center[0]).y=0.0;
3069     U3(center[0]).z=0.50;
3070
3071     radius[0]=3.0f;
3072
3073     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3074
3075     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3076     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
3077
3078     U1(center[0]).x=0.0;
3079     U2(center[0]).y=-20.0;
3080     U3(center[0]).z=0.50;
3081
3082     radius[0]=3.0;
3083
3084     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3085
3086     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3087     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
3088
3089     U1(center[0]).x=0.0;
3090     U2(center[0]).y=20.0;
3091     U3(center[0]).z=0.5;
3092
3093     radius[0]=3.0;
3094
3095     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3096
3097     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3098     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
3099
3100     U1(center[0]).x=0.0;
3101     U2(center[0]).y=0.0;
3102     U3(center[0]).z=-20;
3103
3104     radius[0]=3.0;
3105
3106     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3107
3108     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3109     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
3110
3111     U1(center[0]).x=0.0;
3112     U2(center[0]).y=0.0;
3113     U3(center[0]).z=20.0;
3114
3115     radius[0]=3.0;
3116
3117     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3118
3119     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3120     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
3121 }
3122
3123 static void SetRenderTargetTest(void)
3124 {
3125     HRESULT hr;
3126     IDirectDrawSurface7 *newrt, *failrt, *oldrt;
3127     D3DVIEWPORT7 vp;
3128     DDSURFACEDESC2 ddsd, ddsd2;
3129     DWORD stateblock;
3130
3131     memset(&ddsd, 0, sizeof(ddsd));
3132     ddsd.dwSize = sizeof(ddsd);
3133     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3134     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
3135     ddsd.dwWidth = 64;
3136     ddsd.dwHeight = 64;
3137
3138     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
3139     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3140     if(FAILED(hr))
3141     {
3142         skip("Skipping SetRenderTarget test\n");
3143         return;
3144     }
3145
3146     memset(&ddsd2, 0, sizeof(ddsd2));
3147     ddsd2.dwSize = sizeof(ddsd2);
3148     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3149     ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER;
3150     ddsd2.dwWidth = 64;
3151     ddsd2.dwHeight = 64;
3152     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
3153     U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3154     U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3155     U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3156
3157     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd2, &failrt, NULL);
3158     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3159
3160     memset(&vp, 0, sizeof(vp));
3161     vp.dwX = 10;
3162     vp.dwY = 10;
3163     vp.dwWidth = 246;
3164     vp.dwHeight = 246;
3165     vp.dvMinZ = 0.25;
3166     vp.dvMaxZ = 0.75;
3167     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3168     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3169
3170     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3171     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3172
3173     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, failrt, 0);
3174     ok(hr != D3D_OK, "IDirect3DDevice7_SetRenderTarget succeeded\n");
3175
3176     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3177     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3178     memset(&vp, 0xff, sizeof(vp));
3179     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3180     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3181     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3182     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3183     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3184     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3185     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.25\n", vp.dvMinZ);
3186     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.75\n", vp.dvMaxZ);
3187
3188     memset(&vp, 0, sizeof(vp));
3189     vp.dwX = 0;
3190     vp.dwY = 0;
3191     vp.dwWidth = 64;
3192     vp.dwHeight = 64;
3193     vp.dvMinZ = 0.0;
3194     vp.dvMaxZ = 1.0;
3195     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3196     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3197
3198     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3199     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3200     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3201     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3202
3203     /* Check this twice, before and after ending the stateblock */
3204     memset(&vp, 0xff, sizeof(vp));
3205     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3206     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3207     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3208     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3209     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3210     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3211     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3212     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3213
3214     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3215     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3216
3217     memset(&vp, 0xff, sizeof(vp));
3218     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3219     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3220     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3221     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3222     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3223     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3224     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3225     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3226
3227     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3228     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3229
3230     memset(&vp, 0, sizeof(vp));
3231     vp.dwX = 0;
3232     vp.dwY = 0;
3233     vp.dwWidth = 256;
3234     vp.dwHeight = 256;
3235     vp.dvMinZ = 0.0;
3236     vp.dvMaxZ = 0.0;
3237     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3238     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3239
3240     IDirectDrawSurface7_Release(oldrt);
3241     IDirectDrawSurface7_Release(newrt);
3242     IDirectDrawSurface7_Release(failrt);
3243 }
3244
3245 static const UINT *expect_messages;
3246
3247 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3248 {
3249     if (expect_messages && message == *expect_messages) ++expect_messages;
3250
3251     return DefWindowProcA(hwnd, message, wparam, lparam);
3252 }
3253
3254 static void test_wndproc(void)
3255 {
3256     LONG_PTR proc, ddraw_proc;
3257     IDirectDraw7 *ddraw7;
3258     WNDCLASSA wc = {0};
3259     HWND window;
3260     HRESULT hr;
3261     ULONG ref;
3262
3263     static const UINT messages[] =
3264     {
3265         WM_WINDOWPOSCHANGING,
3266         WM_MOVE,
3267         WM_SIZE,
3268         WM_WINDOWPOSCHANGING,
3269         WM_ACTIVATE,
3270         WM_SETFOCUS,
3271         0,
3272     };
3273
3274     /* DDSCL_EXCLUSIVE replaces the window's window proc. */
3275     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3276     if (FAILED(hr))
3277     {
3278         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3279         return;
3280     }
3281
3282     wc.lpfnWndProc = test_proc;
3283     wc.lpszClassName = "d3d7_test_wndproc_wc";
3284     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3285
3286     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test",
3287             WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3288
3289     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3290     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3291             (LONG_PTR)test_proc, proc);
3292
3293     expect_messages = messages;
3294
3295     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3296     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3297     if (FAILED(hr))
3298     {
3299         IDirectDraw7_Release(ddraw7);
3300         goto done;
3301     }
3302
3303     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3304     expect_messages = NULL;
3305
3306     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3307     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3308             (LONG_PTR)test_proc, proc);
3309
3310     ref = IDirectDraw7_Release(ddraw7);
3311     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3312
3313     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3314     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3315             (LONG_PTR)test_proc, proc);
3316
3317     /* DDSCL_NORMAL doesn't. */
3318     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3319     if (FAILED(hr))
3320     {
3321         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3322         return;
3323     }
3324
3325     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3326     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3327             (LONG_PTR)test_proc, proc);
3328
3329     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3330     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3331     if (FAILED(hr))
3332     {
3333         IDirectDraw7_Release(ddraw7);
3334         goto done;
3335     }
3336
3337     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3338     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3339             (LONG_PTR)test_proc, proc);
3340
3341     ref = IDirectDraw7_Release(ddraw7);
3342     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3343
3344     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3345     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3346             (LONG_PTR)test_proc, proc);
3347
3348     /* The original window proc is only restored by ddraw if the current
3349      * window proc matches the one ddraw set. This also affects switching
3350      * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
3351     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3352     if (FAILED(hr))
3353     {
3354         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3355         return;
3356     }
3357
3358     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3359     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3360             (LONG_PTR)test_proc, proc);
3361
3362     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3363     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3364     if (FAILED(hr))
3365     {
3366         IDirectDraw7_Release(ddraw7);
3367         goto done;
3368     }
3369
3370     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3371     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3372             (LONG_PTR)test_proc, proc);
3373     ddraw_proc = proc;
3374
3375     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3376     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3377     if (FAILED(hr))
3378     {
3379         IDirectDraw7_Release(ddraw7);
3380         goto done;
3381     }
3382
3383     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3384     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3385             (LONG_PTR)test_proc, proc);
3386
3387     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3388     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3389     if (FAILED(hr))
3390     {
3391         IDirectDraw7_Release(ddraw7);
3392         goto done;
3393     }
3394
3395     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3396     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3397             (LONG_PTR)test_proc, proc);
3398
3399     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3400     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3401     if (FAILED(hr))
3402     {
3403         IDirectDraw7_Release(ddraw7);
3404         goto done;
3405     }
3406
3407     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3408     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3409             (LONG_PTR)DefWindowProcA, proc);
3410
3411     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3412     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3413     if (FAILED(hr))
3414     {
3415         IDirectDraw7_Release(ddraw7);
3416         goto done;
3417     }
3418
3419     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
3420     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3421             (LONG_PTR)DefWindowProcA, proc);
3422
3423     ref = IDirectDraw7_Release(ddraw7);
3424     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3425
3426     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3427     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3428             (LONG_PTR)test_proc, proc);
3429
3430     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3431     if (FAILED(hr))
3432     {
3433         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3434         return;
3435     }
3436
3437     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3438     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3439             (LONG_PTR)test_proc, proc);
3440
3441     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3442     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3443     if (FAILED(hr))
3444     {
3445         IDirectDraw7_Release(ddraw7);
3446         goto done;
3447     }
3448
3449     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3450     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3451             (LONG_PTR)test_proc, proc);
3452
3453     ref = IDirectDraw7_Release(ddraw7);
3454     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3455
3456     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3457     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3458             (LONG_PTR)DefWindowProcA, proc);
3459
3460 done:
3461     expect_messages = NULL;
3462     DestroyWindow(window);
3463     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
3464 }
3465
3466 static void VertexBufferLockRest(void)
3467 {
3468     D3DVERTEXBUFFERDESC desc;
3469     IDirect3DVertexBuffer7 *buffer;
3470     HRESULT hr;
3471     unsigned int i;
3472     void *data;
3473     const struct
3474     {
3475         DWORD flags;
3476         const char *debug_string;
3477         HRESULT result;
3478     }
3479     test_data[] =
3480     {
3481         {0,                                         "(none)",                                       D3D_OK },
3482         {DDLOCK_WAIT,                               "DDLOCK_WAIT",                                  D3D_OK },
3483         {DDLOCK_EVENT,                              "DDLOCK_EVENT",                                 D3D_OK },
3484         {DDLOCK_READONLY,                           "DDLOCK_READONLY",                              D3D_OK },
3485         {DDLOCK_WRITEONLY,                          "DDLOCK_WRITEONLY",                             D3D_OK },
3486         {DDLOCK_NOSYSLOCK,                          "DDLOCK_NOSYSLOCK",                             D3D_OK },
3487         {DDLOCK_NOOVERWRITE,                        "DDLOCK_NOOVERWRITE",                           D3D_OK },
3488         {DDLOCK_DISCARDCONTENTS,                    "DDLOCK_DISCARDCONTENTS",                       D3D_OK },
3489
3490         {DDLOCK_READONLY | DDLOCK_WRITEONLY,        "DDLOCK_READONLY | DDLOCK_WRITEONLY",           D3D_OK },
3491         {DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS,  "DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS",     D3D_OK },
3492         {0xdeadbeef,                                "0xdeadbeef",                                   D3D_OK },
3493     };
3494
3495     memset(&desc, 0 , sizeof(desc));
3496     desc.dwSize = sizeof(desc);
3497     desc.dwCaps = 0;
3498     desc.dwFVF = D3DFVF_XYZ;
3499     desc.dwNumVertices = 64;
3500     hr = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &buffer, 0);
3501     ok(hr == D3D_OK, "IDirect3D7_CreateVertexBuffer failed, 0x%08x\n", hr);
3502
3503     for(i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
3504     {
3505         hr = IDirect3DVertexBuffer7_Lock(buffer, test_data[i].flags, &data, NULL);
3506         ok(hr == test_data[i].result, "Lock flags %s returned 0x%08x, expected 0x%08x\n",
3507             test_data[i].debug_string, hr, test_data[i].result);
3508         if(SUCCEEDED(hr))
3509         {
3510             ok(data != NULL, "The data pointer returned by Lock is NULL\n");
3511             hr = IDirect3DVertexBuffer7_Unlock(buffer);
3512             ok(hr == D3D_OK, "IDirect3DVertexBuffer7_Unlock failed, 0x%08x\n", hr);
3513         }
3514     }
3515
3516     IDirect3DVertexBuffer7_Release(buffer);
3517 }
3518
3519 static void FindDevice(void)
3520 {
3521     static const struct
3522     {
3523         const GUID *guid;
3524         int todo;
3525     } deviceGUIDs[] =
3526     {
3527         {&IID_IDirect3DRampDevice, 1},
3528         {&IID_IDirect3DRGBDevice},
3529     };
3530
3531     static const GUID *nonexistent_deviceGUIDs[] = {&IID_IDirect3DMMXDevice,
3532                                                     &IID_IDirect3DRefDevice,
3533                                                     &IID_IDirect3DTnLHalDevice,
3534                                                     &IID_IDirect3DNullDevice};
3535
3536     D3DFINDDEVICESEARCH search = {0};
3537     D3DFINDDEVICERESULT result = {0};
3538     IDirect3DDevice *d3dhal;
3539     HRESULT hr;
3540     int i;
3541
3542     /* Test invalid parameters. */
3543     hr = IDirect3D_FindDevice(Direct3D1, NULL, NULL);
3544     ok(hr == DDERR_INVALIDPARAMS,
3545        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3546
3547     hr = IDirect3D_FindDevice(Direct3D1, NULL, &result);
3548     ok(hr == DDERR_INVALIDPARAMS,
3549        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3550
3551     hr = IDirect3D_FindDevice(Direct3D1, &search, NULL);
3552     ok(hr == DDERR_INVALIDPARAMS,
3553        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3554
3555     search.dwSize = 0;
3556     result.dwSize = 0;
3557
3558     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3559     ok(hr == DDERR_INVALIDPARAMS,
3560        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3561
3562     search.dwSize = sizeof(search) + 1;
3563     result.dwSize = sizeof(result) + 1;
3564
3565     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3566     ok(hr == DDERR_INVALIDPARAMS,
3567        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3568
3569     /* Specifying no flags is permitted. */
3570     search.dwSize = sizeof(search);
3571     search.dwFlags = 0;
3572     result.dwSize = sizeof(result);
3573
3574     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3575     ok(hr == D3D_OK,
3576        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3577
3578     /* Try an arbitrary non-device GUID. */
3579     search.dwSize = sizeof(search);
3580     search.dwFlags = D3DFDS_GUID;
3581     search.guid = IID_IDirect3D;
3582     result.dwSize = sizeof(result);
3583
3584     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3585     ok(hr == DDERR_NOTFOUND,
3586        "Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", hr);
3587
3588     /* These GUIDs appear to be never present. */
3589     for (i = 0; i < sizeof(nonexistent_deviceGUIDs)/sizeof(nonexistent_deviceGUIDs[0]); i++)
3590     {
3591         search.dwSize = sizeof(search);
3592         search.dwFlags = D3DFDS_GUID;
3593         search.guid = *nonexistent_deviceGUIDs[i];
3594         result.dwSize = sizeof(result);
3595
3596         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3597         ok(hr == DDERR_NOTFOUND,
3598            "[%d] Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", i, hr);
3599     }
3600
3601     /* The HAL device can only be enumerated if hardware acceleration is present. */
3602     search.dwSize = sizeof(search);
3603     search.dwFlags = D3DFDS_GUID;
3604     search.guid = IID_IDirect3DHALDevice;
3605     result.dwSize = sizeof(result);
3606
3607     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3608     trace("IDirect3D::FindDevice returned 0x%08x for the HAL device GUID\n", hr);
3609     if (SUCCEEDED(hr))
3610     {
3611         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3612         /* Currently Wine only supports the creation of one Direct3D device
3613          * for a given DirectDraw instance. */
3614         todo_wine
3615         ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
3616            "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3617
3618         if (SUCCEEDED(hr))
3619             IDirect3DDevice_Release(d3dhal);
3620     }
3621     else
3622     {
3623         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3624         ok(FAILED(hr), "Expected IDirectDrawSurface::QueryInterface to fail, got 0x%08x\n", hr);
3625
3626         if (SUCCEEDED(hr))
3627             IDirect3DDevice_Release(d3dhal);
3628     }
3629
3630     /* These GUIDs appear to be always present. */
3631     for (i = 0; i < sizeof(deviceGUIDs)/sizeof(deviceGUIDs[0]); i++)
3632     {
3633         search.dwSize = sizeof(search);
3634         search.dwFlags = D3DFDS_GUID;
3635         search.guid = *deviceGUIDs[i].guid;
3636         result.dwSize = sizeof(result);
3637
3638         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3639
3640         if (deviceGUIDs[i].todo)
3641         {
3642             todo_wine
3643             ok(hr == D3D_OK,
3644                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3645         }
3646         else
3647         {
3648             ok(hr == D3D_OK,
3649                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3650         }
3651     }
3652
3653     /* Curiously the color model criteria seem to be ignored. */
3654     search.dwSize = sizeof(search);
3655     search.dwFlags = D3DFDS_COLORMODEL;
3656     search.dcmColorModel = 0xdeadbeef;
3657     result.dwSize = sizeof(result);
3658
3659     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3660     todo_wine
3661     ok(hr == D3D_OK,
3662        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3663 }
3664
3665 static void BackBuffer3DCreateSurfaceTest(void)
3666 {
3667     DDSURFACEDESC ddsd;
3668     DDSURFACEDESC created_ddsd;
3669     DDSURFACEDESC2 ddsd2;
3670     IDirectDrawSurface *surf;
3671     IDirectDrawSurface4 *surf4;
3672     IDirectDrawSurface7 *surf7;
3673     HRESULT hr;
3674     IDirectDraw2 *dd2;
3675     IDirectDraw4 *dd4;
3676     IDirectDraw7 *dd7;
3677     DDCAPS ddcaps;
3678     IDirect3DDevice *d3dhal;
3679
3680     const DWORD caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3681     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3682
3683     memset(&ddcaps, 0, sizeof(ddcaps));
3684     ddcaps.dwSize = sizeof(DDCAPS);
3685     hr = IDirectDraw_GetCaps(DirectDraw1, &ddcaps, NULL);
3686     ok(SUCCEEDED(hr), "DirectDraw_GetCaps failed: 0x%08x\n", hr);
3687     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3688     {
3689         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3690         return ;
3691     }
3692
3693     memset(&ddsd, 0, sizeof(ddsd));
3694     ddsd.dwSize = sizeof(ddsd);
3695     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3696     ddsd.dwWidth = 64;
3697     ddsd.dwHeight = 64;
3698     ddsd.ddsCaps.dwCaps = caps;
3699     memset(&ddsd2, 0, sizeof(ddsd2));
3700     ddsd2.dwSize = sizeof(ddsd2);
3701     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3702     ddsd2.dwWidth = 64;
3703     ddsd2.dwHeight = 64;
3704     ddsd2.ddsCaps.dwCaps = caps;
3705     memset(&created_ddsd, 0, sizeof(created_ddsd));
3706     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3707
3708     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
3709     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3710     if (surf != NULL)
3711     {
3712         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3713         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3714         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3715            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3716            expected_caps);
3717
3718         hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3719         /* Currently Wine only supports the creation of one Direct3D device
3720            for a given DirectDraw instance. It has been created already
3721            in D3D1_createObjects() - IID_IDirect3DRGBDevice */
3722         todo_wine ok(SUCCEEDED(hr), "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3723
3724         if (SUCCEEDED(hr))
3725             IDirect3DDevice_Release(d3dhal);
3726
3727         IDirectDrawSurface_Release(surf);
3728     }
3729
3730     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw2, (void **) &dd2);
3731     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3732
3733     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3734     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3735        DDERR_INVALIDCAPS, hr);
3736
3737     IDirectDraw2_Release(dd2);
3738
3739     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void **) &dd4);
3740     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3741
3742     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3743     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3744        DDERR_INVALIDCAPS, hr);
3745
3746     IDirectDraw4_Release(dd4);
3747
3748     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw7, (void **) &dd7);
3749     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3750
3751     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3752     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3753        DDERR_INVALIDCAPS, hr);
3754
3755     IDirectDraw7_Release(dd7);
3756 }
3757
3758 static void BackBuffer3DAttachmentTest(void)
3759 {
3760     HRESULT hr;
3761     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3762     DDSURFACEDESC ddsd;
3763     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3764
3765     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3766     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3767
3768     /* Perform attachment tests on a back-buffer */
3769     memset(&ddsd, 0, sizeof(ddsd));
3770     ddsd.dwSize = sizeof(ddsd);
3771     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3772     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3773     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3774     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3775     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface2, NULL);
3776     ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3777
3778     if (surface2 != NULL)
3779     {
3780         /* Try a single primary and a two back buffers */
3781         memset(&ddsd, 0, sizeof(ddsd));
3782         ddsd.dwSize = sizeof(ddsd);
3783         ddsd.dwFlags = DDSD_CAPS;
3784         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3785         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface1, NULL);
3786         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3787
3788         memset(&ddsd, 0, sizeof(ddsd));
3789         ddsd.dwSize = sizeof(ddsd);
3790         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3791         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3792         ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3793         ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3794         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface3, NULL);
3795         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3796
3797         /* This one has a different size */
3798         memset(&ddsd, 0, sizeof(ddsd));
3799         ddsd.dwSize = sizeof(ddsd);
3800         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3801         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3802         ddsd.dwWidth = 128;
3803         ddsd.dwHeight = 128;
3804         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface4, NULL);
3805         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3806
3807         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3808         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3809            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3810         if(SUCCEEDED(hr))
3811         {
3812             /* Try the reverse without detaching first */
3813             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3814             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3815             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3816             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3817         }
3818         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3819         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3820            "Attaching a front buffer to a back buffer returned %08x\n", hr);
3821         if(SUCCEEDED(hr))
3822         {
3823             /* Try to detach reversed */
3824             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3825             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3826             /* Now the proper detach */
3827             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3828             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3829         }
3830         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3831         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3832            "Attaching a back buffer to another back buffer returned %08x\n", hr);
3833         if(SUCCEEDED(hr))
3834         {
3835             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
3836             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3837         }
3838         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
3839         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
3840         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
3841         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
3842
3843         IDirectDrawSurface_Release(surface4);
3844         IDirectDrawSurface_Release(surface3);
3845         IDirectDrawSurface_Release(surface2);
3846         IDirectDrawSurface_Release(surface1);
3847     }
3848
3849     hr =IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
3850     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3851
3852     DestroyWindow(window);
3853 }
3854
3855 START_TEST(d3d)
3856 {
3857     init_function_pointers();
3858     if(!pDirectDrawCreateEx) {
3859         win_skip("function DirectDrawCreateEx not available\n");
3860         return;
3861     }
3862
3863     if(!CreateDirect3D()) {
3864         skip("Skipping d3d7 tests\n");
3865     } else {
3866         LightTest();
3867         ProcessVerticesTest();
3868         StateTest();
3869         SceneTest();
3870         LimitTest();
3871         D3D7EnumTest();
3872         SetMaterialTest();
3873         ComputeSphereVisibility();
3874         CapsTest();
3875         VertexBufferDescTest();
3876         D3D7_OldRenderStateTest();
3877         DeviceLoadTest();
3878         SetRenderTargetTest();
3879         VertexBufferLockRest();
3880         ReleaseDirect3D();
3881     }
3882
3883     if (!D3D1_createObjects()) {
3884         skip("Skipping d3d1 tests\n");
3885     } else {
3886         Direct3D1Test();
3887         TextureLoadTest();
3888         ViewportTest();
3889         FindDevice();
3890         BackBuffer3DCreateSurfaceTest();
3891         BackBuffer3DAttachmentTest();
3892         D3D1_releaseObjects();
3893     }
3894
3895     test_wndproc();
3896 }