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