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