wintrust: Add a helper function to initialize chain creation parameters.
[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 LPDIRECTDRAWSURFACE7    lpDDSdepth = NULL;
31 static LPDIRECT3DDEVICE7       lpD3DDevice = NULL;
32 static LPDIRECT3DVERTEXBUFFER7 lpVBufSrc = NULL;
33 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest1 = NULL;
34 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest2 = NULL;
35
36 typedef struct {
37     int total;
38     int rgb;
39     int hal;
40     int tnlhal;
41     int unk;
42 } D3D7ETest;
43
44 /* To compare bad floating point numbers. Not the ideal way to do it,
45  * but it should be enough for here */
46 #define comparefloat(a, b) ( (((a) - (b)) < 0.0001) && (((a) - (b)) > -0.0001) )
47
48 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
49
50 typedef struct _VERTEX
51 {
52     float x, y, z;  /* position */
53 } VERTEX, *LPVERTEX;
54
55 typedef struct _TVERTEX
56 {
57     float x, y, z;  /* position */
58     float rhw;
59 } TVERTEX, *LPTVERTEX;
60
61
62 static void init_function_pointers(void)
63 {
64     HMODULE hmod = GetModuleHandleA("ddraw.dll");
65     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
66 }
67
68
69 static BOOL CreateDirect3D(void)
70 {
71     HRESULT rc;
72     DDSURFACEDESC2 ddsd;
73
74     rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
75         &IID_IDirectDraw7, NULL);
76     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
77     if (!lpDD) {
78         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
79         return FALSE;
80     }
81
82     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
83     ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
84
85     rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
86     if (rc == E_NOINTERFACE) return FALSE;
87     ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
88
89     memset(&ddsd, 0, sizeof(ddsd));
90     ddsd.dwSize = sizeof(ddsd);
91     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
92     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
93     ddsd.dwWidth = 256;
94     ddsd.dwHeight = 256;
95     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
96     ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
97     if (!SUCCEEDED(rc))
98         return FALSE;
99
100     memset(&ddsd, 0, sizeof(ddsd));
101     ddsd.dwSize = sizeof(ddsd);
102     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
103     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
104     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
105     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
106     U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 16;
107     U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
108     ddsd.dwWidth = 256;
109     ddsd.dwHeight = 256;
110     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDSdepth, NULL);
111     ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
112     if (!SUCCEEDED(rc)) {
113         lpDDSdepth = NULL;
114     } else {
115         rc = IDirectDrawSurface_AddAttachedSurface(lpDDS, lpDDSdepth);
116         ok(rc == DD_OK, "IDirectDrawSurface_AddAttachedSurface returned %x\n", rc);
117         if (!SUCCEEDED(rc))
118             return FALSE;
119     }
120
121     rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
122         &lpD3DDevice);
123     ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
124     if (!lpD3DDevice) {
125         trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
126         rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
127             &lpD3DDevice);
128         if (!lpD3DDevice) {
129             trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
130             rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
131                 &lpD3DDevice);
132             if (!lpD3DDevice) {
133                 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
134                 return FALSE;
135             }
136         }
137     }
138
139     return TRUE;
140 }
141
142 static void ReleaseDirect3D(void)
143 {
144     if (lpD3DDevice != NULL)
145     {
146         IDirect3DDevice7_Release(lpD3DDevice);
147         lpD3DDevice = NULL;
148     }
149
150     if (lpDDSdepth != NULL)
151     {
152         IDirectDrawSurface_Release(lpDDSdepth);
153         lpDDSdepth = NULL;
154     }
155
156     if (lpDDS != NULL)
157     {
158         IDirectDrawSurface_Release(lpDDS);
159         lpDDS = NULL;
160     }
161
162     if (lpD3D != NULL)
163     {
164         IDirect3D7_Release(lpD3D);
165         lpD3D = NULL;
166     }
167
168     if (lpDD != NULL)
169     {
170         IDirectDraw_Release(lpDD);
171         lpDD = NULL;
172     }
173 }
174
175 static void LightTest(void)
176 {
177     HRESULT rc;
178     D3DLIGHT7 light;
179     D3DLIGHT7 defaultlight;
180     BOOL bEnabled = FALSE;
181     float one = 1.0f;
182     float zero= 0.0f;
183     D3DMATERIAL7 mat;
184
185     /* Set a few lights with funky indices. */
186     memset(&light, 0, sizeof(light));
187     light.dltType = D3DLIGHT_DIRECTIONAL;
188     U1(light.dcvDiffuse).r = 0.5f;
189     U2(light.dcvDiffuse).g = 0.6f;
190     U3(light.dcvDiffuse).b = 0.7f;
191     U2(light.dvDirection).y = 1.f;
192
193     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
194     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
195     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
196     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
197     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
198     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
199
200
201     /* Try to retrieve a light beyond the indices of the lights that have
202        been set. */
203     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
204     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
205     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
206     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
207
208
209     /* Try to retrieve one of the lights that have been set */
210     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
211     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
212
213
214     /* Enable a light that have been previously set. */
215     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
216     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
217
218
219     /* Enable some lights that have not been previously set, and verify that
220        they have been initialized with proper default values. */
221     memset(&defaultlight, 0, sizeof(D3DLIGHT7));
222     defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
223     U1(defaultlight.dcvDiffuse).r = 1.f;
224     U2(defaultlight.dcvDiffuse).g = 1.f;
225     U3(defaultlight.dcvDiffuse).b = 1.f;
226     U3(defaultlight.dvDirection).z = 1.f;
227
228     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
229     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
230     memset(&light, 0, sizeof(D3DLIGHT7));
231     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
232     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
233     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
234         "light data doesn't match expected default values\n" );
235
236     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
237     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
238     memset(&light, 0, sizeof(D3DLIGHT7));
239     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
240     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
241     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
242         "light data doesn't match expected default values\n" );
243
244
245     /* Disable one of the light that have been previously enabled. */
246     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
247     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
248
249     /* Try to retrieve the enable status of some lights */
250     /* Light 20 is supposed to be disabled */
251     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
252     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
253     ok(!bEnabled, "GetLightEnable says the light is enabled\n");
254
255     /* Light 10 is supposed to be enabled */
256     bEnabled = FALSE;
257     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
258     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
259     ok(bEnabled, "GetLightEnable says the light is disabled\n");
260
261     /* Light 80 has not been set */
262     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
263     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
264
265     /* Light 23 has not been set */
266     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
267     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
268
269     /* Set some lights with invalid parameters */
270     memset(&light, 0, sizeof(D3DLIGHT7));
271     light.dltType = 0;
272     U1(light.dcvDiffuse).r = 1.f;
273     U2(light.dcvDiffuse).g = 1.f;
274     U3(light.dcvDiffuse).b = 1.f;
275     U3(light.dvDirection).z = 1.f;
276     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
277     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
278
279     memset(&light, 0, sizeof(D3DLIGHT7));
280     light.dltType = 12345;
281     U1(light.dcvDiffuse).r = 1.f;
282     U2(light.dcvDiffuse).g = 1.f;
283     U3(light.dcvDiffuse).b = 1.f;
284     U3(light.dvDirection).z = 1.f;
285     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
286     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
287
288     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
289     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
290
291     memset(&light, 0, sizeof(D3DLIGHT7));
292     light.dltType = D3DLIGHT_SPOT;
293     U1(light.dcvDiffuse).r = 1.f;
294     U2(light.dcvDiffuse).g = 1.f;
295     U3(light.dcvDiffuse).b = 1.f;
296     U3(light.dvDirection).z = 1.f;
297
298     light.dvAttenuation0 = -one / zero; /* -INFINITY */
299     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
300     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
301
302     light.dvAttenuation0 = -1.0;
303     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
304     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
305
306     light.dvAttenuation0 = 0.0;
307     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
308     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
309
310     light.dvAttenuation0 = 1.0;
311     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
312     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
313
314     light.dvAttenuation0 = one / zero; /* +INFINITY */
315     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
316     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
317
318     light.dvAttenuation0 = zero / zero; /* NaN */
319     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
320     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
321
322     /* Directional light ignores attenuation */
323     light.dltType = D3DLIGHT_DIRECTIONAL;
324     light.dvAttenuation0 = -1.0;
325     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
326     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
327
328     memset(&mat, 0, sizeof(mat));
329     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
330     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial returned: %x\n", rc);
331
332     U4(mat).power = 129.0;
333     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
334     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = 129.0) returned: %x\n", rc);
335     memset(&mat, 0, sizeof(mat));
336     rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
337     ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
338     ok(U4(mat).power == 129, "Returned power is %f\n", U4(mat).power);
339
340     U4(mat).power = -1.0;
341     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
342     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = -1.0) returned: %x\n", rc);
343     memset(&mat, 0, sizeof(mat));
344     rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
345     ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
346     ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
347 }
348
349 static void ProcessVerticesTest(void)
350 {
351     D3DVERTEXBUFFERDESC desc;
352     HRESULT rc;
353     VERTEX *in;
354     TVERTEX *out;
355     VERTEX *out2;
356     D3DVIEWPORT7 vp;
357     D3DMATRIX view = {  2.0, 0.0, 0.0, 0.0,
358                         0.0, -1.0, 0.0, 0.0,
359                         0.0, 0.0, 1.0, 0.0,
360                         0.0, 0.0, 0.0, 3.0 };
361
362     D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
363                         1.0, 0.0, 0.0, 0.0,
364                         0.0, 0.0, 0.0, 1.0,
365                         0.0, 1.0, 1.0, 1.0 };
366
367     D3DMATRIX proj = {  1.0, 0.0, 0.0, 1.0,
368                         0.0, 1.0, 1.0, 0.0,
369                         0.0, 1.0, 1.0, 0.0,
370                         1.0, 0.0, 0.0, 1.0 };
371     /* Create some vertex buffers */
372
373     memset(&desc, 0, sizeof(desc));
374     desc.dwSize = sizeof(desc);
375     desc.dwCaps = 0;
376     desc.dwFVF = D3DFVF_XYZ;
377     desc.dwNumVertices = 16;
378     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
379     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
380     if (!lpVBufSrc)
381     {
382         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
383         goto out;
384     }
385
386     memset(&desc, 0, sizeof(desc));
387     desc.dwSize = sizeof(desc);
388     desc.dwCaps = 0;
389     desc.dwFVF = D3DFVF_XYZRHW;
390     desc.dwNumVertices = 16;
391     /* Msdn says that the last parameter must be 0 - check that */
392     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
393     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
394     if (!lpVBufDest1)
395     {
396         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
397         goto out;
398     }
399
400     memset(&desc, 0, sizeof(desc));
401     desc.dwSize = sizeof(desc);
402     desc.dwCaps = 0;
403     desc.dwFVF = D3DFVF_XYZ;
404     desc.dwNumVertices = 16;
405     /* Msdn says that the last parameter must be 0 - check that */
406     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
407     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
408     if (!lpVBufDest2)
409     {
410         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
411         goto out;
412     }
413
414     rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
415     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
416     if(!in) goto out;
417
418     /* Check basic transformation */
419
420     in[0].x = 0.0;
421     in[0].y = 0.0;
422     in[0].z = 0.0;
423
424     in[1].x = 1.0;
425     in[1].y = 1.0;
426     in[1].z = 1.0;
427
428     in[2].x = -1.0;
429     in[2].y = -1.0;
430     in[2].z = 0.5;
431
432     in[3].x = 0.5;
433     in[3].y = -0.5;
434     in[3].z = 0.25;
435     rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
436     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
437
438     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
439     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
440
441     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
442     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
443
444     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
445     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
446     if(!out) goto out;
447
448     /* Check the results */
449     ok( comparefloat(out[0].x, 128.0 ) &&
450         comparefloat(out[0].y, 128.0 ) &&
451         comparefloat(out[0].z, 0.0 ) &&
452         comparefloat(out[0].rhw, 1.0 ),
453         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
454
455     ok( comparefloat(out[1].x, 256.0 ) &&
456         comparefloat(out[1].y, 0.0 ) &&
457         comparefloat(out[1].z, 1.0 ) &&
458         comparefloat(out[1].rhw, 1.0 ),
459         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
460
461     ok( comparefloat(out[2].x, 0.0 ) &&
462         comparefloat(out[2].y, 256.0 ) &&
463         comparefloat(out[2].z, 0.5 ) &&
464         comparefloat(out[2].rhw, 1.0 ),
465         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
466
467     ok( comparefloat(out[3].x, 192.0 ) &&
468         comparefloat(out[3].y, 192.0 ) &&
469         comparefloat(out[3].z, 0.25 ) &&
470         comparefloat(out[3].rhw, 1.0 ),
471         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
472
473     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
474     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
475     out = NULL;
476
477     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
478     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
479     if(!out2) goto out;
480     /* Small thing without much practial meaning, but I stumbled upon it,
481      * so let's check for it: If the output vertex buffer has to RHW value,
482      * The RHW value of the last vertex is written into the next vertex
483      */
484     ok( comparefloat(out2[4].x, 1.0 ) &&
485         comparefloat(out2[4].y, 0.0 ) &&
486         comparefloat(out2[4].z, 0.0 ),
487         "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
488
489     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
490     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
491     out = NULL;
492
493     /* Try a more complicated viewport, same vertices */
494     memset(&vp, 0, sizeof(vp));
495     vp.dwX = 10;
496     vp.dwY = 5;
497     vp.dwWidth = 246;
498     vp.dwHeight = 130;
499     vp.dvMinZ = -2.0;
500     vp.dvMaxZ = 4.0;
501     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
502     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
503
504     /* Process again */
505     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
506     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
507
508     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
509     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
510     if(!out) goto out;
511
512     /* Check the results */
513     ok( comparefloat(out[0].x, 133.0 ) &&
514         comparefloat(out[0].y, 70.0 ) &&
515         comparefloat(out[0].z, -2.0 ) &&
516         comparefloat(out[0].rhw, 1.0 ),
517         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
518
519     ok( comparefloat(out[1].x, 256.0 ) &&
520         comparefloat(out[1].y, 5.0 ) &&
521         comparefloat(out[1].z, 4.0 ) &&
522         comparefloat(out[1].rhw, 1.0 ),
523         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
524
525     ok( comparefloat(out[2].x, 10.0 ) &&
526         comparefloat(out[2].y, 135.0 ) &&
527         comparefloat(out[2].z, 1.0 ) &&
528         comparefloat(out[2].rhw, 1.0 ),
529         "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
530
531     ok( comparefloat(out[3].x, 194.5 ) &&
532         comparefloat(out[3].y, 102.5 ) &&
533         comparefloat(out[3].z, -0.5 ) &&
534         comparefloat(out[3].rhw, 1.0 ),
535         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
536
537     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
538     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
539     out = NULL;
540
541     /* Play with some matrices. */
542
543     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
544     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
545
546     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
547     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
548
549     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
550     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
551
552     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
553     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
554
555     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
556     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
557     if(!out) goto out;
558
559     /* Keep the viewport simpler, otherwise we get bad numbers to compare */
560     vp.dwX = 0;
561     vp.dwY = 0;
562     vp.dwWidth = 100;
563     vp.dwHeight = 100;
564     vp.dvMinZ = 1.0;
565     vp.dvMaxZ = 0.0;
566     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
567     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
568
569     /* Check the results */
570     ok( comparefloat(out[0].x, 256.0 ) &&    /* X coordinate is cut at the surface edges */
571         comparefloat(out[0].y, 70.0 ) &&
572         comparefloat(out[0].z, -2.0 ) &&
573         comparefloat(out[0].rhw, (1.0 / 3.0)),
574         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
575
576     ok( comparefloat(out[1].x, 256.0 ) &&
577         comparefloat(out[1].y, 78.125000 ) &&
578         comparefloat(out[1].z, -2.750000 ) &&
579         comparefloat(out[1].rhw, 0.125000 ),
580         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
581
582     ok( comparefloat(out[2].x, 256.0 ) &&
583         comparefloat(out[2].y, 44.000000 ) &&
584         comparefloat(out[2].z, 0.400000 ) &&
585         comparefloat(out[2].rhw, 0.400000 ),
586         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
587
588     ok( comparefloat(out[3].x, 256.0 ) &&
589         comparefloat(out[3].y, 81.818184 ) &&
590         comparefloat(out[3].z, -3.090909 ) &&
591         comparefloat(out[3].rhw, 0.363636 ),
592         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
593
594     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
595     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
596     out = NULL;
597
598 out:
599     IDirect3DVertexBuffer7_Release(lpVBufSrc);
600     IDirect3DVertexBuffer7_Release(lpVBufDest1);
601     IDirect3DVertexBuffer7_Release(lpVBufDest2);
602 }
603
604 static void StateTest( void )
605 {
606     HRESULT rc;
607
608     /* The msdn says its undocumented, does it return an error too? */
609     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
610     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
611     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
612     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
613 }
614
615
616 static void SceneTest(void)
617 {
618     HRESULT                      hr;
619
620     /* Test an EndScene without beginscene. Should return an error */
621     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
622     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
623
624     /* Test a normal BeginScene / EndScene pair, this should work */
625     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
626     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
627     if(SUCCEEDED(hr))
628     {
629         DDBLTFX fx;
630         memset(&fx, 0, sizeof(fx));
631         fx.dwSize = sizeof(fx);
632
633         if(lpDDSdepth) {
634             hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
635             ok(hr == D3D_OK, "Depthfill failed in a BeginScene / EndScene pair\n");
636         } else {
637             skip("Depth stencil creation failed at startup, skipping\n");
638         }
639         hr = IDirect3DDevice7_EndScene(lpD3DDevice);
640         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
641     }
642
643     /* Test another EndScene without having begun a new scene. Should return an error */
644     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
645     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
646
647     /* Two nested BeginScene and EndScene calls */
648     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
649     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
650     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
651     ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
652     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
653     ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
654     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
655     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
656
657     /* TODO: Verify that blitting works in the same way as in d3d9 */
658 }
659
660 static void LimitTest(void)
661 {
662     IDirectDrawSurface7 *pTexture = NULL;
663     HRESULT hr;
664     int i;
665     DDSURFACEDESC2 ddsd;
666
667     memset(&ddsd, 0, sizeof(ddsd));
668     ddsd.dwSize = sizeof(ddsd);
669     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
670     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
671     ddsd.dwWidth = 16;
672     ddsd.dwHeight = 16;
673     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
674     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
675     if(!pTexture) return;
676
677     for(i = 0; i < 8; i++) {
678         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
679         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
680         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
681         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
682         hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
683         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
684     }
685
686     IDirectDrawSurface7_Release(pTexture);
687 }
688
689 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
690 {
691     UINT ver = *((UINT *) ctx);
692     if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
693     {
694         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
695            "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
696         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
697            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
698         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
699            "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
700         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
701            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
702
703         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
704            "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
705         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
706            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
707         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
708            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
709         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
710            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
711     }
712     else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
713     {
714         /* pow2 is hardware dependent */
715
716         ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
717            "HAL Device %d hal line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
718         ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
719            "HAL Device %d hal tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
720         ok((hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
721            "HAL Device %d hel line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
722         ok((hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
723            "HAL Device %d hel tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
724     }
725     else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
726     {
727         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
728            "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
729         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
730            "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
731         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
732            "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
733         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
734            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
735
736         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
737            "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
738         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
739            "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
740         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
741            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
742         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
743            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
744     }
745     else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
746     {
747         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
748            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
749         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
750            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
751         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
752            "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
753         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
754            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
755
756         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
757            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
758         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
759            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
760         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
761            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
762         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
763            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
764     }
765     else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
766     {
767         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
768            "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
769         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
770            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
771         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
772            "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
773         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
774            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
775
776         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
777            "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
778         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
779            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
780         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
781            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
782         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
783            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
784     }
785     else
786     {
787         ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
788         if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
789         else trace("hal line does NOT have pow2 set\n");
790         if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
791         else trace("hal tri does NOT have pow2 set\n");
792         if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
793         else trace("hel line does NOT have pow2 set\n");
794         if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
795         else trace("hel tri does NOT have pow2 set\n");
796     }
797     return DDENUMRET_OK;
798 }
799
800 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
801 {
802     D3D7ETest *d3d7et = (D3D7ETest*)Context;
803     if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
804         d3d7et->rgb++;
805     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
806         d3d7et->hal++;
807     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
808         d3d7et->tnlhal++;
809     else
810         d3d7et->unk++;
811
812     d3d7et->total++;
813
814     return DDENUMRET_OK;
815 }
816
817
818 /*  Check the deviceGUID of devices enumerated by
819     IDirect3D7_EnumDevices. */
820 static void D3D7EnumTest(void)
821 {
822     D3D7ETest d3d7et;
823
824     if (!lpD3D) {
825         skip("No Direct3D7 interface.\n");
826         return;
827     }
828
829     memset(&d3d7et, 0, sizeof(d3d7et));
830     IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, (LPVOID) &d3d7et);
831
832
833     /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
834     ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
835
836     /* We make two additional assumptions. */
837     ok(d3d7et.rgb, "No RGB Device enumerated.\n");
838
839     if(d3d7et.tnlhal)
840         ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
841
842     return;
843 }
844
845 static void CapsTest(void)
846 {
847     IDirect3D3 *d3d3;
848     IDirect3D3 *d3d2;
849     IDirectDraw *dd1;
850     HRESULT hr;
851     UINT ver;
852
853     hr = DirectDrawCreate(NULL, &dd1, NULL);
854     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
855     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
856     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
857     ver = 3;
858     IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
859
860     IDirect3D3_Release(d3d3);
861     IDirectDraw_Release(dd1);
862
863     hr = DirectDrawCreate(NULL, &dd1, NULL);
864     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
865     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
866     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
867     ver = 2;
868     IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
869
870     IDirect3D2_Release(d3d2);
871     IDirectDraw_Release(dd1);
872 }
873
874 struct v_in {
875     float x, y, z;
876 };
877 struct v_out {
878     float x, y, z, rhw;
879 };
880
881 static void Direct3D1Test(void)
882 {
883     IDirect3DDevice *dev1 = NULL;
884     IDirectDraw *dd;
885     IDirect3D *d3d;
886     IDirectDrawSurface *dds;
887     IDirect3DExecuteBuffer *exebuf;
888     IDirect3DViewport *vp;
889     HRESULT hr;
890     DDSURFACEDESC ddsd;
891     D3DEXECUTEBUFFERDESC desc;
892     D3DVIEWPORT vp_data;
893     D3DINSTRUCTION *instr;
894     D3DBRANCH *branch;
895     unsigned int idx = 0;
896     static struct v_in testverts[] = {
897         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
898         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
899     };
900     static struct v_in cliptest[] = {
901         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
902         {25.61, 25.61, 1.01}, {-25.60, -25.60, -0.01},
903     };
904     static struct v_in offscreentest[] = {
905         {128.1, 0.0, 0.0},
906     };
907     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
908     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
909     D3DTRANSFORMDATA transformdata;
910     DWORD i = FALSE;
911
912     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
913     hr = DirectDrawCreate(NULL, &dd, NULL);
914     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
915     if (!dd) {
916         trace("DirectDrawCreate() failed with an error %x\n", hr);
917         return;
918     }
919
920     hr = IDirectDraw_SetCooperativeLevel(dd, NULL, DDSCL_NORMAL);
921     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
922
923     hr = IDirectDraw_QueryInterface(dd, &IID_IDirect3D, (void**) &d3d);
924     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
925
926     memset(&ddsd, 0, sizeof(ddsd));
927     ddsd.dwSize = sizeof(ddsd);
928     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
929     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
930     ddsd.dwWidth = 256;
931     ddsd.dwHeight = 256;
932     hr = IDirectDraw_CreateSurface(dd, &ddsd, &dds, NULL);
933     ok(hr==DD_OK, "CreateSurface returned: %x\n", hr);
934
935     dev1 = NULL;
936     hr = IDirectDrawSurface_QueryInterface(dds, &IID_IDirect3DRGBDevice, (void **) &dev1);
937     ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
938     if(!dev1) return;
939
940     memset(&desc, 0, sizeof(desc));
941     desc.dwSize = sizeof(desc);
942     desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
943     desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
944     desc.dwBufferSize = 128;
945     desc.lpData = NULL;
946     hr = IDirect3DDevice_CreateExecuteBuffer(dev1, &desc, &exebuf, NULL);
947     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
948
949     memset(&desc, 0, sizeof(desc));
950     desc.dwSize = sizeof(desc);
951
952     hr = IDirect3DExecuteBuffer_Lock(exebuf, &desc);
953     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
954     instr = desc.lpData;
955     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
956     instr[idx].bSize = sizeof(*branch);
957     instr[idx].wCount = 1;
958     idx++;
959     branch = (D3DBRANCH *) &instr[idx];
960     branch->dwMask = 0x0;
961     branch->dwValue = 1;
962     branch->bNegate = TRUE;
963     branch->dwOffset = 0;
964     idx += (sizeof(*branch) / sizeof(*instr));
965     instr[idx].bOpcode = D3DOP_EXIT;
966     instr[idx].bSize = 0;
967     instr[idx].bSize = 0;
968     hr = IDirect3DExecuteBuffer_Unlock(exebuf);
969     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
970
971     hr = IDirect3D_CreateViewport(d3d, &vp, NULL);
972     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
973     hr = IDirect3DViewport_Initialize(vp, d3d);
974     ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
975
976     hr = IDirect3DDevice_AddViewport(dev1, vp);
977     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
978     vp_data.dwSize = sizeof(vp_data);
979     vp_data.dwX = 0;
980     vp_data.dwY = 0;
981     vp_data.dwWidth = 256;
982     vp_data.dwHeight = 256;
983     vp_data.dvScaleX = 1;
984     vp_data.dvScaleY = 1;
985     vp_data.dvMaxX = 256;
986     vp_data.dvMaxY = 256;
987     vp_data.dvMinZ = 0;
988     vp_data.dvMaxZ = 1;
989     hr = IDirect3DViewport_SetViewport(vp, &vp_data);
990     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
991
992     hr = IDirect3DDevice_Execute(dev1, exebuf, vp, D3DEXECUTE_CLIPPED);
993     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
994
995     memset(&transformdata, 0, sizeof(transformdata));
996     transformdata.dwSize = sizeof(transformdata);
997     transformdata.lpIn = (void *) testverts;
998     transformdata.dwInSize = sizeof(testverts[0]);
999     transformdata.lpOut = out;
1000     transformdata.dwOutSize = sizeof(out[0]);
1001
1002     transformdata.lpHOut = NULL;
1003     hr = IDirect3DViewport_TransformVertices(vp, sizeof(testverts) / sizeof(testverts[0]),
1004                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1005                                              &i);
1006     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1007
1008     transformdata.lpHOut = outH;
1009     memset(outH, 0xaa, sizeof(outH));
1010     hr = IDirect3DViewport_TransformVertices(vp, sizeof(testverts) / sizeof(testverts[0]),
1011                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1012                                              &i);
1013     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1014     ok(i == 0, "Offscreen is %d\n", i);
1015
1016     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1017         static const struct v_out cmp[] = {
1018             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1019             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1020         };
1021
1022         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1023            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1024            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1025            out[i].x, out[i].y, out[i].z, out[i].rhw,
1026            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1027     }
1028     for(i = 0; i < sizeof(outH); i++) {
1029         if(((unsigned char *) outH)[i] != 0xaa) {
1030             ok(FALSE, "Homogenous output was generated despite UNCLIPPED flag\n");
1031             break;
1032         }
1033     }
1034
1035     vp_data.dvScaleX = 5;
1036     vp_data.dvScaleY = 5;
1037     vp_data.dvMinZ = -25;
1038     vp_data.dvMaxZ = 60;
1039     hr = IDirect3DViewport_SetViewport(vp, &vp_data);
1040     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1041     hr = IDirect3DViewport_TransformVertices(vp, sizeof(testverts) / sizeof(testverts[0]),
1042                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1043                                              &i);
1044     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1045     ok(i == 0, "Offscreen is %d\n", i);
1046     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1047         static const struct v_out cmp[] = {
1048             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1049             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1050         };
1051         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1052            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1053            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1054            out[i].x, out[i].y, out[i].z, out[i].rhw,
1055            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1056     }
1057
1058     vp_data.dwX = 10;
1059     vp_data.dwY = 20;
1060     hr = IDirect3DViewport_SetViewport(vp, &vp_data);
1061     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1062     hr = IDirect3DViewport_TransformVertices(vp, sizeof(testverts) / sizeof(testverts[0]),
1063                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1064                                              &i);
1065     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1066     ok(i == 0, "Offscreen is %d\n", i);
1067     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1068         static const struct v_out cmp[] = {
1069             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1070             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1071         };
1072         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1073            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1074            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1075            out[i].x, out[i].y, out[i].z, out[i].rhw,
1076            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1077     }
1078
1079     memset(out, 0xbb, sizeof(out));
1080     hr = IDirect3DViewport_TransformVertices(vp, sizeof(testverts) / sizeof(testverts[0]),
1081                                              &transformdata, D3DTRANSFORM_CLIPPED,
1082                                              &i);
1083     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1084     ok(i == 0, "Offscreen is %d\n", i);
1085     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1086         static const D3DHVERTEX cmpH[] = {
1087             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1088             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1089             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1090         };
1091         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1092            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1093            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1094            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1095            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1096
1097         /* No scheme has been found behind those return values. It seems to be
1098          * whatever data windows has when throwing the vertex away. Modify the
1099          * input test vertices to test this more. Depending on the input data
1100          * it can happen that the z coord gets written into y, or similar things
1101          */
1102         if(0)
1103         {
1104             static const struct v_out cmp[] = {
1105                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1106                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1107             };
1108             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1109                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1110                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1111                out[i].x, out[i].y, out[i].z, out[i].rhw,
1112                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1113         }
1114     }
1115     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1116         ok(((DWORD *) out)[i] != 0xbbbbbbbb,
1117                 "Regular output DWORD %d remained untouched\n", i);
1118     }
1119
1120     transformdata.lpIn = (void *) cliptest;
1121     transformdata.dwInSize = sizeof(cliptest[0]);
1122     hr = IDirect3DViewport_TransformVertices(vp, sizeof(cliptest) / sizeof(cliptest[0]),
1123                                              &transformdata, D3DTRANSFORM_CLIPPED,
1124                                              &i);
1125     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1126     ok(i == 0, "Offscreen is %d\n", i);
1127     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1128         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1129         {
1130             0,
1131             0,
1132             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1133             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1134         };
1135         ok(Flags[i] == outH[i].dwFlags,
1136            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1137            outH[i].dwFlags, Flags[i]);
1138     }
1139
1140     vp_data.dwWidth = 10;
1141     vp_data.dwHeight = 1000;
1142     hr = IDirect3DViewport_SetViewport(vp, &vp_data);
1143     i = 10;
1144     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1145     hr = IDirect3DViewport_TransformVertices(vp, sizeof(cliptest) / sizeof(cliptest[0]),
1146                                              &transformdata, D3DTRANSFORM_CLIPPED,
1147                                              &i);
1148     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1149     ok(i == 0, "Offscreen is %d\n", i);
1150     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1151         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1152         {
1153             D3DCLIP_RIGHT,
1154             D3DCLIP_LEFT,
1155             D3DCLIP_RIGHT | D3DCLIP_BACK,
1156             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1157         };
1158         ok(Flags[i] == outH[i].dwFlags,
1159            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1160            outH[i].dwFlags, Flags[i]);
1161     }
1162     vp_data.dwWidth = 256;
1163     vp_data.dwHeight = 256;
1164     vp_data.dvScaleX = 1;
1165     vp_data.dvScaleY = 1;
1166     hr = IDirect3DViewport_SetViewport(vp, &vp_data);
1167     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1168     hr = IDirect3DViewport_TransformVertices(vp, sizeof(cliptest) / sizeof(cliptest[0]),
1169                                              &transformdata, D3DTRANSFORM_CLIPPED,
1170                                              &i);
1171     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1172     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1173     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1174         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1175         {
1176             0,
1177             0,
1178             D3DCLIP_BACK,
1179             D3DCLIP_FRONT,
1180         };
1181         ok(Flags[i] == outH[i].dwFlags,
1182            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1183            outH[i].dwFlags, Flags[i]);
1184     }
1185
1186     /* Finally try to figure out how the DWORD dwOffscreen works.
1187      * Apparently no vertex is offscreen with clipping off,
1188      * and with clipping on the offscreen flag is set if only one vertex
1189      * is transformed, and this vertex is offscreen.
1190      */
1191     vp_data.dwWidth = 5;
1192     vp_data.dwHeight = 5;
1193     vp_data.dvScaleX = 10000;
1194     vp_data.dvScaleY = 10000;
1195     hr = IDirect3DViewport_SetViewport(vp, &vp_data);
1196     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1197     transformdata.lpIn = cliptest;
1198     hr = IDirect3DViewport_TransformVertices(vp, 1,
1199                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1200                                              &i);
1201     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1202     ok(i == 0, "Offscreen is %d\n", i);
1203     hr = IDirect3DViewport_TransformVertices(vp, 1,
1204                                              &transformdata, D3DTRANSFORM_CLIPPED,
1205                                              &i);
1206     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1207     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1208     hr = IDirect3DViewport_TransformVertices(vp, 2,
1209                                              &transformdata, D3DTRANSFORM_CLIPPED,
1210                                              &i);
1211     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1212     ok(i == 0, "Offscreen is %d\n", i);
1213     transformdata.lpIn = cliptest + 1;
1214     hr = IDirect3DViewport_TransformVertices(vp, 1,
1215                                              &transformdata, D3DTRANSFORM_CLIPPED,
1216                                              &i);
1217     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1218     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1219
1220     transformdata.lpIn = (void *) offscreentest;
1221     transformdata.dwInSize = sizeof(offscreentest[0]);
1222     vp_data.dwWidth = 257;
1223     vp_data.dwHeight = 257;
1224     vp_data.dvScaleX = 1;
1225     vp_data.dvScaleY = 1;
1226     hr = IDirect3DViewport_SetViewport(vp, &vp_data);
1227     i = 12345;
1228     hr = IDirect3DViewport_TransformVertices(vp, sizeof(offscreentest) / sizeof(offscreentest[0]),
1229                                              &transformdata, D3DTRANSFORM_CLIPPED,
1230                                              &i);
1231     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1232     ok(i == 0, "Offscreen is %d\n", i);
1233     vp_data.dwWidth = 256;
1234     vp_data.dwHeight = 256;
1235     hr = IDirect3DViewport_SetViewport(vp, &vp_data);
1236     i = 12345;
1237     hr = IDirect3DViewport_TransformVertices(vp, sizeof(offscreentest) / sizeof(offscreentest[0]),
1238                                              &transformdata, D3DTRANSFORM_CLIPPED,
1239                                              &i);
1240     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1241     ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1242
1243     hr = IDirect3DViewport_TransformVertices(vp, sizeof(testverts) / sizeof(testverts[0]),
1244                                              &transformdata, 0,
1245                                              &i);
1246     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1247
1248     hr = IDirect3DDevice_DeleteViewport(dev1, vp);
1249     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1250
1251     IDirect3DViewport_Release(vp);
1252     IDirect3DExecuteBuffer_Release(exebuf);
1253     IDirect3DDevice_Release(dev1);
1254     IDirectDrawSurface_Release(dds);
1255     IDirect3D_Release(d3d);
1256     IDirectDraw_Release(dd);
1257     return;
1258 }
1259
1260 START_TEST(d3d)
1261 {
1262     init_function_pointers();
1263     if(!pDirectDrawCreateEx) {
1264         skip("function DirectDrawCreateEx not available\n");
1265         return;
1266     }
1267
1268     if(!CreateDirect3D()) {
1269         trace("Skipping tests\n");
1270         return;
1271     }
1272     LightTest();
1273     ProcessVerticesTest();
1274     StateTest();
1275     SceneTest();
1276     LimitTest();
1277     D3D7EnumTest();
1278     CapsTest();
1279     ReleaseDirect3D();
1280     Direct3D1Test();
1281 }