ddraw/tests: Check for failing to create surfaces.
[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     if (!SUCCEEDED(rc))
89         return FALSE;
90
91     rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
92         &lpD3DDevice);
93     ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
94     if (!lpD3DDevice) {
95         trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
96         rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
97             &lpD3DDevice);
98         if (!lpD3DDevice) {
99             trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
100             rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
101                 &lpD3DDevice);
102             if (!lpD3DDevice) {
103                 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
104                 return FALSE;
105             }
106         }
107     }
108
109     return TRUE;
110 }
111
112 static void ReleaseDirect3D(void)
113 {
114     if (lpD3DDevice != NULL)
115     {
116         IDirect3DDevice7_Release(lpD3DDevice);
117         lpD3DDevice = NULL;
118     }
119
120     if (lpDDS != NULL)
121     {
122         IDirectDrawSurface_Release(lpDDS);
123         lpDDS = NULL;
124     }
125
126     if (lpD3D != NULL)
127     {
128         IDirect3D7_Release(lpD3D);
129         lpD3D = NULL;
130     }
131
132     if (lpDD != NULL)
133     {
134         IDirectDraw_Release(lpDD);
135         lpDD = NULL;
136     }
137 }
138
139 static void LightTest(void)
140 {
141     HRESULT rc;
142     D3DLIGHT7 light;
143     D3DLIGHT7 defaultlight;
144     BOOL bEnabled = FALSE;
145
146     /* Set a few lights with funky indices. */
147     memset(&light, 0, sizeof(light));
148     light.dltType = D3DLIGHT_DIRECTIONAL;
149     U1(light.dcvDiffuse).r = 0.5f;
150     U2(light.dcvDiffuse).g = 0.6f;
151     U3(light.dcvDiffuse).b = 0.7f;
152     U2(light.dvDirection).y = 1.f;
153
154     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
155     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
156     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
157     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
158     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
159     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
160
161
162     /* Try to retrieve a light beyond the indices of the lights that have
163        been set. */
164     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
165     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
166     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
167     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
168
169
170     /* Try to retrieve one of the lights that have been set */
171     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
172     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
173
174
175     /* Enable a light that have been previously set. */
176     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
177     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
178
179
180     /* Enable some lights that have not been previously set, and verify that
181        they have been initialized with proper default values. */
182     memset(&defaultlight, 0, sizeof(D3DLIGHT7));
183     defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
184     U1(defaultlight.dcvDiffuse).r = 1.f;
185     U2(defaultlight.dcvDiffuse).g = 1.f;
186     U3(defaultlight.dcvDiffuse).b = 1.f;
187     U3(defaultlight.dvDirection).z = 1.f;
188
189     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
190     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
191     memset(&light, 0, sizeof(D3DLIGHT7));
192     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
193     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
194     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
195         "light data doesn't match expected default values\n" );
196
197     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
198     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
199     memset(&light, 0, sizeof(D3DLIGHT7));
200     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
201     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
202     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
203         "light data doesn't match expected default values\n" );
204
205
206     /* Disable one of the light that have been previously enabled. */
207     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
208     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
209
210     /* Try to retrieve the enable status of some lights */
211     /* Light 20 is supposed to be disabled */
212     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
213     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
214     ok(!bEnabled, "GetLightEnable says the light is enabled\n");
215
216     /* Light 10 is supposed to be enabled */
217     bEnabled = FALSE;
218     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
219     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
220     ok(bEnabled, "GetLightEnable says the light is disabled\n");
221
222     /* Light 80 has not been set */
223     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
224     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
225
226     /* Light 23 has not been set */
227     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
228     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
229
230     /* Set some lights with invalid parameters */
231     memset(&light, 0, sizeof(D3DLIGHT7));
232     light.dltType = 0;
233     U1(light.dcvDiffuse).r = 1.f;
234     U2(light.dcvDiffuse).g = 1.f;
235     U3(light.dcvDiffuse).b = 1.f;
236     U3(light.dvDirection).z = 1.f;
237     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
238     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
239
240     memset(&light, 0, sizeof(D3DLIGHT7));
241     light.dltType = 12345;
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     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
247     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
248
249     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
250     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
251
252     memset(&light, 0, sizeof(D3DLIGHT7));
253     light.dltType = D3DLIGHT_SPOT;
254     U1(light.dcvDiffuse).r = 1.f;
255     U2(light.dcvDiffuse).g = 1.f;
256     U3(light.dcvDiffuse).b = 1.f;
257     U3(light.dvDirection).z = 1.f;
258
259     light.dvAttenuation0 = -1.0 / 0.0; /* -INFINITY */
260     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
261     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
262
263     light.dvAttenuation0 = -1.0;
264     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
265     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
266
267     light.dvAttenuation0 = 0.0;
268     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
269     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
270
271     light.dvAttenuation0 = 1.0;
272     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
273     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
274
275     light.dvAttenuation0 = 1.0 / 0.0; /* +INFINITY */
276     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
277     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
278
279     light.dvAttenuation0 = 0.0 / 0.0; /* NaN */
280     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
281     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
282
283     /* Directional light ignores attenuation */
284     light.dltType = D3DLIGHT_DIRECTIONAL;
285     light.dvAttenuation0 = -1.0;
286     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
287     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
288 }
289
290 static void ProcessVerticesTest(void)
291 {
292     D3DVERTEXBUFFERDESC desc;
293     HRESULT rc;
294     VERTEX *in;
295     TVERTEX *out;
296     VERTEX *out2;
297     D3DVIEWPORT7 vp;
298     D3DMATRIX view = {  2.0, 0.0, 0.0, 0.0,
299                         0.0, -1.0, 0.0, 0.0,
300                         0.0, 0.0, 1.0, 0.0,
301                         0.0, 0.0, 0.0, 3.0 };
302
303     D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
304                         1.0, 0.0, 0.0, 0.0,
305                         0.0, 0.0, 0.0, 1.0,
306                         0.0, 1.0, 1.0, 1.0 };
307
308     D3DMATRIX proj = {  1.0, 0.0, 0.0, 1.0,
309                         0.0, 1.0, 1.0, 0.0,
310                         0.0, 1.0, 1.0, 0.0,
311                         1.0, 0.0, 0.0, 1.0 };
312     /* Create some vertex buffers */
313
314     memset(&desc, 0, sizeof(desc));
315     desc.dwSize = sizeof(desc);
316     desc.dwCaps = 0;
317     desc.dwFVF = D3DFVF_XYZ;
318     desc.dwNumVertices = 16;
319     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
320     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
321     if (!lpVBufSrc)
322     {
323         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
324         goto out;
325     }
326
327     memset(&desc, 0, sizeof(desc));
328     desc.dwSize = sizeof(desc);
329     desc.dwCaps = 0;
330     desc.dwFVF = D3DFVF_XYZRHW;
331     desc.dwNumVertices = 16;
332     /* Msdn says that the last parameter must be 0 - check that */
333     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
334     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
335     if (!lpVBufDest1)
336     {
337         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
338         goto out;
339     }
340
341     memset(&desc, 0, sizeof(desc));
342     desc.dwSize = sizeof(desc);
343     desc.dwCaps = 0;
344     desc.dwFVF = D3DFVF_XYZ;
345     desc.dwNumVertices = 16;
346     /* Msdn says that the last parameter must be 0 - check that */
347     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
348     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
349     if (!lpVBufDest2)
350     {
351         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
352         goto out;
353     }
354
355     rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
356     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
357     if(!in) goto out;
358
359     /* Check basic transformation */
360
361     in[0].x = 0.0;
362     in[0].y = 0.0;
363     in[0].z = 0.0;
364
365     in[1].x = 1.0;
366     in[1].y = 1.0;
367     in[1].z = 1.0;
368
369     in[2].x = -1.0;
370     in[2].y = -1.0;
371     in[2].z = 0.5;
372
373     in[3].x = 0.5;
374     in[3].y = -0.5;
375     in[3].z = 0.25;
376     rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
377     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
378
379     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
380     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
381
382     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
383     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
384
385     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
386     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
387     if(!out) goto out;
388
389     /* Check the results */
390     ok( comparefloat(out[0].x, 128.0 ) &&
391         comparefloat(out[0].y, 128.0 ) &&
392         comparefloat(out[0].z, 0.0 ) &&
393         comparefloat(out[0].rhw, 1.0 ),
394         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
395
396     ok( comparefloat(out[1].x, 256.0 ) &&
397         comparefloat(out[1].y, 0.0 ) &&
398         comparefloat(out[1].z, 1.0 ) &&
399         comparefloat(out[1].rhw, 1.0 ),
400         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
401
402     ok( comparefloat(out[2].x, 0.0 ) &&
403         comparefloat(out[2].y, 256.0 ) &&
404         comparefloat(out[2].z, 0.5 ) &&
405         comparefloat(out[2].rhw, 1.0 ),
406         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
407
408     ok( comparefloat(out[3].x, 192.0 ) &&
409         comparefloat(out[3].y, 192.0 ) &&
410         comparefloat(out[3].z, 0.25 ) &&
411         comparefloat(out[3].rhw, 1.0 ),
412         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
413
414     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
415     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
416     out = NULL;
417
418     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
419     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
420     if(!out2) goto out;
421     /* Small thing without much practial meaning, but I stumbled upon it,
422      * so let's check for it: If the output vertex buffer has to RHW value,
423      * The RHW value of the last vertex is written into the next vertex
424      */
425     ok( comparefloat(out2[4].x, 1.0 ) &&
426         comparefloat(out2[4].y, 0.0 ) &&
427         comparefloat(out2[4].z, 0.0 ),
428         "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
429
430     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
431     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
432     out = NULL;
433
434     /* Try a more complicated viewport, same vertices */
435     memset(&vp, 0, sizeof(vp));
436     vp.dwX = 10;
437     vp.dwY = 5;
438     vp.dwWidth = 246;
439     vp.dwHeight = 130;
440     vp.dvMinZ = -2.0;
441     vp.dvMaxZ = 4.0;
442     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
443     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
444
445     /* Process again */
446     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
447     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
448
449     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
450     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
451     if(!out) goto out;
452
453     /* Check the results */
454     ok( comparefloat(out[0].x, 133.0 ) &&
455         comparefloat(out[0].y, 70.0 ) &&
456         comparefloat(out[0].z, -2.0 ) &&
457         comparefloat(out[0].rhw, 1.0 ),
458         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
459
460     ok( comparefloat(out[1].x, 256.0 ) &&
461         comparefloat(out[1].y, 5.0 ) &&
462         comparefloat(out[1].z, 4.0 ) &&
463         comparefloat(out[1].rhw, 1.0 ),
464         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
465
466     ok( comparefloat(out[2].x, 10.0 ) &&
467         comparefloat(out[2].y, 135.0 ) &&
468         comparefloat(out[2].z, 1.0 ) &&
469         comparefloat(out[2].rhw, 1.0 ),
470         "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
471
472     ok( comparefloat(out[3].x, 194.5 ) &&
473         comparefloat(out[3].y, 102.5 ) &&
474         comparefloat(out[3].z, -0.5 ) &&
475         comparefloat(out[3].rhw, 1.0 ),
476         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
477
478     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
479     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
480     out = NULL;
481
482     /* Play with some matrices. */
483
484     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
485     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
486
487     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
488     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
489
490     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
491     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
492
493     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
494     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
495
496     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
497     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
498     if(!out) goto out;
499
500     /* Keep the viewport simpler, otherwise we get bad numbers to compare */
501     vp.dwX = 0;
502     vp.dwY = 0;
503     vp.dwWidth = 100;
504     vp.dwHeight = 100;
505     vp.dvMinZ = 1.0;
506     vp.dvMaxZ = 0.0;
507     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
508     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
509
510     /* Check the results */
511     ok( comparefloat(out[0].x, 256.0 ) &&    /* X coordinate is cut at the surface edges */
512         comparefloat(out[0].y, 70.0 ) &&
513         comparefloat(out[0].z, -2.0 ) &&
514         comparefloat(out[0].rhw, (1.0 / 3.0)),
515         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
516
517     ok( comparefloat(out[1].x, 256.0 ) &&
518         comparefloat(out[1].y, 78.125000 ) &&
519         comparefloat(out[1].z, -2.750000 ) &&
520         comparefloat(out[1].rhw, 0.125000 ),
521         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
522
523     ok( comparefloat(out[2].x, 256.0 ) &&
524         comparefloat(out[2].y, 44.000000 ) &&
525         comparefloat(out[2].z, 0.400000 ) &&
526         comparefloat(out[2].rhw, 0.400000 ),
527         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
528
529     ok( comparefloat(out[3].x, 256.0 ) &&
530         comparefloat(out[3].y, 81.818184 ) &&
531         comparefloat(out[3].z, -3.090909 ) &&
532         comparefloat(out[3].rhw, 0.363636 ),
533         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
534
535     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
536     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
537     out = NULL;
538
539 out:
540     IDirect3DVertexBuffer7_Release(lpVBufSrc);
541     IDirect3DVertexBuffer7_Release(lpVBufDest1);
542     IDirect3DVertexBuffer7_Release(lpVBufDest2);
543 }
544
545 static void StateTest( void )
546 {
547     HRESULT rc;
548
549     /* The msdn says its undocumented, does it return an error too? */
550     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
551     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
552     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
553     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
554 }
555
556
557 static void SceneTest(void)
558 {
559     HRESULT                      hr;
560
561     /* Test an EndScene without beginscene. Should return an error */
562     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
563     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
564
565     /* Test a normal BeginScene / EndScene pair, this should work */
566     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
567     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
568     if(SUCCEEDED(hr))
569     {
570         hr = IDirect3DDevice7_EndScene(lpD3DDevice);
571         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
572     }
573
574     /* Test another EndScene without having begun a new scene. Should return an error */
575     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
576     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
577
578     /* Two nested BeginScene and EndScene calls */
579     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
580     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
581     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
582     ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
583     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
584     ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
585     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
586     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
587
588     /* TODO: Verify that blitting works in the same way as in d3d9 */
589 }
590
591 static void LimitTest(void)
592 {
593     IDirectDrawSurface7 *pTexture = NULL;
594     HRESULT hr;
595     int i;
596     DDSURFACEDESC2 ddsd;
597
598     memset(&ddsd, 0, sizeof(ddsd));
599     ddsd.dwSize = sizeof(ddsd);
600     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
601     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
602     ddsd.dwWidth = 16;
603     ddsd.dwHeight = 16;
604     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
605     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
606     if(!pTexture) return;
607
608     for(i = 0; i < 8; i++) {
609         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
610         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
611         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
612         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
613         hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
614         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
615     }
616
617     IDirectDrawSurface7_Release(pTexture);
618 }
619
620 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
621 {
622     UINT ver = *((UINT *) ctx);
623     if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
624     {
625         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
626            "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
627         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
628            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
629         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
630            "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
631         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
632            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
633
634         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
635            "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
636         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
637            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
638         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
639            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
640         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
641            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
642     }
643     else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
644     {
645         /* pow2 is hardware dependent */
646
647         ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
648            "HAL Device %d hal line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
649         ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
650            "HAL Device %d hal tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
651         ok((hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
652            "HAL Device %d hel line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
653         ok((hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
654            "HAL Device %d hel tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
655     }
656     else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
657     {
658         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
659            "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
660         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
661            "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
662         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
663            "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
664         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
665            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
666
667         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
668            "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
669         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
670            "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
671         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
672            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
673         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
674            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
675     }
676     else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
677     {
678         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
679            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
680         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
681            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
682         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
683            "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
684         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
685            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
686
687         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
688            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
689         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
690            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
691         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
692            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
693         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
694            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
695     }
696     else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
697     {
698         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
699            "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
700         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
701            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
702         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
703            "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
704         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
705            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
706
707         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
708            "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
709         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
710            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
711         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
712            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
713         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
714            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
715     }
716     else
717     {
718         ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
719         if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
720         else trace("hal line does NOT have pow2 set\n");
721         if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
722         else trace("hal tri does NOT have pow2 set\n");
723         if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
724         else trace("hel line does NOT have pow2 set\n");
725         if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
726         else trace("hel tri does NOT have pow2 set\n");
727     }
728     return DDENUMRET_OK;
729 }
730
731 static void CapsTest(void)
732 {
733     IDirect3D3 *d3d3;
734     IDirect3D3 *d3d2;
735     IDirectDraw *dd1;
736     HRESULT hr;
737     UINT ver;
738
739     hr = DirectDrawCreate(NULL, &dd1, NULL);
740     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
741     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
742     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
743     ver = 3;
744     IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
745
746     IDirect3D3_Release(d3d3);
747     IDirectDraw_Release(dd1);
748
749     hr = DirectDrawCreate(NULL, &dd1, NULL);
750     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
751     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
752     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
753     ver = 2;
754     IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
755
756     IDirect3D2_Release(d3d2);
757     IDirectDraw_Release(dd1);
758 }
759
760 START_TEST(d3d)
761 {
762     init_function_pointers();
763     if(!pDirectDrawCreateEx) {
764         trace("function DirectDrawCreateEx not available, skipping tests\n");
765         return;
766     }
767
768     if(!CreateDirect3D()) {
769         trace("Skipping tests\n");
770         return;
771     }
772     LightTest();
773     ProcessVerticesTest();
774     StateTest();
775     SceneTest();
776     LimitTest();
777     CapsTest();
778     ReleaseDirect3D();
779 }