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