setupapi: Implement SetupGetFileCompressionInfo on top of SetupGetFileCompressionInfoEx.
[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  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <assert.h>
23 #include "wine/test.h"
24 #include "ddraw.h"
25 #include "d3d.h"
26
27 static LPDIRECTDRAW7           lpDD = NULL;
28 static LPDIRECT3D7             lpD3D = NULL;
29 static LPDIRECTDRAWSURFACE7    lpDDS = NULL;
30 static LPDIRECT3DDEVICE7       lpD3DDevice = NULL;
31 static LPDIRECT3DVERTEXBUFFER7 lpVBufSrc = NULL;
32 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest1 = NULL;
33 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest2 = NULL;
34
35 /* To compare bad floating point numbers. Not the ideal way to do it,
36  * but it should be enough for here */
37 #define comparefloat(a, b) ( (((a) - (b)) < 0.0001) && (((a) - (b)) > -0.0001) )
38
39 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
40
41 typedef struct _VERTEX
42 {
43     float x, y, z;  /* position */
44 } VERTEX, *LPVERTEX;
45
46 typedef struct _TVERTEX
47 {
48     float x, y, z;  /* position */
49     float rhw;
50 } TVERTEX, *LPTVERTEX;
51
52
53 static void init_function_pointers(void)
54 {
55     HMODULE hmod = GetModuleHandleA("ddraw.dll");
56     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
57 }
58
59
60 static BOOL CreateDirect3D(void)
61 {
62     HRESULT rc;
63     DDSURFACEDESC2 ddsd;
64
65     rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
66         &IID_IDirectDraw7, NULL);
67     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
68     if (!lpDD) {
69         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
70         return FALSE;
71     }
72
73     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
74     ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
75
76     rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
77     if (rc == E_NOINTERFACE) return FALSE;
78     ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
79
80     memset(&ddsd, 0, sizeof(ddsd));
81     ddsd.dwSize = sizeof(ddsd);
82     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
83     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
84     ddsd.dwWidth = 256;
85     ddsd.dwHeight = 256;
86     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
87     ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
88
89     rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
90         &lpD3DDevice);
91     ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
92     if (!lpD3DDevice) {
93         trace("IDirect3D7::CreateDevice() failed with an error %x\n", rc);
94         return FALSE;
95     }
96
97     return TRUE;
98 }
99
100 static void ReleaseDirect3D(void)
101 {
102     if (lpD3DDevice != NULL)
103     {
104         IDirect3DDevice7_Release(lpD3DDevice);
105         lpD3DDevice = NULL;
106     }
107
108     if (lpDDS != NULL)
109     {
110         IDirectDrawSurface_Release(lpDDS);
111         lpDDS = NULL;
112     }
113
114     if (lpD3D != NULL)
115     {
116         IDirect3D7_Release(lpD3D);
117         lpD3D = NULL;
118     }
119
120     if (lpDD != NULL)
121     {
122         IDirectDraw_Release(lpDD);
123         lpDD = NULL;
124     }
125 }
126
127 static void LightTest(void)
128 {
129     HRESULT rc;
130     D3DLIGHT7 light;
131     D3DLIGHT7 defaultlight;
132     BOOL bEnabled = FALSE;
133
134     /* Set a few lights with funky indices. */
135     memset(&light, 0, sizeof(light));
136     light.dltType = D3DLIGHT_DIRECTIONAL;
137     U1(light.dcvDiffuse).r = 0.5f;
138     U2(light.dcvDiffuse).g = 0.6f;
139     U3(light.dcvDiffuse).b = 0.7f;
140     U2(light.dvDirection).y = 1.f;
141
142     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
143     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
144     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
145     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
146     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
147     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
148
149
150     /* Try to retrieve a light beyond the indices of the lights that have
151        been set. */
152     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
153     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
154     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
155     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
156
157
158     /* Try to retrieve one of the lights that have been set */
159     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
160     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
161
162
163     /* Enable a light that have been previously set. */
164     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
165     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
166
167
168     /* Enable some lights that have not been previously set, and verify that
169        they have been initialized with proper default values. */
170     memset(&defaultlight, 0, sizeof(D3DLIGHT7));
171     defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
172     U1(defaultlight.dcvDiffuse).r = 1.f;
173     U2(defaultlight.dcvDiffuse).g = 1.f;
174     U3(defaultlight.dcvDiffuse).b = 1.f;
175     U3(defaultlight.dvDirection).z = 1.f;
176
177     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
178     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
179     memset(&light, 0, sizeof(D3DLIGHT7));
180     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
181     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
182     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
183         "light data doesn't match expected default values\n" );
184
185     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
186     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
187     memset(&light, 0, sizeof(D3DLIGHT7));
188     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
189     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
190     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
191         "light data doesn't match expected default values\n" );
192
193
194     /* Disable one of the light that have been previously enabled. */
195     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
196     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
197
198     /* Try to retrieve the enable status of some lights */
199     /* Light 20 is supposed to be disabled */
200     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
201     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
202     ok(!bEnabled, "GetLightEnable says the light is enabled\n");
203
204     /* Light 10 is supposed to be enabled */
205     bEnabled = FALSE;
206     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
207     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
208     ok(bEnabled, "GetLightEnable says the light is disabled\n");
209
210     /* Light 80 has not been set */
211     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
212     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
213
214     /* Light 23 has not been set */
215     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
216     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
217
218     /* Set some lights with invalid parameters */
219     memset(&light, 0, sizeof(D3DLIGHT7));
220     light.dltType = 0;
221     U1(light.dcvDiffuse).r = 1.f;
222     U2(light.dcvDiffuse).g = 1.f;
223     U3(light.dcvDiffuse).b = 1.f;
224     U3(light.dvDirection).z = 1.f;
225     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
226     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
227
228     memset(&light, 0, sizeof(D3DLIGHT7));
229     light.dltType = 12345;
230     U1(light.dcvDiffuse).r = 1.f;
231     U2(light.dcvDiffuse).g = 1.f;
232     U3(light.dcvDiffuse).b = 1.f;
233     U3(light.dvDirection).z = 1.f;
234     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
235     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
236
237     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
238     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
239
240     memset(&light, 0, sizeof(D3DLIGHT7));
241     light.dltType = D3DLIGHT_SPOT;
242     U1(light.dcvDiffuse).r = 1.f;
243     U2(light.dcvDiffuse).g = 1.f;
244     U3(light.dcvDiffuse).b = 1.f;
245     U3(light.dvDirection).z = 1.f;
246
247     light.dvAttenuation0 = -1.0 / 0.0; /* -INFINITY */
248     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
249     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
250
251     light.dvAttenuation0 = -1.0;
252     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
253     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
254
255     light.dvAttenuation0 = 0.0;
256     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
257     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
258
259     light.dvAttenuation0 = 1.0;
260     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
261     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
262
263     light.dvAttenuation0 = 1.0 / 0.0; /* +INFINITY */
264     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
265     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
266
267     light.dvAttenuation0 = 0.0 / 0.0; /* NaN */
268     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
269     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
270
271     /* Directional light ignores attenuation */
272     light.dltType = D3DLIGHT_DIRECTIONAL;
273     light.dvAttenuation0 = -1.0;
274     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
275     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
276 }
277
278 static void ProcessVerticesTest(void)
279 {
280     D3DVERTEXBUFFERDESC desc;
281     HRESULT rc;
282     VERTEX *in;
283     TVERTEX *out;
284     VERTEX *out2;
285     D3DVIEWPORT7 vp;
286     D3DMATRIX view = {  2.0, 0.0, 0.0, 0.0,
287                         0.0, -1.0, 0.0, 0.0,
288                         0.0, 0.0, 1.0, 0.0,
289                         0.0, 0.0, 0.0, 3.0 };
290
291     D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
292                         1.0, 0.0, 0.0, 0.0,
293                         0.0, 0.0, 0.0, 1.0,
294                         0.0, 1.0, 1.0, 1.0 };
295
296     D3DMATRIX proj = {  1.0, 0.0, 0.0, 1.0,
297                         0.0, 1.0, 1.0, 0.0,
298                         0.0, 1.0, 1.0, 0.0,
299                         1.0, 0.0, 0.0, 1.0 };
300     /* Create some vertex buffers */
301
302     memset(&desc, 0, sizeof(desc));
303     desc.dwSize = sizeof(desc);
304     desc.dwCaps = 0;
305     desc.dwFVF = D3DFVF_XYZ;
306     desc.dwNumVertices = 16;
307     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
308     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
309     if (!lpVBufSrc)
310     {
311         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
312         goto out;
313     }
314
315     memset(&desc, 0, sizeof(desc));
316     desc.dwSize = sizeof(desc);
317     desc.dwCaps = 0;
318     desc.dwFVF = D3DFVF_XYZRHW;
319     desc.dwNumVertices = 16;
320     /* Msdn says that the last parameter must be 0 - check that */
321     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
322     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
323     if (!lpVBufDest1)
324     {
325         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
326         goto out;
327     }
328
329     memset(&desc, 0, sizeof(desc));
330     desc.dwSize = sizeof(desc);
331     desc.dwCaps = 0;
332     desc.dwFVF = D3DFVF_XYZ;
333     desc.dwNumVertices = 16;
334     /* Msdn says that the last parameter must be 0 - check that */
335     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
336     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
337     if (!lpVBufDest2)
338     {
339         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
340         goto out;
341     }
342
343     rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
344     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
345     if(!in) goto out;
346
347     /* Check basic transformation */
348
349     in[0].x = 0.0;
350     in[0].y = 0.0;
351     in[0].z = 0.0;
352
353     in[1].x = 1.0;
354     in[1].y = 1.0;
355     in[1].z = 1.0;
356
357     in[2].x = -1.0;
358     in[2].y = -1.0;
359     in[2].z = 0.5;
360
361     in[3].x = 0.5;
362     in[3].y = -0.5;
363     in[3].z = 0.25;
364     rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
365     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
366
367     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
368     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
369
370     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
371     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
372
373     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
374     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
375     if(!out) goto out;
376
377     /* Check the results */
378     ok( comparefloat(out[0].x, 128.0 ) &&
379         comparefloat(out[0].y, 128.0 ) &&
380         comparefloat(out[0].z, 0.0 ) &&
381         comparefloat(out[0].rhw, 1.0 ),
382         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
383
384     ok( comparefloat(out[1].x, 256.0 ) &&
385         comparefloat(out[1].y, 0.0 ) &&
386         comparefloat(out[1].z, 1.0 ) &&
387         comparefloat(out[1].rhw, 1.0 ),
388         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
389
390     ok( comparefloat(out[2].x, 0.0 ) &&
391         comparefloat(out[2].y, 256.0 ) &&
392         comparefloat(out[2].z, 0.5 ) &&
393         comparefloat(out[2].rhw, 1.0 ),
394         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
395
396     ok( comparefloat(out[3].x, 192.0 ) &&
397         comparefloat(out[3].y, 192.0 ) &&
398         comparefloat(out[3].z, 0.25 ) &&
399         comparefloat(out[3].rhw, 1.0 ),
400         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
401
402     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
403     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
404     out = NULL;
405
406     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
407     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
408     if(!out2) goto out;
409     /* Small thing without much practial meaning, but I stumbled upon it,
410      * so let's check for it: If the output vertex buffer has to RHW value,
411      * The RHW value of the last vertex is written into the next vertex
412      */
413     ok( comparefloat(out2[4].x, 1.0 ) &&
414         comparefloat(out2[4].y, 0.0 ) &&
415         comparefloat(out2[4].z, 0.0 ),
416         "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
417
418     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
419     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
420     out = NULL;
421
422     /* Try a more complicated viewport, same vertices */
423     memset(&vp, 0, sizeof(vp));
424     vp.dwX = 10;
425     vp.dwY = 5;
426     vp.dwWidth = 246;
427     vp.dwHeight = 130;
428     vp.dvMinZ = -2.0;
429     vp.dvMaxZ = 4.0;
430     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
431     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
432
433     /* Process again */
434     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
435     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
436
437     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
438     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
439     if(!out) goto out;
440
441     /* Check the results */
442     ok( comparefloat(out[0].x, 133.0 ) &&
443         comparefloat(out[0].y, 70.0 ) &&
444         comparefloat(out[0].z, -2.0 ) &&
445         comparefloat(out[0].rhw, 1.0 ),
446         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
447
448     ok( comparefloat(out[1].x, 256.0 ) &&
449         comparefloat(out[1].y, 5.0 ) &&
450         comparefloat(out[1].z, 4.0 ) &&
451         comparefloat(out[1].rhw, 1.0 ),
452         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
453
454     ok( comparefloat(out[2].x, 10.0 ) &&
455         comparefloat(out[2].y, 135.0 ) &&
456         comparefloat(out[2].z, 1.0 ) &&
457         comparefloat(out[2].rhw, 1.0 ),
458         "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
459
460     ok( comparefloat(out[3].x, 194.5 ) &&
461         comparefloat(out[3].y, 102.5 ) &&
462         comparefloat(out[3].z, -0.5 ) &&
463         comparefloat(out[3].rhw, 1.0 ),
464         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
465
466     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
467     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
468     out = NULL;
469
470     /* Play with some matrices. */
471
472     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
473     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
474
475     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
476     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
477
478     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
479     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
480
481     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
482     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
483
484     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
485     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
486     if(!out) goto out;
487
488     /* Keep the viewport simpler, otherwise we get bad numbers to compare */
489     vp.dwX = 0;
490     vp.dwY = 0;
491     vp.dwWidth = 100;
492     vp.dwHeight = 100;
493     vp.dvMinZ = 1.0;
494     vp.dvMaxZ = 0.0;
495     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
496     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
497
498     /* Check the results */
499     ok( comparefloat(out[0].x, 256.0 ) &&    /* X coordinate is cut at the surface edges */
500         comparefloat(out[0].y, 70.0 ) &&
501         comparefloat(out[0].z, -2.0 ) &&
502         comparefloat(out[0].rhw, (1.0 / 3.0)),
503         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
504
505     ok( comparefloat(out[1].x, 256.0 ) &&
506         comparefloat(out[1].y, 78.125000 ) &&
507         comparefloat(out[1].z, -2.750000 ) &&
508         comparefloat(out[1].rhw, 0.125000 ),
509         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
510
511     ok( comparefloat(out[2].x, 256.0 ) &&
512         comparefloat(out[2].y, 44.000000 ) &&
513         comparefloat(out[2].z, 0.400000 ) &&
514         comparefloat(out[2].rhw, 0.400000 ),
515         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
516
517     ok( comparefloat(out[3].x, 256.0 ) &&
518         comparefloat(out[3].y, 81.818184 ) &&
519         comparefloat(out[3].z, -3.090909 ) &&
520         comparefloat(out[3].rhw, 0.363636 ),
521         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
522
523     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
524     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
525     out = NULL;
526
527 out:
528     IDirect3DVertexBuffer7_Release(lpVBufSrc);
529     IDirect3DVertexBuffer7_Release(lpVBufDest1);
530     IDirect3DVertexBuffer7_Release(lpVBufDest2);
531 }
532
533 static void StateTest( void )
534 {
535     HRESULT rc;
536
537     /* The msdn says its undocumented, does it return an error too? */
538     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
539     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
540     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
541     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
542 }
543
544
545 static void SceneTest(void)
546 {
547     HRESULT                      hr;
548
549     /* Test an EndScene without beginscene. Should return an error */
550     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
551     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
552
553     /* Test a normal BeginScene / EndScene pair, this should work */
554     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
555     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
556     if(SUCCEEDED(hr))
557     {
558         hr = IDirect3DDevice7_EndScene(lpD3DDevice);
559         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
560     }
561
562     /* Test another EndScene without having begun a new scene. Should return an error */
563     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
564     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
565
566     /* Two nested BeginScene and EndScene calls */
567     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
568     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
569     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
570     ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
571     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
572     ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
573     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
574     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
575
576     /* TODO: Verify that blitting works in the same way as in d3d9 */
577 }
578
579 static void LimitTest(void)
580 {
581     IDirectDrawSurface7 *pTexture = NULL;
582     HRESULT hr;
583     int i;
584     DDSURFACEDESC2 ddsd;
585
586     memset(&ddsd, 0, sizeof(ddsd));
587     ddsd.dwSize = sizeof(ddsd);
588     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
589     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
590     ddsd.dwWidth = 16;
591     ddsd.dwHeight = 16;
592     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
593     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
594     if(!pTexture) return;
595
596     for(i = 0; i < 8; i++) {
597         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
598         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
599         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
600         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
601         hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
602         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
603     }
604
605     IDirectDrawSurface7_Release(pTexture);
606 }
607
608 START_TEST(d3d)
609 {
610     init_function_pointers();
611     if(!pDirectDrawCreateEx) {
612         trace("function DirectDrawCreateEx not available, skipping tests\n");
613         return;
614     }
615
616     if(!CreateDirect3D()) {
617         trace("Skipping tests\n");
618         return;
619     }
620     LightTest();
621     ProcessVerticesTest();
622     StateTest();
623     SceneTest();
624     LimitTest();
625     ReleaseDirect3D();
626 }