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