urlmon: Added stub for CoInternetGetSecurityUrlEx.
[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     idx = 0;
1298
1299     instr->bOpcode = D3DOP_TRIANGLE;
1300     instr->bSize = sizeof(D3DOP_TRIANGLE);
1301     instr->wCount = 0;
1302     instr++;
1303     instr->bOpcode = D3DOP_EXIT;
1304     instr->bSize = 0;
1305     instr->wCount = 0;
1306     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1307     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1308
1309     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1310     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1311
1312     memset(&transformdata, 0, sizeof(transformdata));
1313     transformdata.dwSize = sizeof(transformdata);
1314     transformdata.lpIn = testverts;
1315     transformdata.dwInSize = sizeof(testverts[0]);
1316     transformdata.lpOut = out;
1317     transformdata.dwOutSize = sizeof(out[0]);
1318
1319     transformdata.lpHOut = NULL;
1320     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1321                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1322                                              &i);
1323     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1324
1325     transformdata.lpHOut = outH;
1326     memset(outH, 0xcc, sizeof(outH));
1327     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1328                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1329                                              &i);
1330     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1331     ok(i == 0, "Offscreen is %d\n", i);
1332
1333     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1334         static const struct v_out cmp[] = {
1335             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1336             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1337         };
1338
1339         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1340            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1341            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1342            out[i].x, out[i].y, out[i].z, out[i].rhw,
1343            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1344     }
1345     for(i = 0; i < sizeof(outH); i++) {
1346         if(((unsigned char *) outH)[i] != 0xcc) {
1347             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1348             break;
1349         }
1350     }
1351
1352     SET_VP_DATA(vp_data);
1353     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1354     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1355     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1356                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1357                                              &i);
1358     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1359     ok(i == 0, "Offscreen is %d\n", i);
1360
1361     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1362         static const struct v_out cmp[] = {
1363             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1364             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1365         };
1366         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1367            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1368            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1369            out[i].x, out[i].y, out[i].z, out[i].rhw,
1370            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1371     }
1372
1373     SET_VP_DATA(vp_data);
1374     vp_data.dwX = 10;
1375     vp_data.dwY = 20;
1376     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1377     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1378     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1379                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1380                                              &i);
1381     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1382     ok(i == 0, "Offscreen is %d\n", i);
1383     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1384         static const struct v_out cmp[] = {
1385             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1386             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1387         };
1388         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1389            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1390            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1391            out[i].x, out[i].y, out[i].z, out[i].rhw,
1392            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1393     }
1394
1395     memset(out, 0xcc, sizeof(out));
1396     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1397                                              &transformdata, D3DTRANSFORM_CLIPPED,
1398                                              &i);
1399     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1400     ok(i == 0, "Offscreen is %d\n", i);
1401     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1402         static const D3DHVERTEX cmpH[] = {
1403             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1404             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1405             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1406         };
1407         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1408            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1409            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1410            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1411            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1412
1413         /* No scheme has been found behind those return values. It seems to be
1414          * whatever data windows has when throwing the vertex away. Modify the
1415          * input test vertices to test this more. Depending on the input data
1416          * it can happen that the z coord gets written into y, or similar things
1417          */
1418         if(0)
1419         {
1420             static const struct v_out cmp[] = {
1421                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1422                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1423             };
1424             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1425                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1426                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1427                out[i].x, out[i].y, out[i].z, out[i].rhw,
1428                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1429         }
1430     }
1431     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1432         ok(((DWORD *) out)[i] != 0xcccccccc,
1433                 "Regular output DWORD %d remained untouched\n", i);
1434     }
1435
1436     transformdata.lpIn = cliptest;
1437     transformdata.dwInSize = sizeof(cliptest[0]);
1438     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1439                                              &transformdata, D3DTRANSFORM_CLIPPED,
1440                                              &i);
1441     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1442     ok(i == 0, "Offscreen is %d\n", i);
1443     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1444         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1445         {
1446             0,
1447             0,
1448             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1449             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1450         };
1451         ok(Flags[i] == outH[i].dwFlags,
1452            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1453            outH[i].dwFlags, Flags[i]);
1454     }
1455
1456     SET_VP_DATA(vp_data);
1457     vp_data.dwWidth = 10;
1458     vp_data.dwHeight = 1000;
1459     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1460     i = 10;
1461     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1462     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1463                                              &transformdata, D3DTRANSFORM_CLIPPED,
1464                                              &i);
1465     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1466     ok(i == 0, "Offscreen is %d\n", i);
1467     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1468         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1469         {
1470             D3DCLIP_RIGHT,
1471             D3DCLIP_LEFT,
1472             D3DCLIP_RIGHT | D3DCLIP_BACK,
1473             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1474         };
1475         ok(Flags[i] == outH[i].dwFlags,
1476            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1477            outH[i].dwFlags, Flags[i]);
1478     }
1479
1480     SET_VP_DATA(vp_data);
1481     vp_data.dwWidth = 256;
1482     vp_data.dwHeight = 256;
1483     vp_data.dvScaleX = 1;
1484     vp_data.dvScaleY = 1;
1485     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1486     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1487     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1488                                              &transformdata, D3DTRANSFORM_CLIPPED,
1489                                              &i);
1490     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1491     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1492     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1493         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1494         {
1495             0,
1496             0,
1497             D3DCLIP_BACK,
1498             D3DCLIP_FRONT,
1499         };
1500         ok(Flags[i] == outH[i].dwFlags,
1501            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1502            outH[i].dwFlags, Flags[i]);
1503     }
1504
1505     /* Finally try to figure out how the DWORD dwOffscreen works.
1506      * Apparently no vertex is offscreen with clipping off,
1507      * and with clipping on the offscreen flag is set if only one vertex
1508      * is transformed, and this vertex is offscreen.
1509      */
1510     SET_VP_DATA(vp_data);
1511     vp_data.dwWidth = 5;
1512     vp_data.dwHeight = 5;
1513     vp_data.dvScaleX = 10000;
1514     vp_data.dvScaleY = 10000;
1515     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1516     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1517     transformdata.lpIn = cliptest;
1518     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1519                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1520                                              &i);
1521     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1522     ok(i == 0, "Offscreen is %d\n", i);
1523     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1524                                              &transformdata, D3DTRANSFORM_CLIPPED,
1525                                              &i);
1526     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1527     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1528     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1529                                              &transformdata, D3DTRANSFORM_CLIPPED,
1530                                              &i);
1531     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1532     ok(i == 0, "Offscreen is %d\n", i);
1533     transformdata.lpIn = cliptest + 1;
1534     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1535                                              &transformdata, D3DTRANSFORM_CLIPPED,
1536                                              &i);
1537     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1538     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1539
1540     transformdata.lpIn = offscreentest;
1541     transformdata.dwInSize = sizeof(offscreentest[0]);
1542     SET_VP_DATA(vp_data);
1543     vp_data.dwWidth = 257;
1544     vp_data.dwHeight = 257;
1545     vp_data.dvScaleX = 1;
1546     vp_data.dvScaleY = 1;
1547     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1548     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1549     i = 12345;
1550     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1551                                              &transformdata, D3DTRANSFORM_CLIPPED,
1552                                              &i);
1553     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1554     ok(i == 0, "Offscreen is %d\n", i);
1555     vp_data.dwWidth = 256;
1556     vp_data.dwHeight = 256;
1557     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1558     ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1559     i = 12345;
1560     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1561                                              &transformdata, D3DTRANSFORM_CLIPPED,
1562                                              &i);
1563     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1564     ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1565
1566     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1567                                              &transformdata, 0,
1568                                              &i);
1569     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1570
1571     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1572     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1573
1574     hr = IDirect3DViewport_AddLight(Viewport, Light);
1575     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1576     refcount = getRefcount((IUnknown*) Light);
1577     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1578
1579     hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1580     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1581     ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1582     refcount = getRefcount((IUnknown*) Light);
1583     ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1584
1585     hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1586     ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1587     refcount = getRefcount((IUnknown*) Light);
1588     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1589
1590     IDirect3DLight_Release(Light);
1591 }
1592
1593 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1594 {
1595     int i;
1596
1597     for (i = 0; i < 256; i++) {
1598        if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1599            table1[i].peBlue != table2[i].peBlue) return FALSE;
1600     }
1601
1602     return TRUE;
1603 }
1604
1605 /* test palette handling in IDirect3DTexture_Load */
1606 static void TextureLoadTest(void)
1607 {
1608     IDirectDrawSurface *TexSurface = NULL;
1609     IDirect3DTexture *Texture = NULL;
1610     IDirectDrawSurface *TexSurface2 = NULL;
1611     IDirect3DTexture *Texture2 = NULL;
1612     IDirectDrawPalette *palette = NULL;
1613     IDirectDrawPalette *palette2 = NULL;
1614     IDirectDrawPalette *palette_tmp = NULL;
1615     PALETTEENTRY table1[256], table2[256], table_tmp[256];
1616     HRESULT hr;
1617     DDSURFACEDESC ddsd;
1618     int i;
1619
1620     memset (&ddsd, 0, sizeof (ddsd));
1621     ddsd.dwSize = sizeof (ddsd);
1622     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1623     ddsd.dwHeight = 128;
1624     ddsd.dwWidth = 128;
1625     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1626     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1627     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1628     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1629
1630     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1631     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1632     if (FAILED(hr)) {
1633         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1634         goto cleanup;
1635     }
1636
1637     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1638                 (void *)&Texture);
1639     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1640     if (FAILED(hr)) {
1641         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1642         goto cleanup;
1643     }
1644
1645     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1646     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1647     if (FAILED(hr)) {
1648         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1649         goto cleanup;
1650     }
1651
1652     hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1653                 (void *)&Texture2);
1654     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1655     if (FAILED(hr)) {
1656         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1657         goto cleanup;
1658     }
1659
1660     /* test load of Texture to Texture */
1661     hr = IDirect3DTexture_Load(Texture, Texture);
1662     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1663
1664     /* test Load when both textures have no palette */
1665     hr = IDirect3DTexture_Load(Texture2, Texture);
1666     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1667
1668     for (i = 0; i < 256; i++) {
1669         table1[i].peRed = i;
1670         table1[i].peGreen = i;
1671         table1[i].peBlue = i;
1672         table1[i].peFlags = 0;
1673     }
1674
1675     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1676     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1677     if (FAILED(hr)) {
1678         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1679         goto cleanup;
1680     }
1681
1682     /* test Load when source texture has palette and destination has no palette */
1683     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1684     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1685     hr = IDirect3DTexture_Load(Texture2, Texture);
1686     ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1687
1688     for (i = 0; i < 256; i++) {
1689         table2[i].peRed = 255 - i;
1690         table2[i].peGreen = 255 - i;
1691         table2[i].peBlue = 255 - i;
1692         table2[i].peFlags = 0;
1693     }
1694
1695     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1696     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1697     if (FAILED(hr)) {
1698         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1699         goto cleanup;
1700     }
1701
1702     /* test Load when source has no palette and destination has a palette */
1703     hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1704     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1705     hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1706     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1707     hr = IDirect3DTexture_Load(Texture2, Texture);
1708     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1709     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1710     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1711     if (!palette_tmp) {
1712         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1713         goto cleanup;
1714     } else {
1715         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1716         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1717         ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1718         IDirectDrawPalette_Release(palette_tmp);
1719     }
1720
1721     /* test Load when both textures have palettes */
1722     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1723     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1724     hr = IDirect3DTexture_Load(Texture2, Texture);
1725     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1726     hr = IDirect3DTexture_Load(Texture2, Texture);
1727     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1728     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1729     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1730     if (!palette_tmp) {
1731         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1732         goto cleanup;
1733     } else {
1734         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1735         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1736         ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1737         IDirectDrawPalette_Release(palette_tmp);
1738     }
1739
1740     cleanup:
1741
1742     if (palette) IDirectDrawPalette_Release(palette);
1743     if (palette2) IDirectDrawPalette_Release(palette2);
1744     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1745     if (Texture) IDirect3DTexture_Release(Texture);
1746     if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1747     if (Texture2) IDirect3DTexture_Release(Texture2);
1748 }
1749
1750 static void VertexBufferDescTest(void)
1751 {
1752     HRESULT rc;
1753     D3DVERTEXBUFFERDESC desc;
1754     union mem_t
1755     {
1756         D3DVERTEXBUFFERDESC desc2;
1757         unsigned char buffer[512];
1758     } mem;
1759
1760     memset(&desc, 0, sizeof(desc));
1761     desc.dwSize = sizeof(desc);
1762     desc.dwCaps = 0;
1763     desc.dwFVF = D3DFVF_XYZ;
1764     desc.dwNumVertices = 1;
1765     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1766     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1767     if (!lpVBufSrc)
1768     {
1769         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1770         goto out;
1771     }
1772
1773     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1774     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1775     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1776     if(rc != D3D_OK)
1777         skip("GetVertexBuffer Failed!\n");
1778     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1779     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1780     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1781     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1782     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1783
1784     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1785     mem.desc2.dwSize = 0;
1786     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1787     if(rc != D3D_OK)
1788         skip("GetVertexBuffer Failed!\n");
1789     ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1790     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1791     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1792     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1793     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1794
1795     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1796     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1797     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1798     if(rc != D3D_OK)
1799         skip("GetVertexBuffer Failed!\n");
1800     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1801     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1802     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1803     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1804     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1805
1806 out:
1807     IDirect3DVertexBuffer7_Release(lpVBufSrc);
1808 }
1809
1810 static void D3D7_OldRenderStateTest(void)
1811 {
1812     HRESULT hr;
1813     DWORD val;
1814
1815     /* Test reaction to some deprecated states in D3D7. */
1816     hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1817     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1818     hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1819     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1820     hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1821     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1822     hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1823     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1824 }
1825
1826 #define IS_VALUE_NEAR(a, b)    ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1827 #define MIN(a, b)    ((a) < (b) ? (a) : (b))
1828
1829 static void DeviceLoadTest(void)
1830 {
1831     DDSURFACEDESC2 ddsd;
1832     IDirectDrawSurface7 *texture_levels[2][8];
1833     IDirectDrawSurface7 *cube_face_levels[2][6][8];
1834     DWORD flags;
1835     HRESULT hr;
1836     DDBLTFX ddbltfx;
1837     RECT loadrect;
1838     POINT loadpoint;
1839     int i, i1, i2;
1840     unsigned diff_count = 0, diff_count2 = 0;
1841     unsigned x, y;
1842     BOOL load_mip_subset_broken = FALSE;
1843     IDirectDrawPalette *palettes[5];
1844     PALETTEENTRY table1[256];
1845     DDCOLORKEY ddckey;
1846     D3DDEVICEDESC7 d3dcaps;
1847
1848     /* Test loading of texture subrectangle with a mipmap surface. */
1849     memset(texture_levels, 0, sizeof(texture_levels));
1850     memset(cube_face_levels, 0, sizeof(cube_face_levels));
1851     memset(palettes, 0, sizeof(palettes));
1852
1853     for (i = 0; i < 2; i++)
1854     {
1855         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1856         ddsd.dwSize = sizeof(ddsd);
1857         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1858         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1859         ddsd.dwWidth = 128;
1860         ddsd.dwHeight = 128;
1861         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1862         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1863         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1864         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1865         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1866         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1867         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1868         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1869         if (FAILED(hr)) goto out;
1870
1871         /* Check the number of created mipmaps */
1872         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1873         ddsd.dwSize = sizeof(ddsd);
1874         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1875         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1876         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1877         if (U2(ddsd).dwMipMapCount != 8) goto out;
1878
1879         for (i1 = 1; i1 < 8; i1++)
1880         {
1881             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1882             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1883             if (FAILED(hr)) goto out;
1884         }
1885     }
1886
1887     for (i1 = 0; i1 < 8; i1++)
1888     {
1889         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1890         ddsd.dwSize = sizeof(ddsd);
1891         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1892         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1893         if (FAILED(hr)) goto out;
1894
1895         for (y = 0 ; y < ddsd.dwHeight; y++)
1896         {
1897             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1898
1899             for (x = 0; x < ddsd.dwWidth;  x++)
1900             {
1901                 /* x stored in green component, y in blue. */
1902                 DWORD color = 0xff0000 | (x << 8)  | y;
1903                 *textureRow++ = color;
1904             }
1905         }
1906
1907         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1908         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1909     }
1910
1911     for (i1 = 0; i1 < 8; i1++)
1912     {
1913         memset(&ddbltfx, 0, sizeof(ddbltfx));
1914         ddbltfx.dwSize = sizeof(ddbltfx);
1915         U5(ddbltfx).dwFillColor = 0;
1916         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1917         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1918     }
1919
1920     /* First test some broken coordinates. */
1921     loadpoint.x = loadpoint.y = 0;
1922     loadrect.left = 0;
1923     loadrect.top = 0;
1924     loadrect.right = 0;
1925     loadrect.bottom = 0;
1926     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1927     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1928
1929     loadpoint.x = loadpoint.y = 50;
1930     loadrect.left = 0;
1931     loadrect.top = 0;
1932     loadrect.right = 100;
1933     loadrect.bottom = 100;
1934     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1935     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1936
1937     /* Test actual loading. */
1938     loadpoint.x = loadpoint.y = 31;
1939     loadrect.left = 30;
1940     loadrect.top = 20;
1941     loadrect.right = 93;
1942     loadrect.bottom = 52;
1943
1944     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1945     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1946
1947     for (i1 = 0; i1 < 8; i1++)
1948     {
1949         diff_count = 0;
1950         diff_count2 = 0;
1951
1952         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1953         ddsd.dwSize = sizeof(ddsd);
1954         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1955         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1956         if (FAILED(hr)) goto out;
1957
1958         for (y = 0 ; y < ddsd.dwHeight; y++)
1959         {
1960             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1961
1962             for (x = 0; x < ddsd.dwWidth;  x++)
1963             {
1964                 DWORD color = *textureRow++;
1965
1966                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1967                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1968                 {
1969                     if (color & 0xffffff) diff_count++;
1970                 }
1971                 else
1972                 {
1973                     DWORD r = (color & 0xff0000) >> 16;
1974                     DWORD g = (color & 0xff00) >> 8;
1975                     DWORD b = (color & 0xff);
1976
1977                     if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1978                 }
1979
1980                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1981                    technically be correct as it's not precisely defined by docs. */
1982                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1983                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1984                 {
1985                     if (color & 0xffffff) diff_count2++;
1986                 }
1987                 else
1988                 {
1989                     DWORD r = (color & 0xff0000) >> 16;
1990                     DWORD g = (color & 0xff00) >> 8;
1991                     DWORD b = (color & 0xff);
1992
1993                     if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1994                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1995                 }
1996             }
1997         }
1998
1999         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2000         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2001
2002         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2003                 MIN(diff_count, diff_count2), i1);
2004
2005         loadpoint.x /= 2;
2006         loadpoint.y /= 2;
2007         loadrect.top /= 2;
2008         loadrect.left /= 2;
2009         loadrect.right = (loadrect.right + 1) / 2;
2010         loadrect.bottom = (loadrect.bottom + 1) / 2;
2011     }
2012
2013     /* This crashes on native (tested on real windows XP / directx9 / nvidia and
2014      * qemu Win98 / directx7 / RGB software rasterizer):
2015      * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
2016     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
2017     */
2018
2019     /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
2020     for (i = 0; i < 2; i++)
2021     {
2022         for (i1 = 7; i1 >= 0; i1--)
2023         {
2024             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2025         }
2026     }
2027     memset(texture_levels, 0, sizeof(texture_levels));
2028
2029     /* Test texture size mismatch. */
2030     for (i = 0; i < 2; i++)
2031     {
2032         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2033         ddsd.dwSize = sizeof(ddsd);
2034         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2035         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2036         ddsd.dwWidth = i ? 256 : 128;
2037         ddsd.dwHeight = 128;
2038         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2039         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2040         if (FAILED(hr)) goto out;
2041     }
2042
2043     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2044     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2045
2046     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
2047     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2048
2049     IDirectDrawSurface7_Release(texture_levels[0][0]);
2050     IDirectDrawSurface7_Release(texture_levels[1][0]);
2051     memset(texture_levels, 0, sizeof(texture_levels));
2052
2053     memset(&d3dcaps, 0, sizeof(d3dcaps));
2054     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
2055     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
2056
2057     if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
2058     {
2059         skip("No cubemap support\n");
2060     }
2061     else
2062     {
2063         /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
2064         for (i = 0; i < 2; i++)
2065         {
2066             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2067             ddsd.dwSize = sizeof(ddsd);
2068             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2069             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2070             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2071             ddsd.dwWidth = 128;
2072             ddsd.dwHeight = 128;
2073             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2074             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2075             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2076             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2077             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2078             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2079             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
2080             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2081             if (FAILED(hr)) goto out;
2082
2083             flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
2084             for (i1 = 1; i1 < 6; i1++, flags <<= 1)
2085             {
2086                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2087                 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
2088                 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
2089                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2090                 if (FAILED(hr)) goto out;
2091             }
2092
2093             for (i1 = 0; i1 < 6; i1++)
2094             {
2095                 /* Check the number of created mipmaps */
2096                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2097                 ddsd.dwSize = sizeof(ddsd);
2098                 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
2099                 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2100                 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2101                 if (U2(ddsd).dwMipMapCount != 8) goto out;
2102
2103                 for (i2 = 1; i2 < 8; i2++)
2104                 {
2105                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
2106                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
2107                     hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
2108                     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2109                     if (FAILED(hr)) goto out;
2110                 }
2111             }
2112         }
2113
2114         for (i = 0; i < 6; i++)
2115             for (i1 = 0; i1 < 8; i1++)
2116             {
2117                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2118                 ddsd.dwSize = sizeof(ddsd);
2119                 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2120                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2121                 if (FAILED(hr)) goto out;
2122
2123                 for (y = 0 ; y < ddsd.dwHeight; y++)
2124                 {
2125                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2126
2127                     for (x = 0; x < ddsd.dwWidth;  x++)
2128                     {
2129                         /* face number in low 4 bits of red, x stored in green component, y in blue. */
2130                         DWORD color = 0xf00000 | (i << 16) | (x << 8)  | y;
2131                         *textureRow++ = color;
2132                     }
2133                 }
2134
2135                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
2136                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2137             }
2138
2139         for (i = 0; i < 6; i++)
2140             for (i1 = 0; i1 < 8; i1++)
2141             {
2142                 memset(&ddbltfx, 0, sizeof(ddbltfx));
2143                 ddbltfx.dwSize = sizeof(ddbltfx);
2144                 U5(ddbltfx).dwFillColor = 0;
2145                 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2146                 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2147             }
2148
2149         loadpoint.x = loadpoint.y = 10;
2150         loadrect.left = 30;
2151         loadrect.top = 20;
2152         loadrect.right = 93;
2153         loadrect.bottom = 52;
2154
2155         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2156                                         DDSCAPS2_CUBEMAP_ALLFACES);
2157         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2158
2159         for (i = 0; i < 6; i++)
2160         {
2161             loadpoint.x = loadpoint.y = 10;
2162             loadrect.left = 30;
2163             loadrect.top = 20;
2164             loadrect.right = 93;
2165             loadrect.bottom = 52;
2166
2167             for (i1 = 0; i1 < 8; i1++)
2168             {
2169                 diff_count = 0;
2170                 diff_count2 = 0;
2171
2172                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2173                 ddsd.dwSize = sizeof(ddsd);
2174                 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2175                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2176                 if (FAILED(hr)) goto out;
2177
2178                 for (y = 0 ; y < ddsd.dwHeight; y++)
2179                 {
2180                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2181
2182                     for (x = 0; x < ddsd.dwWidth;  x++)
2183                     {
2184                         DWORD color = *textureRow++;
2185
2186                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2187                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2188                         {
2189                             if (color & 0xffffff) diff_count++;
2190                         }
2191                         else
2192                         {
2193                             DWORD r = (color & 0xff0000) >> 16;
2194                             DWORD g = (color & 0xff00) >> 8;
2195                             DWORD b = (color & 0xff);
2196
2197                             if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2198                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2199                         }
2200
2201                         /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2202                         technically be correct as it's not precisely defined by docs. */
2203                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2204                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2205                         {
2206                             if (color & 0xffffff) diff_count2++;
2207                         }
2208                         else
2209                         {
2210                             DWORD r = (color & 0xff0000) >> 16;
2211                             DWORD g = (color & 0xff00) >> 8;
2212                             DWORD b = (color & 0xff);
2213
2214                             if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2215                                 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2216                         }
2217                     }
2218                 }
2219
2220                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2221                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2222
2223                 ok(diff_count == 0 || diff_count2 == 0,
2224                     "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2225                     MIN(diff_count, diff_count2), i, i1);
2226
2227                 loadpoint.x /= 2;
2228                 loadpoint.y /= 2;
2229                 loadrect.top /= 2;
2230                 loadrect.left /= 2;
2231                 loadrect.right = (loadrect.right + 1) / 2;
2232                 loadrect.bottom = (loadrect.bottom + 1) / 2;
2233             }
2234         }
2235
2236         for (i = 0; i < 2; i++)
2237             for (i1 = 5; i1 >= 0; i1--)
2238                 for (i2 = 7; i2 >= 0; i2--)
2239                 {
2240                     if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2241                 }
2242         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2243
2244         /* Test cubemap loading from regular texture. */
2245         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2246         ddsd.dwSize = sizeof(ddsd);
2247         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2248         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2249         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2250         ddsd.dwWidth = 128;
2251         ddsd.dwHeight = 128;
2252         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2253         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2254         if (FAILED(hr)) goto out;
2255
2256         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2257         ddsd.dwSize = sizeof(ddsd);
2258         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2259         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2260         ddsd.dwWidth = 128;
2261         ddsd.dwHeight = 128;
2262         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2263         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2264         if (FAILED(hr)) goto out;
2265
2266         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2267                                         DDSCAPS2_CUBEMAP_ALLFACES);
2268         ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2269
2270         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2271         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2272         IDirectDrawSurface7_Release(texture_levels[0][0]);
2273         memset(texture_levels, 0, sizeof(texture_levels));
2274
2275         /* Test cubemap loading from cubemap with different number of faces. */
2276         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2277         ddsd.dwSize = sizeof(ddsd);
2278         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2279         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2280         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2281         ddsd.dwWidth = 128;
2282         ddsd.dwHeight = 128;
2283         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2284         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2285         if (FAILED(hr)) goto out;
2286
2287         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2288         ddsd.dwSize = sizeof(ddsd);
2289         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2290         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2291         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2292         ddsd.dwWidth = 128;
2293         ddsd.dwHeight = 128;
2294         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2295         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2296         if (FAILED(hr)) goto out;
2297
2298         /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2299             (the above created cubemaps will have all faces. */
2300         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2301                                         DDSCAPS2_CUBEMAP_ALLFACES);
2302         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2303
2304         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2305                                         DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2306         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2307
2308         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2309                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2310         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2311
2312         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2313                                         DDSCAPS2_CUBEMAP_ALLFACES);
2314         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2315
2316         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2317                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2318         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2319
2320         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2321                                         DDSCAPS2_CUBEMAP_POSITIVEZ);
2322         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2323
2324         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2325         IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2326         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2327     }
2328
2329     /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2330     for (i = 0; i < 2; i++)
2331     {
2332         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2333         ddsd.dwSize = sizeof(ddsd);
2334         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2335         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2336         ddsd.dwWidth = 128;
2337         ddsd.dwHeight = 128;
2338         U2(ddsd).dwMipMapCount = i ? 4 : 8;
2339         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2340         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2341         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2342         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2343         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2344         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2345         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2346         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2347         if (FAILED(hr)) goto out;
2348
2349         /* Check the number of created mipmaps */
2350         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2351         ddsd.dwSize = sizeof(ddsd);
2352         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2353         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2354         ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2355         if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2356
2357         for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2358         {
2359             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2360             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2361             if (FAILED(hr)) goto out;
2362         }
2363     }
2364
2365     for (i1 = 0; i1 < 8; i1++)
2366     {
2367         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2368         ddsd.dwSize = sizeof(ddsd);
2369         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2370         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2371         if (FAILED(hr)) goto out;
2372
2373         for (y = 0 ; y < ddsd.dwHeight; y++)
2374         {
2375             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2376
2377             for (x = 0; x < ddsd.dwWidth;  x++)
2378             {
2379                 /* x stored in green component, y in blue. */
2380                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2381                 *textureRow++ = color;
2382             }
2383         }
2384
2385         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2386         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2387     }
2388
2389     for (i1 = 0; i1 < 4; i1++)
2390     {
2391         memset(&ddbltfx, 0, sizeof(ddbltfx));
2392         ddbltfx.dwSize = sizeof(ddbltfx);
2393         U5(ddbltfx).dwFillColor = 0;
2394         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2395         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2396     }
2397
2398     loadpoint.x = loadpoint.y = 31;
2399     loadrect.left = 30;
2400     loadrect.top = 20;
2401     loadrect.right = 93;
2402     loadrect.bottom = 52;
2403
2404     /* Destination mip levels are a subset of source mip levels. */
2405     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2406     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2407
2408     for (i1 = 0; i1 < 4; i1++)
2409     {
2410         diff_count = 0;
2411         diff_count2 = 0;
2412
2413         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2414         ddsd.dwSize = sizeof(ddsd);
2415         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2416         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2417         if (FAILED(hr)) goto out;
2418
2419         for (y = 0 ; y < ddsd.dwHeight; y++)
2420         {
2421             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2422
2423             for (x = 0; x < ddsd.dwWidth;  x++)
2424             {
2425                 DWORD color = *textureRow++;
2426
2427                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2428                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2429                 {
2430                     if (color & 0xffffff) diff_count++;
2431                 }
2432                 else
2433                 {
2434                     DWORD r = (color & 0xff0000) >> 16;
2435                     DWORD g = (color & 0xff00) >> 8;
2436                     DWORD b = (color & 0xff);
2437
2438                     if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2439                         b != y + loadrect.top - loadpoint.y) diff_count++;
2440                 }
2441
2442                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2443                 technically be correct as it's not precisely defined by docs. */
2444                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2445                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2446                 {
2447                     if (color & 0xffffff) diff_count2++;
2448                 }
2449                 else
2450                 {
2451                     DWORD r = (color & 0xff0000) >> 16;
2452                     DWORD g = (color & 0xff00) >> 8;
2453                     DWORD b = (color & 0xff);
2454
2455                     if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2456                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2457                 }
2458             }
2459         }
2460
2461         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2462         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2463
2464         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2465              MIN(diff_count, diff_count2), i1);
2466
2467         loadpoint.x /= 2;
2468         loadpoint.y /= 2;
2469         loadrect.top /= 2;
2470         loadrect.left /= 2;
2471         loadrect.right = (loadrect.right + 1) / 2;
2472         loadrect.bottom = (loadrect.bottom + 1) / 2;
2473     }
2474
2475     /* Destination mip levels are a superset of source mip levels (should fail). */
2476     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2477     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2478
2479     for (i = 0; i < 2; i++)
2480     {
2481         for (i1 = 7; i1 >= 0; i1--)
2482         {
2483             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2484         }
2485     }
2486     memset(texture_levels, 0, sizeof(texture_levels));
2487
2488     /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2489     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2490     ddsd.dwSize = sizeof(ddsd);
2491     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2492     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2493     ddsd.dwWidth = 128;
2494     ddsd.dwHeight = 128;
2495     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2496     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2497     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2498     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2499     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2500     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2501     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2502     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2503     if (FAILED(hr)) goto out;
2504
2505     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2506     ddsd.dwSize = sizeof(ddsd);
2507     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2508     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2509     ddsd.dwWidth = 32;
2510     ddsd.dwHeight = 32;
2511     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2512     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2513     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2514     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2515     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2516     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2517     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2518     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2519     if (FAILED(hr)) goto out;
2520
2521     for (i1 = 1; i1 < 8; i1++)
2522     {
2523         hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2524         ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2525         if (FAILED(hr)) goto out;
2526     }
2527
2528     for (i1 = 0; i1 < 8; i1++)
2529     {
2530         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2531         ddsd.dwSize = sizeof(ddsd);
2532         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2533         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2534         if (FAILED(hr)) goto out;
2535
2536         for (y = 0 ; y < ddsd.dwHeight; y++)
2537         {
2538             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2539
2540             for (x = 0; x < ddsd.dwWidth;  x++)
2541             {
2542                 /* x stored in green component, y in blue. */
2543                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2544                 *textureRow++ = color;
2545             }
2546         }
2547
2548         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2549         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2550     }
2551
2552     memset(&ddbltfx, 0, sizeof(ddbltfx));
2553     ddbltfx.dwSize = sizeof(ddbltfx);
2554     U5(ddbltfx).dwFillColor = 0;
2555     hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2556     ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2557
2558     loadpoint.x = loadpoint.y = 32;
2559     loadrect.left = 32;
2560     loadrect.top = 32;
2561     loadrect.right = 96;
2562     loadrect.bottom = 96;
2563
2564     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2565     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2566
2567     loadpoint.x /= 4;
2568     loadpoint.y /= 4;
2569     loadrect.top /= 4;
2570     loadrect.left /= 4;
2571     loadrect.right = (loadrect.right + 3) / 4;
2572     loadrect.bottom = (loadrect.bottom + 3) / 4;
2573
2574     /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2575      * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2576      * copied subrectangles divided more than needed, without apparent logic. But it works
2577      * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2578      * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2579      * The following code attempts to detect broken results, actual tests will then be skipped
2580      */
2581     load_mip_subset_broken = TRUE;
2582     diff_count = 0;
2583
2584     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2585     ddsd.dwSize = sizeof(ddsd);
2586     hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2587     ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2588     if (FAILED(hr)) goto out;
2589
2590     for (y = 0 ; y < ddsd.dwHeight; y++)
2591     {
2592         DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2593
2594         for (x = 0; x < ddsd.dwWidth;  x++)
2595         {
2596             DWORD color = *textureRow++;
2597
2598             if (x < 2 || x >= 2 + 4 ||
2599                 y < 2 || y >= 2 + 4)
2600             {
2601                 if (color & 0xffffff) diff_count++;
2602             }
2603             else
2604             {
2605                 DWORD r = (color & 0xff0000) >> 16;
2606
2607                 if ((r & (0xf0)) != 0xf0) diff_count++;
2608             }
2609         }
2610     }
2611
2612     if (diff_count) load_mip_subset_broken = FALSE;
2613
2614     if (load_mip_subset_broken) {
2615         skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2616     } else {
2617         diff_count = 0;
2618
2619         for (y = 0 ; y < ddsd.dwHeight; y++)
2620         {
2621             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2622
2623             for (x = 0; x < ddsd.dwWidth;  x++)
2624             {
2625                 DWORD color = *textureRow++;
2626
2627                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2628                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2629                 {
2630                     if (color & 0xffffff) diff_count++;
2631                 }
2632                 else
2633                 {
2634                     DWORD r = (color & 0xff0000) >> 16;
2635                     DWORD g = (color & 0xff00) >> 8;
2636                     DWORD b = (color & 0xff);
2637
2638                     if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2639                         b != y + loadrect.top - loadpoint.y) diff_count++;
2640                 }
2641             }
2642         }
2643     }
2644
2645     hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2646     ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2647
2648     ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2649
2650     for (i = 0; i < 2; i++)
2651     {
2652         for (i1 = 7; i1 >= 0; i1--)
2653         {
2654             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2655         }
2656     }
2657     memset(texture_levels, 0, sizeof(texture_levels));
2658
2659     if (!load_mip_subset_broken)
2660     {
2661         /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2662         * surface (than first source mip level)
2663         */
2664         for (i = 0; i < 2; i++)
2665         {
2666             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2667             ddsd.dwSize = sizeof(ddsd);
2668             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2669             if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2670             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2671             ddsd.dwWidth = i ? 32 : 128;
2672             ddsd.dwHeight = i ? 32 : 128;
2673             if (i) U2(ddsd).dwMipMapCount = 4;
2674             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2675             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2676             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2677             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2678             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2679             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2680             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2681             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2682             if (FAILED(hr)) goto out;
2683
2684             /* Check the number of created mipmaps */
2685             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2686             ddsd.dwSize = sizeof(ddsd);
2687             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2688             ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2689             ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2690             if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2691
2692             for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2693             {
2694                 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2695                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2696                 if (FAILED(hr)) goto out;
2697             }
2698         }
2699
2700         for (i1 = 0; i1 < 8; i1++)
2701         {
2702             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2703             ddsd.dwSize = sizeof(ddsd);
2704             hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2705             ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2706             if (FAILED(hr)) goto out;
2707
2708             for (y = 0 ; y < ddsd.dwHeight; y++)
2709             {
2710                 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2711
2712                 for (x = 0; x < ddsd.dwWidth;  x++)
2713                 {
2714                     /* x stored in green component, y in blue. */
2715                     DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2716                     *textureRow++ = color;
2717                 }
2718             }
2719
2720             hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2721             ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2722         }
2723
2724         for (i1 = 0; i1 < 4; i1++)
2725         {
2726             memset(&ddbltfx, 0, sizeof(ddbltfx));
2727             ddbltfx.dwSize = sizeof(ddbltfx);
2728             U5(ddbltfx).dwFillColor = 0;
2729             hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2730             ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2731         }
2732
2733         loadpoint.x = loadpoint.y = 0;
2734         loadrect.left = 0;
2735         loadrect.top = 0;
2736         loadrect.right = 64;
2737         loadrect.bottom = 64;
2738
2739         hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2740         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2741
2742         i = 0;
2743         for (i1 = 0; i1 < 8 && i < 4; i1++)
2744         {
2745             DDSURFACEDESC2 ddsd2;
2746
2747             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2748             ddsd.dwSize = sizeof(ddsd);
2749             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2750             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2751
2752             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2753             ddsd2.dwSize = sizeof(ddsd2);
2754             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2755             ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2756
2757             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2758             {
2759                 diff_count = 0;
2760
2761                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2762                 ddsd.dwSize = sizeof(ddsd);
2763                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2764                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2765                 if (FAILED(hr)) goto out;
2766
2767                 for (y = 0 ; y < ddsd.dwHeight; y++)
2768                 {
2769                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2770
2771                     for (x = 0; x < ddsd.dwWidth;  x++)
2772                     {
2773                         DWORD color = *textureRow++;
2774
2775                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2776                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2777                         {
2778                             if (color & 0xffffff) diff_count++;
2779                         }
2780                         else
2781                         {
2782                             DWORD r = (color & 0xff0000) >> 16;
2783                             DWORD g = (color & 0xff00) >> 8;
2784                             DWORD b = (color & 0xff);
2785
2786                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2787                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2788                         }
2789                     }
2790                 }
2791
2792                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2793                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2794
2795                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2796
2797                 i++;
2798             }
2799
2800             loadpoint.x /= 2;
2801             loadpoint.y /= 2;
2802             loadrect.top /= 2;
2803             loadrect.left /= 2;
2804             loadrect.right = (loadrect.right + 1) / 2;
2805             loadrect.bottom = (loadrect.bottom + 1) / 2;
2806         }
2807
2808         for (i = 0; i < 2; i++)
2809         {
2810             for (i1 = 7; i1 >= 0; i1--)
2811             {
2812                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2813             }
2814         }
2815         memset(texture_levels, 0, sizeof(texture_levels));
2816     }
2817
2818     /* Test palette copying. */
2819     for (i = 0; i < 2; i++)
2820     {
2821         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2822         ddsd.dwSize = sizeof(ddsd);
2823         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2824         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2825         ddsd.dwWidth = 128;
2826         ddsd.dwHeight = 128;
2827         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2828         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2829         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2830         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2831         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2832         if (FAILED(hr)) goto out;
2833
2834         /* Check the number of created mipmaps */
2835         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2836         ddsd.dwSize = sizeof(ddsd);
2837         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2838         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2839         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2840         if (U2(ddsd).dwMipMapCount != 8) goto out;
2841
2842         for (i1 = 1; i1 < 8; i1++)
2843         {
2844             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2845             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2846             if (FAILED(hr)) goto out;
2847         }
2848     }
2849
2850     memset(table1, 0, sizeof(table1));
2851     for (i = 0; i < 3; i++)
2852     {
2853         table1[0].peBlue = i + 1;
2854         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2855         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2856         if (FAILED(hr))
2857         {
2858             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2859             goto out;
2860         }
2861     }
2862
2863     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2864     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2865
2866     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2867     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2868
2869     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2870     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2871
2872     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2873     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2874     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2875     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2876
2877     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2878     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2879
2880     memset(table1, 0, sizeof(table1));
2881     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2882     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2883     if (SUCCEEDED(hr))
2884     {
2885         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2886         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2887         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2888     }
2889
2890     /* Test colorkey copying. */
2891     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2892     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2893     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2894     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2895     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2896
2897     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2898     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2899
2900     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2901     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2902
2903     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2904     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2905     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2906         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2907
2908     out:
2909
2910     for (i = 0; i < 5; i++)
2911     {
2912         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2913     }
2914
2915     for (i = 0; i < 2; i++)
2916     {
2917         for (i1 = 7; i1 >= 0; i1--)
2918         {
2919             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2920         }
2921     }
2922
2923     for (i = 0; i < 2; i++)
2924         for (i1 = 5; i1 >= 0; i1--)
2925             for (i2 = 7; i2 >= 0; i2--)
2926             {
2927                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2928             }
2929 }
2930
2931 static void SetMaterialTest(void)
2932 {
2933     HRESULT rc;
2934
2935     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2936     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2937 }
2938
2939 static void ComputeSphereVisibility(void)
2940 {
2941     D3DMATRIX proj, view, world;
2942     D3DVALUE radius[3];
2943     D3DVECTOR center[3];
2944     DWORD result[3];
2945     HRESULT rc;
2946
2947     world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2948     world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2949     world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2950     world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2951
2952     view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2953     view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2954     view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2955     view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2956
2957     proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2958     proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2959     proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2960     proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2961
2962     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2963     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2964     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2965
2966     U1(center[0]).x=11.461533;
2967     U2(center[0]).y=-4.761727;
2968     U3(center[0]).z=-1.171646;
2969
2970     radius[0]=38.252632;
2971
2972     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2973
2974     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2975     ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2976
2977     U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
2978     radius[0]=4.354097;
2979     U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
2980     radius[1]=12.500704;
2981     U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
2982     radius[2]=17.251318;
2983
2984     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2985
2986     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2987     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2988     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2989     ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2990     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2991     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2992
2993     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2994     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2995     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2996     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2997
2998     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2999     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
3000     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
3001     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
3002
3003     U1(center[0]).x=0.0;
3004     U2(center[0]).y=0.0;
3005     U3(center[0]).z=0.05;
3006
3007     radius[0]=0.04;
3008
3009     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
3010     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3011
3012     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3013
3014     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3015     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3016
3017     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
3018     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
3019     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
3020     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
3021
3022     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3023
3024     U1(center[0]).x=0.0;
3025     U2(center[0]).y=0.0;
3026     U3(center[0]).z=0.5;
3027
3028     radius[0]=0.5;
3029
3030     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3031
3032     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3033     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3034
3035     U1(center[0]).x=0.0;
3036     U2(center[0]).y=0.0;
3037     U3(center[0]).z=0.0;
3038
3039     radius[0]=0.0;
3040
3041     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3042
3043     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3044     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3045
3046     U1(center[0]).x=-1.0;
3047     U2(center[0]).y=-1.0;
3048     U3(center[0]).z=0.50;
3049
3050     radius[0]=0.25;
3051
3052     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3053
3054     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3055     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
3056
3057     U1(center[0]).x=-20.0;
3058     U2(center[0]).y=0.0;
3059     U3(center[0]).z=0.50;
3060
3061     radius[0]=3.0;
3062
3063     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3064
3065     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3066     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
3067
3068     U1(center[0]).x=20.0;
3069     U2(center[0]).y=0.0;
3070     U3(center[0]).z=0.50;
3071
3072     radius[0]=3.0f;
3073
3074     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3075
3076     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3077     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
3078
3079     U1(center[0]).x=0.0;
3080     U2(center[0]).y=-20.0;
3081     U3(center[0]).z=0.50;
3082
3083     radius[0]=3.0;
3084
3085     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3086
3087     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3088     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
3089
3090     U1(center[0]).x=0.0;
3091     U2(center[0]).y=20.0;
3092     U3(center[0]).z=0.5;
3093
3094     radius[0]=3.0;
3095
3096     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3097
3098     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3099     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
3100
3101     U1(center[0]).x=0.0;
3102     U2(center[0]).y=0.0;
3103     U3(center[0]).z=-20;
3104
3105     radius[0]=3.0;
3106
3107     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3108
3109     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3110     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
3111
3112     U1(center[0]).x=0.0;
3113     U2(center[0]).y=0.0;
3114     U3(center[0]).z=20.0;
3115
3116     radius[0]=3.0;
3117
3118     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3119
3120     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3121     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
3122 }
3123
3124 static void SetRenderTargetTest(void)
3125 {
3126     HRESULT hr;
3127     IDirectDrawSurface7 *newrt, *failrt, *oldrt;
3128     D3DVIEWPORT7 vp;
3129     DDSURFACEDESC2 ddsd, ddsd2;
3130     DWORD stateblock;
3131
3132     memset(&ddsd, 0, sizeof(ddsd));
3133     ddsd.dwSize = sizeof(ddsd);
3134     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3135     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
3136     ddsd.dwWidth = 64;
3137     ddsd.dwHeight = 64;
3138
3139     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
3140     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3141     if(FAILED(hr))
3142     {
3143         skip("Skipping SetRenderTarget test\n");
3144         return;
3145     }
3146
3147     memset(&ddsd2, 0, sizeof(ddsd2));
3148     ddsd2.dwSize = sizeof(ddsd2);
3149     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3150     ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER;
3151     ddsd2.dwWidth = 64;
3152     ddsd2.dwHeight = 64;
3153     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
3154     U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3155     U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3156     U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3157
3158     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd2, &failrt, NULL);
3159     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3160
3161     memset(&vp, 0, sizeof(vp));
3162     vp.dwX = 10;
3163     vp.dwY = 10;
3164     vp.dwWidth = 246;
3165     vp.dwHeight = 246;
3166     vp.dvMinZ = 0.25;
3167     vp.dvMaxZ = 0.75;
3168     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3169     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3170
3171     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3172     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3173
3174     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, failrt, 0);
3175     ok(hr != D3D_OK, "IDirect3DDevice7_SetRenderTarget succeeded\n");
3176
3177     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3178     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3179     memset(&vp, 0xff, sizeof(vp));
3180     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3181     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3182     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3183     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3184     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3185     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3186     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.25\n", vp.dvMinZ);
3187     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.75\n", vp.dvMaxZ);
3188
3189     memset(&vp, 0, sizeof(vp));
3190     vp.dwX = 0;
3191     vp.dwY = 0;
3192     vp.dwWidth = 64;
3193     vp.dwHeight = 64;
3194     vp.dvMinZ = 0.0;
3195     vp.dvMaxZ = 1.0;
3196     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3197     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3198
3199     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3200     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3201     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3202     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3203
3204     /* Check this twice, before and after ending the stateblock */
3205     memset(&vp, 0xff, sizeof(vp));
3206     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3207     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3208     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3209     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3210     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3211     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3212     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3213     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3214
3215     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3216     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3217
3218     memset(&vp, 0xff, sizeof(vp));
3219     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3220     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3221     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3222     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3223     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3224     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3225     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3226     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3227
3228     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3229     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3230
3231     memset(&vp, 0, sizeof(vp));
3232     vp.dwX = 0;
3233     vp.dwY = 0;
3234     vp.dwWidth = 256;
3235     vp.dwHeight = 256;
3236     vp.dvMinZ = 0.0;
3237     vp.dvMaxZ = 0.0;
3238     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3239     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3240
3241     IDirectDrawSurface7_Release(oldrt);
3242     IDirectDrawSurface7_Release(newrt);
3243     IDirectDrawSurface7_Release(failrt);
3244 }
3245
3246 static const UINT *expect_messages;
3247
3248 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3249 {
3250     if (expect_messages && message == *expect_messages) ++expect_messages;
3251
3252     return DefWindowProcA(hwnd, message, wparam, lparam);
3253 }
3254
3255 static void test_wndproc(void)
3256 {
3257     LONG_PTR proc, ddraw_proc;
3258     IDirectDraw7 *ddraw7;
3259     WNDCLASSA wc = {0};
3260     HWND window;
3261     HRESULT hr;
3262     ULONG ref;
3263
3264     static const UINT messages[] =
3265     {
3266         WM_WINDOWPOSCHANGING,
3267         WM_MOVE,
3268         WM_SIZE,
3269         WM_WINDOWPOSCHANGING,
3270         WM_ACTIVATE,
3271         WM_SETFOCUS,
3272         0,
3273     };
3274
3275     /* DDSCL_EXCLUSIVE replaces the window's window proc. */
3276     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3277     if (FAILED(hr))
3278     {
3279         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3280         return;
3281     }
3282
3283     wc.lpfnWndProc = test_proc;
3284     wc.lpszClassName = "d3d7_test_wndproc_wc";
3285     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3286
3287     window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test",
3288             WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3289
3290     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3291     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3292             (LONG_PTR)test_proc, proc);
3293
3294     expect_messages = messages;
3295
3296     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3297     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3298     if (FAILED(hr))
3299     {
3300         IDirectDraw7_Release(ddraw7);
3301         goto done;
3302     }
3303
3304     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3305     expect_messages = NULL;
3306
3307     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3308     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3309             (LONG_PTR)test_proc, proc);
3310
3311     ref = IDirectDraw7_Release(ddraw7);
3312     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3313
3314     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3315     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3316             (LONG_PTR)test_proc, proc);
3317
3318     /* DDSCL_NORMAL doesn't. */
3319     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3320     if (FAILED(hr))
3321     {
3322         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3323         return;
3324     }
3325
3326     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3327     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3328             (LONG_PTR)test_proc, proc);
3329
3330     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3331     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3332     if (FAILED(hr))
3333     {
3334         IDirectDraw7_Release(ddraw7);
3335         goto done;
3336     }
3337
3338     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3339     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3340             (LONG_PTR)test_proc, proc);
3341
3342     ref = IDirectDraw7_Release(ddraw7);
3343     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3344
3345     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3346     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3347             (LONG_PTR)test_proc, proc);
3348
3349     /* The original window proc is only restored by ddraw if the current
3350      * window proc matches the one ddraw set. This also affects switching
3351      * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
3352     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3353     if (FAILED(hr))
3354     {
3355         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3356         return;
3357     }
3358
3359     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3360     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3361             (LONG_PTR)test_proc, proc);
3362
3363     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3364     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3365     if (FAILED(hr))
3366     {
3367         IDirectDraw7_Release(ddraw7);
3368         goto done;
3369     }
3370
3371     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3372     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3373             (LONG_PTR)test_proc, proc);
3374     ddraw_proc = proc;
3375
3376     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3377     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3378     if (FAILED(hr))
3379     {
3380         IDirectDraw7_Release(ddraw7);
3381         goto done;
3382     }
3383
3384     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3385     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3386             (LONG_PTR)test_proc, proc);
3387
3388     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3389     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3390     if (FAILED(hr))
3391     {
3392         IDirectDraw7_Release(ddraw7);
3393         goto done;
3394     }
3395
3396     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3397     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3398             (LONG_PTR)test_proc, proc);
3399
3400     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3401     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3402     if (FAILED(hr))
3403     {
3404         IDirectDraw7_Release(ddraw7);
3405         goto done;
3406     }
3407
3408     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3409     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3410             (LONG_PTR)DefWindowProcA, proc);
3411
3412     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3413     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3414     if (FAILED(hr))
3415     {
3416         IDirectDraw7_Release(ddraw7);
3417         goto done;
3418     }
3419
3420     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
3421     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3422             (LONG_PTR)DefWindowProcA, proc);
3423
3424     ref = IDirectDraw7_Release(ddraw7);
3425     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3426
3427     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3428     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3429             (LONG_PTR)test_proc, proc);
3430
3431     hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3432     if (FAILED(hr))
3433     {
3434         skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3435         return;
3436     }
3437
3438     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3439     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3440             (LONG_PTR)test_proc, proc);
3441
3442     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3443     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3444     if (FAILED(hr))
3445     {
3446         IDirectDraw7_Release(ddraw7);
3447         goto done;
3448     }
3449
3450     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3451     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3452             (LONG_PTR)test_proc, proc);
3453
3454     ref = IDirectDraw7_Release(ddraw7);
3455     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3456
3457     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3458     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3459             (LONG_PTR)DefWindowProcA, proc);
3460
3461 done:
3462     expect_messages = NULL;
3463     DestroyWindow(window);
3464     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
3465 }
3466
3467 static void VertexBufferLockRest(void)
3468 {
3469     D3DVERTEXBUFFERDESC desc;
3470     IDirect3DVertexBuffer7 *buffer;
3471     HRESULT hr;
3472     unsigned int i;
3473     void *data;
3474     const struct
3475     {
3476         DWORD flags;
3477         const char *debug_string;
3478         HRESULT result;
3479     }
3480     test_data[] =
3481     {
3482         {0,                                         "(none)",                                       D3D_OK },
3483         {DDLOCK_WAIT,                               "DDLOCK_WAIT",                                  D3D_OK },
3484         {DDLOCK_EVENT,                              "DDLOCK_EVENT",                                 D3D_OK },
3485         {DDLOCK_READONLY,                           "DDLOCK_READONLY",                              D3D_OK },
3486         {DDLOCK_WRITEONLY,                          "DDLOCK_WRITEONLY",                             D3D_OK },
3487         {DDLOCK_NOSYSLOCK,                          "DDLOCK_NOSYSLOCK",                             D3D_OK },
3488         {DDLOCK_NOOVERWRITE,                        "DDLOCK_NOOVERWRITE",                           D3D_OK },
3489         {DDLOCK_DISCARDCONTENTS,                    "DDLOCK_DISCARDCONTENTS",                       D3D_OK },
3490
3491         {DDLOCK_READONLY | DDLOCK_WRITEONLY,        "DDLOCK_READONLY | DDLOCK_WRITEONLY",           D3D_OK },
3492         {DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS,  "DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS",     D3D_OK },
3493         {0xdeadbeef,                                "0xdeadbeef",                                   D3D_OK },
3494     };
3495
3496     memset(&desc, 0 , sizeof(desc));
3497     desc.dwSize = sizeof(desc);
3498     desc.dwCaps = 0;
3499     desc.dwFVF = D3DFVF_XYZ;
3500     desc.dwNumVertices = 64;
3501     hr = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &buffer, 0);
3502     ok(hr == D3D_OK, "IDirect3D7_CreateVertexBuffer failed, 0x%08x\n", hr);
3503
3504     for(i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
3505     {
3506         hr = IDirect3DVertexBuffer7_Lock(buffer, test_data[i].flags, &data, NULL);
3507         ok(hr == test_data[i].result, "Lock flags %s returned 0x%08x, expected 0x%08x\n",
3508             test_data[i].debug_string, hr, test_data[i].result);
3509         if(SUCCEEDED(hr))
3510         {
3511             ok(data != NULL, "The data pointer returned by Lock is NULL\n");
3512             hr = IDirect3DVertexBuffer7_Unlock(buffer);
3513             ok(hr == D3D_OK, "IDirect3DVertexBuffer7_Unlock failed, 0x%08x\n", hr);
3514         }
3515     }
3516
3517     IDirect3DVertexBuffer7_Release(buffer);
3518 }
3519
3520 static void FindDevice(void)
3521 {
3522     static const struct
3523     {
3524         const GUID *guid;
3525         int todo;
3526     } deviceGUIDs[] =
3527     {
3528         {&IID_IDirect3DRampDevice, 1},
3529         {&IID_IDirect3DRGBDevice},
3530     };
3531
3532     static const GUID *nonexistent_deviceGUIDs[] = {&IID_IDirect3DMMXDevice,
3533                                                     &IID_IDirect3DRefDevice,
3534                                                     &IID_IDirect3DTnLHalDevice,
3535                                                     &IID_IDirect3DNullDevice};
3536
3537     D3DFINDDEVICESEARCH search = {0};
3538     D3DFINDDEVICERESULT result = {0};
3539     IDirect3DDevice *d3dhal;
3540     HRESULT hr;
3541     int i;
3542
3543     /* Test invalid parameters. */
3544     hr = IDirect3D_FindDevice(Direct3D1, NULL, NULL);
3545     ok(hr == DDERR_INVALIDPARAMS,
3546        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3547
3548     hr = IDirect3D_FindDevice(Direct3D1, NULL, &result);
3549     ok(hr == DDERR_INVALIDPARAMS,
3550        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3551
3552     hr = IDirect3D_FindDevice(Direct3D1, &search, NULL);
3553     ok(hr == DDERR_INVALIDPARAMS,
3554        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3555
3556     search.dwSize = 0;
3557     result.dwSize = 0;
3558
3559     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3560     ok(hr == DDERR_INVALIDPARAMS,
3561        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3562
3563     search.dwSize = sizeof(search) + 1;
3564     result.dwSize = sizeof(result) + 1;
3565
3566     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3567     ok(hr == DDERR_INVALIDPARAMS,
3568        "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3569
3570     /* Specifying no flags is permitted. */
3571     search.dwSize = sizeof(search);
3572     search.dwFlags = 0;
3573     result.dwSize = sizeof(result);
3574
3575     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3576     ok(hr == D3D_OK,
3577        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3578
3579     /* Try an arbitrary non-device GUID. */
3580     search.dwSize = sizeof(search);
3581     search.dwFlags = D3DFDS_GUID;
3582     search.guid = IID_IDirect3D;
3583     result.dwSize = sizeof(result);
3584
3585     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3586     ok(hr == DDERR_NOTFOUND,
3587        "Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", hr);
3588
3589     /* These GUIDs appear to be never present. */
3590     for (i = 0; i < sizeof(nonexistent_deviceGUIDs)/sizeof(nonexistent_deviceGUIDs[0]); i++)
3591     {
3592         search.dwSize = sizeof(search);
3593         search.dwFlags = D3DFDS_GUID;
3594         search.guid = *nonexistent_deviceGUIDs[i];
3595         result.dwSize = sizeof(result);
3596
3597         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3598         ok(hr == DDERR_NOTFOUND,
3599            "[%d] Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", i, hr);
3600     }
3601
3602     /* The HAL device can only be enumerated if hardware acceleration is present. */
3603     search.dwSize = sizeof(search);
3604     search.dwFlags = D3DFDS_GUID;
3605     search.guid = IID_IDirect3DHALDevice;
3606     result.dwSize = sizeof(result);
3607
3608     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3609     trace("IDirect3D::FindDevice returned 0x%08x for the HAL device GUID\n", hr);
3610     if (SUCCEEDED(hr))
3611     {
3612         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3613         /* Currently Wine only supports the creation of one Direct3D device
3614          * for a given DirectDraw instance. */
3615         todo_wine
3616         ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
3617            "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3618
3619         if (SUCCEEDED(hr))
3620             IDirect3DDevice_Release(d3dhal);
3621     }
3622     else
3623     {
3624         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3625         ok(FAILED(hr), "Expected IDirectDrawSurface::QueryInterface to fail, got 0x%08x\n", hr);
3626
3627         if (SUCCEEDED(hr))
3628             IDirect3DDevice_Release(d3dhal);
3629     }
3630
3631     /* These GUIDs appear to be always present. */
3632     for (i = 0; i < sizeof(deviceGUIDs)/sizeof(deviceGUIDs[0]); i++)
3633     {
3634         search.dwSize = sizeof(search);
3635         search.dwFlags = D3DFDS_GUID;
3636         search.guid = *deviceGUIDs[i].guid;
3637         result.dwSize = sizeof(result);
3638
3639         hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3640
3641         if (deviceGUIDs[i].todo)
3642         {
3643             todo_wine
3644             ok(hr == D3D_OK,
3645                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3646         }
3647         else
3648         {
3649             ok(hr == D3D_OK,
3650                "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3651         }
3652     }
3653
3654     /* Curiously the color model criteria seem to be ignored. */
3655     search.dwSize = sizeof(search);
3656     search.dwFlags = D3DFDS_COLORMODEL;
3657     search.dcmColorModel = 0xdeadbeef;
3658     result.dwSize = sizeof(result);
3659
3660     hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3661     todo_wine
3662     ok(hr == D3D_OK,
3663        "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3664 }
3665
3666 static void BackBuffer3DCreateSurfaceTest(void)
3667 {
3668     DDSURFACEDESC ddsd;
3669     DDSURFACEDESC created_ddsd;
3670     DDSURFACEDESC2 ddsd2;
3671     IDirectDrawSurface *surf;
3672     IDirectDrawSurface4 *surf4;
3673     IDirectDrawSurface7 *surf7;
3674     HRESULT hr;
3675     IDirectDraw2 *dd2;
3676     IDirectDraw4 *dd4;
3677     IDirectDraw7 *dd7;
3678     DDCAPS ddcaps;
3679     IDirect3DDevice *d3dhal;
3680
3681     const DWORD caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3682     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3683
3684     memset(&ddcaps, 0, sizeof(ddcaps));
3685     ddcaps.dwSize = sizeof(DDCAPS);
3686     hr = IDirectDraw_GetCaps(DirectDraw1, &ddcaps, NULL);
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 }