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