comctl32/tooltips: Remove redundant code, let handlers deal with A<->W conversions.
[wine] / dlls / ddraw / tests / d3d.c
1 /*
2  * Some unit tests for d3d functions
3  *
4  * Copyright (C) 2005 Antoine Chavasse
5  * Copyright (C) 2006 Stefan Dösinger for CodeWeavers
6  * 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 <assert.h>
26 #include "wine/test.h"
27 #include "initguid.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "unknwn.h"
31
32 static LPDIRECTDRAW7           lpDD = NULL;
33 static LPDIRECT3D7             lpD3D = NULL;
34 static LPDIRECTDRAWSURFACE7    lpDDS = NULL;
35 static LPDIRECTDRAWSURFACE7    lpDDSdepth = NULL;
36 static LPDIRECT3DDEVICE7       lpD3DDevice = NULL;
37 static LPDIRECT3DVERTEXBUFFER7 lpVBufSrc = NULL;
38 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest1 = NULL;
39 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest2 = NULL;
40
41 static IDirectDraw *DirectDraw1 = NULL;
42 static IDirectDrawSurface *Surface1 = NULL;
43 static IDirect3D *Direct3D1 = NULL;
44 static IDirect3DDevice *Direct3DDevice1 = NULL;
45 static IDirect3DExecuteBuffer *ExecuteBuffer = NULL;
46 static IDirect3DViewport *Viewport = NULL;
47 static IDirect3DLight *Light = NULL;
48
49 typedef struct {
50     int total;
51     int rgb;
52     int hal;
53     int tnlhal;
54     int unk;
55 } D3D7ETest;
56
57 /* To compare bad floating point numbers. Not the ideal way to do it,
58  * but it should be enough for here */
59 #define comparefloat(a, b) ( (((a) - (b)) < 0.0001) && (((a) - (b)) > -0.0001) )
60
61 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
62
63 typedef struct _VERTEX
64 {
65     float x, y, z;  /* position */
66 } VERTEX, *LPVERTEX;
67
68 typedef struct _TVERTEX
69 {
70     float x, y, z;  /* position */
71     float rhw;
72 } TVERTEX, *LPTVERTEX;
73
74
75 static void init_function_pointers(void)
76 {
77     HMODULE hmod = GetModuleHandleA("ddraw.dll");
78     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
79 }
80
81
82 static ULONG getRefcount(IUnknown *iface)
83 {
84     IUnknown_AddRef(iface);
85     return IUnknown_Release(iface);
86 }
87
88
89 static BOOL CreateDirect3D(void)
90 {
91     HRESULT rc;
92     DDSURFACEDESC2 ddsd;
93
94     rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
95         &IID_IDirectDraw7, NULL);
96     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
97     if (!lpDD) {
98         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
99         return FALSE;
100     }
101
102     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
103     ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
104
105     rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
106     if (rc == E_NOINTERFACE) return FALSE;
107     ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
108
109     memset(&ddsd, 0, sizeof(ddsd));
110     ddsd.dwSize = sizeof(ddsd);
111     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
112     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
113     ddsd.dwWidth = 256;
114     ddsd.dwHeight = 256;
115     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
116     if (FAILED(rc))
117         return FALSE;
118
119     memset(&ddsd, 0, sizeof(ddsd));
120     ddsd.dwSize = sizeof(ddsd);
121     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
122     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
123     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
124     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
125     U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 16;
126     U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
127     ddsd.dwWidth = 256;
128     ddsd.dwHeight = 256;
129     rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDSdepth, NULL);
130     ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
131     if (FAILED(rc)) {
132         lpDDSdepth = NULL;
133     } else {
134         rc = IDirectDrawSurface_AddAttachedSurface(lpDDS, lpDDSdepth);
135         ok(rc == DD_OK, "IDirectDrawSurface_AddAttachedSurface returned %x\n", rc);
136         if (FAILED(rc))
137             return FALSE;
138     }
139
140     rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
141         &lpD3DDevice);
142     ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
143     if (!lpD3DDevice) {
144         trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
145         rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
146             &lpD3DDevice);
147         if (!lpD3DDevice) {
148             trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
149             rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
150                 &lpD3DDevice);
151             if (!lpD3DDevice) {
152                 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
153                 return FALSE;
154             }
155         }
156     }
157
158     return TRUE;
159 }
160
161 static void ReleaseDirect3D(void)
162 {
163     if (lpD3DDevice != NULL)
164     {
165         IDirect3DDevice7_Release(lpD3DDevice);
166         lpD3DDevice = NULL;
167     }
168
169     if (lpDDSdepth != NULL)
170     {
171         IDirectDrawSurface_Release(lpDDSdepth);
172         lpDDSdepth = NULL;
173     }
174
175     if (lpDDS != NULL)
176     {
177         IDirectDrawSurface_Release(lpDDS);
178         lpDDS = NULL;
179     }
180
181     if (lpD3D != NULL)
182     {
183         IDirect3D7_Release(lpD3D);
184         lpD3D = NULL;
185     }
186
187     if (lpDD != NULL)
188     {
189         IDirectDraw_Release(lpDD);
190         lpDD = NULL;
191     }
192 }
193
194 static void LightTest(void)
195 {
196     HRESULT rc;
197     D3DLIGHT7 light;
198     D3DLIGHT7 defaultlight;
199     BOOL bEnabled = FALSE;
200     float one = 1.0f;
201     float zero= 0.0f;
202     D3DMATERIAL7 mat;
203     BOOL enabled;
204     unsigned int i;
205     D3DDEVICEDESC7 caps;
206
207     /* Set a few lights with funky indices. */
208     memset(&light, 0, sizeof(light));
209     light.dltType = D3DLIGHT_DIRECTIONAL;
210     U1(light.dcvDiffuse).r = 0.5f;
211     U2(light.dcvDiffuse).g = 0.6f;
212     U3(light.dcvDiffuse).b = 0.7f;
213     U2(light.dvDirection).y = 1.f;
214
215     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
216     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
217     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
218     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
219     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
220     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
221
222
223     /* Try to retrieve a light beyond the indices of the lights that have
224        been set. */
225     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
226     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
227     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
228     ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
229
230
231     /* Try to retrieve one of the lights that have been set */
232     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
233     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
234
235
236     /* Enable a light that have been previously set. */
237     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
238     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
239
240
241     /* Enable some lights that have not been previously set, and verify that
242        they have been initialized with proper default values. */
243     memset(&defaultlight, 0, sizeof(D3DLIGHT7));
244     defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
245     U1(defaultlight.dcvDiffuse).r = 1.f;
246     U2(defaultlight.dcvDiffuse).g = 1.f;
247     U3(defaultlight.dcvDiffuse).b = 1.f;
248     U3(defaultlight.dvDirection).z = 1.f;
249
250     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
251     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
252     memset(&light, 0, sizeof(D3DLIGHT7));
253     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
254     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
255     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
256         "light data doesn't match expected default values\n" );
257
258     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
259     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
260     memset(&light, 0, sizeof(D3DLIGHT7));
261     rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
262     ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
263     ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
264         "light data doesn't match expected default values\n" );
265
266
267     /* Disable one of the light that have been previously enabled. */
268     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
269     ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
270
271     /* Try to retrieve the enable status of some lights */
272     /* Light 20 is supposed to be disabled */
273     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
274     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
275     ok(!bEnabled, "GetLightEnable says the light is enabled\n");
276
277     /* Light 10 is supposed to be enabled */
278     bEnabled = FALSE;
279     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
280     ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
281     ok(bEnabled, "GetLightEnable says the light is disabled\n");
282
283     /* Light 80 has not been set */
284     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
285     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
286
287     /* Light 23 has not been set */
288     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
289     ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
290
291     /* Set some lights with invalid parameters */
292     memset(&light, 0, sizeof(D3DLIGHT7));
293     light.dltType = 0;
294     U1(light.dcvDiffuse).r = 1.f;
295     U2(light.dcvDiffuse).g = 1.f;
296     U3(light.dcvDiffuse).b = 1.f;
297     U3(light.dvDirection).z = 1.f;
298     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
299     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
300
301     memset(&light, 0, sizeof(D3DLIGHT7));
302     light.dltType = 12345;
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, 101, &light);
308     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
309
310     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
311     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
312
313     memset(&light, 0, sizeof(D3DLIGHT7));
314     light.dltType = D3DLIGHT_SPOT;
315     U1(light.dcvDiffuse).r = 1.f;
316     U2(light.dcvDiffuse).g = 1.f;
317     U3(light.dcvDiffuse).b = 1.f;
318     U3(light.dvDirection).z = 1.f;
319
320     light.dvAttenuation0 = -one / zero; /* -INFINITY */
321     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
322     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
323
324     light.dvAttenuation0 = -1.0;
325     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
326     ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
327
328     light.dvAttenuation0 = 0.0;
329     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
330     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
331
332     light.dvAttenuation0 = 1.0;
333     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
334     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
335
336     light.dvAttenuation0 = one / zero; /* +INFINITY */
337     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
338     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
339
340     light.dvAttenuation0 = zero / zero; /* NaN */
341     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
342     ok(rc==D3D_OK ||
343        broken(rc==DDERR_INVALIDPARAMS), "SetLight returned: %x\n", rc);
344
345     /* Directional light ignores attenuation */
346     light.dltType = D3DLIGHT_DIRECTIONAL;
347     light.dvAttenuation0 = -1.0;
348     rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
349     ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
350
351     memset(&mat, 0, sizeof(mat));
352     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
353     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial returned: %x\n", rc);
354
355     U4(mat).power = 129.0;
356     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
357     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = 129.0) returned: %x\n", rc);
358     memset(&mat, 0, sizeof(mat));
359     rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
360     ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
361     ok(U4(mat).power == 129, "Returned power is %f\n", U4(mat).power);
362
363     U4(mat).power = -1.0;
364     rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
365     ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = -1.0) returned: %x\n", rc);
366     memset(&mat, 0, sizeof(mat));
367     rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
368     ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
369     ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
370
371     memset(&caps, 0, sizeof(caps));
372     rc = IDirect3DDevice7_GetCaps(lpD3DDevice, &caps);
373     ok(rc == D3D_OK, "IDirect3DDevice7_GetCaps failed with %x\n", rc);
374
375     if ( caps.dwMaxActiveLights == (DWORD) -1) {
376         /* Some cards without T&L Support return -1 (Examples: Voodoo Banshee, RivaTNT / NV4) */
377         skip("T&L not supported\n");
378         return;
379     }
380
381     for(i = 1; i <= caps.dwMaxActiveLights; i++) {
382         rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, TRUE);
383         ok(rc == D3D_OK, "Enabling light %u failed with %x\n", i, rc);
384         rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i, &enabled);
385         ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i, rc);
386         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
387     }
388
389     /* TODO: Test the rendering results in this situation */
390     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, TRUE);
391     ok(rc == D3D_OK, "Enabling one light more than supported returned %x\n", rc);
392     rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i + 1, &enabled);
393     ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i + 1,  rc);
394     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
395     rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, FALSE);
396     ok(rc == D3D_OK, "Disabling the additional returned %x\n", rc);
397
398     for(i = 1; i <= caps.dwMaxActiveLights; i++) {
399         rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, FALSE);
400         ok(rc == D3D_OK, "Disabling light %u failed with %x\n", i, rc);
401     }
402 }
403
404 static void ProcessVerticesTest(void)
405 {
406     D3DVERTEXBUFFERDESC desc;
407     HRESULT rc;
408     VERTEX *in;
409     TVERTEX *out;
410     VERTEX *out2;
411     D3DVIEWPORT7 vp;
412     D3DMATRIX view = {  2.0, 0.0, 0.0, 0.0,
413                         0.0, -1.0, 0.0, 0.0,
414                         0.0, 0.0, 1.0, 0.0,
415                         0.0, 0.0, 0.0, 3.0 };
416
417     D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
418                         1.0, 0.0, 0.0, 0.0,
419                         0.0, 0.0, 0.0, 1.0,
420                         0.0, 1.0, 1.0, 1.0 };
421
422     D3DMATRIX proj = {  1.0, 0.0, 0.0, 1.0,
423                         0.0, 1.0, 1.0, 0.0,
424                         0.0, 1.0, 1.0, 0.0,
425                         1.0, 0.0, 0.0, 1.0 };
426     /* Create some vertex buffers */
427
428     memset(&desc, 0, sizeof(desc));
429     desc.dwSize = sizeof(desc);
430     desc.dwCaps = 0;
431     desc.dwFVF = D3DFVF_XYZ;
432     desc.dwNumVertices = 16;
433     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
434     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
435     if (!lpVBufSrc)
436     {
437         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
438         goto out;
439     }
440
441     memset(&desc, 0, sizeof(desc));
442     desc.dwSize = sizeof(desc);
443     desc.dwCaps = 0;
444     desc.dwFVF = D3DFVF_XYZRHW;
445     desc.dwNumVertices = 16;
446     /* Msdn says that the last parameter must be 0 - check that */
447     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
448     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
449     if (!lpVBufDest1)
450     {
451         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
452         goto out;
453     }
454
455     memset(&desc, 0, sizeof(desc));
456     desc.dwSize = sizeof(desc);
457     desc.dwCaps = 0;
458     desc.dwFVF = D3DFVF_XYZ;
459     desc.dwNumVertices = 16;
460     /* Msdn says that the last parameter must be 0 - check that */
461     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
462     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
463     if (!lpVBufDest2)
464     {
465         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
466         goto out;
467     }
468
469     rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
470     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
471     if(!in) goto out;
472
473     /* Check basic transformation */
474
475     in[0].x = 0.0;
476     in[0].y = 0.0;
477     in[0].z = 0.0;
478
479     in[1].x = 1.0;
480     in[1].y = 1.0;
481     in[1].z = 1.0;
482
483     in[2].x = -1.0;
484     in[2].y = -1.0;
485     in[2].z = 0.5;
486
487     in[3].x = 0.5;
488     in[3].y = -0.5;
489     in[3].z = 0.25;
490     rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
491     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
492
493     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
494     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
495
496     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
497     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
498
499     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
500     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
501     if(!out) goto out;
502
503     /* Check the results */
504     ok( comparefloat(out[0].x, 128.0 ) &&
505         comparefloat(out[0].y, 128.0 ) &&
506         comparefloat(out[0].z, 0.0 ) &&
507         comparefloat(out[0].rhw, 1.0 ),
508         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
509
510     ok( comparefloat(out[1].x, 256.0 ) &&
511         comparefloat(out[1].y, 0.0 ) &&
512         comparefloat(out[1].z, 1.0 ) &&
513         comparefloat(out[1].rhw, 1.0 ),
514         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
515
516     ok( comparefloat(out[2].x, 0.0 ) &&
517         comparefloat(out[2].y, 256.0 ) &&
518         comparefloat(out[2].z, 0.5 ) &&
519         comparefloat(out[2].rhw, 1.0 ),
520         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
521
522     ok( comparefloat(out[3].x, 192.0 ) &&
523         comparefloat(out[3].y, 192.0 ) &&
524         comparefloat(out[3].z, 0.25 ) &&
525         comparefloat(out[3].rhw, 1.0 ),
526         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
527
528     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
529     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
530     out = NULL;
531
532     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
533     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
534     if(!out2) goto out;
535     /* Small thing without much practical meaning, but I stumbled upon it,
536      * so let's check for it: If the output vertex buffer has to RHW value,
537      * The RHW value of the last vertex is written into the next vertex
538      */
539     ok( comparefloat(out2[4].x, 1.0 ) &&
540         comparefloat(out2[4].y, 0.0 ) &&
541         comparefloat(out2[4].z, 0.0 ),
542         "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
543
544     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
545     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
546     out = NULL;
547
548     /* Try a more complicated viewport, same vertices */
549     memset(&vp, 0, sizeof(vp));
550     vp.dwX = 10;
551     vp.dwY = 5;
552     vp.dwWidth = 246;
553     vp.dwHeight = 130;
554     vp.dvMinZ = -2.0;
555     vp.dvMaxZ = 4.0;
556     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
557     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
558
559     /* Process again */
560     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
561     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
562
563     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
564     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
565     if(!out) goto out;
566
567     /* Check the results */
568     ok( comparefloat(out[0].x, 133.0 ) &&
569         comparefloat(out[0].y, 70.0 ) &&
570         comparefloat(out[0].z, -2.0 ) &&
571         comparefloat(out[0].rhw, 1.0 ),
572         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
573
574     ok( comparefloat(out[1].x, 256.0 ) &&
575         comparefloat(out[1].y, 5.0 ) &&
576         comparefloat(out[1].z, 4.0 ) &&
577         comparefloat(out[1].rhw, 1.0 ),
578         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
579
580     ok( comparefloat(out[2].x, 10.0 ) &&
581         comparefloat(out[2].y, 135.0 ) &&
582         comparefloat(out[2].z, 1.0 ) &&
583         comparefloat(out[2].rhw, 1.0 ),
584         "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
585
586     ok( comparefloat(out[3].x, 194.5 ) &&
587         comparefloat(out[3].y, 102.5 ) &&
588         comparefloat(out[3].z, -0.5 ) &&
589         comparefloat(out[3].rhw, 1.0 ),
590         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
591
592     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
593     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
594     out = NULL;
595
596     /* Play with some matrices. */
597
598     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
599     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
600
601     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
602     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
603
604     rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
605     ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
606
607     rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
608     ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
609
610     rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
611     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
612     if(!out) goto out;
613
614     /* Keep the viewport simpler, otherwise we get bad numbers to compare */
615     vp.dwX = 0;
616     vp.dwY = 0;
617     vp.dwWidth = 100;
618     vp.dwHeight = 100;
619     vp.dvMinZ = 1.0;
620     vp.dvMaxZ = 0.0;
621     rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
622     ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
623
624     /* Check the results */
625     ok( comparefloat(out[0].x, 256.0 ) &&    /* X coordinate is cut at the surface edges */
626         comparefloat(out[0].y, 70.0 ) &&
627         comparefloat(out[0].z, -2.0 ) &&
628         comparefloat(out[0].rhw, (1.0 / 3.0)),
629         "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
630
631     ok( comparefloat(out[1].x, 256.0 ) &&
632         comparefloat(out[1].y, 78.125000 ) &&
633         comparefloat(out[1].z, -2.750000 ) &&
634         comparefloat(out[1].rhw, 0.125000 ),
635         "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
636
637     ok( comparefloat(out[2].x, 256.0 ) &&
638         comparefloat(out[2].y, 44.000000 ) &&
639         comparefloat(out[2].z, 0.400000 ) &&
640         comparefloat(out[2].rhw, 0.400000 ),
641         "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
642
643     ok( comparefloat(out[3].x, 256.0 ) &&
644         comparefloat(out[3].y, 81.818184 ) &&
645         comparefloat(out[3].z, -3.090909 ) &&
646         comparefloat(out[3].rhw, 0.363636 ),
647         "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
648
649     rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
650     ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
651     out = NULL;
652
653 out:
654     IDirect3DVertexBuffer7_Release(lpVBufSrc);
655     IDirect3DVertexBuffer7_Release(lpVBufDest1);
656     IDirect3DVertexBuffer7_Release(lpVBufDest2);
657 }
658
659 static void StateTest( void )
660 {
661     HRESULT rc;
662
663     /* The msdn says its undocumented, does it return an error too? */
664     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
665     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
666     rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
667     ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
668 }
669
670
671 static void SceneTest(void)
672 {
673     HRESULT                      hr;
674
675     /* Test an EndScene without beginscene. Should return an error */
676     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
677     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
678
679     /* Test a normal BeginScene / EndScene pair, this should work */
680     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
681     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
682     if(SUCCEEDED(hr))
683     {
684         DDBLTFX fx;
685         memset(&fx, 0, sizeof(fx));
686         fx.dwSize = sizeof(fx);
687
688         if(lpDDSdepth) {
689             hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
690             ok(hr == D3D_OK, "Depthfill failed in a BeginScene / EndScene pair\n");
691         } else {
692             skip("Depth stencil creation failed at startup, skipping\n");
693         }
694         hr = IDirect3DDevice7_EndScene(lpD3DDevice);
695         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
696     }
697
698     /* Test another EndScene without having begun a new scene. Should return an error */
699     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
700     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
701
702     /* Two nested BeginScene and EndScene calls */
703     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
704     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
705     hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
706     ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
707     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
708     ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
709     hr = IDirect3DDevice7_EndScene(lpD3DDevice);
710     ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
711
712     /* TODO: Verify that blitting works in the same way as in d3d9 */
713 }
714
715 static void LimitTest(void)
716 {
717     IDirectDrawSurface7 *pTexture = NULL;
718     HRESULT hr;
719     int i;
720     DDSURFACEDESC2 ddsd;
721
722     memset(&ddsd, 0, sizeof(ddsd));
723     ddsd.dwSize = sizeof(ddsd);
724     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
725     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
726     ddsd.dwWidth = 16;
727     ddsd.dwHeight = 16;
728     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
729     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
730     if(!pTexture) return;
731
732     for(i = 0; i < 8; i++) {
733         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
734         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
735         hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
736         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
737         hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
738         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
739     }
740
741     IDirectDrawSurface7_Release(pTexture);
742 }
743
744 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
745 {
746     UINT ver = *((UINT *) ctx);
747     if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
748     {
749         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
750            "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
751         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
752            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
753         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
754            "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
755         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
756            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
757
758         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
759            "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
760         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
761            "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
762         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
763            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
764         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
765            "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
766     }
767     else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
768     {
769         /* pow2 is hardware dependent */
770
771         ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
772            "HAL Device %d hal line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
773         ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
774            "HAL Device %d hal tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
775         ok((hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
776            "HAL Device %d hel line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
777         ok((hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
778            "HAL Device %d hel tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
779     }
780     else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
781     {
782         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
783            "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
784         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
785            "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
786         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
787            "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
788         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
789            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
790
791         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
792            "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
793         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
794            "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
795         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
796            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
797         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
798            "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
799     }
800     else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
801     {
802         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
803            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
804         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
805            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
806         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
807            "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
808         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
809            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
810
811         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
812            "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
813         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
814            "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
815         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
816            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
817         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
818            "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
819     }
820     else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
821     {
822         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
823            "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
824         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
825            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
826         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
827            "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
828         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
829            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
830
831         ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
832            "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
833         ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
834            "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
835         ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
836            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
837         ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
838            "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
839     }
840     else
841     {
842         ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
843         if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
844         else trace("hal line does NOT have pow2 set\n");
845         if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
846         else trace("hal tri does NOT have pow2 set\n");
847         if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
848         else trace("hel line does NOT have pow2 set\n");
849         if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
850         else trace("hel tri does NOT have pow2 set\n");
851     }
852     return DDENUMRET_OK;
853 }
854
855 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
856 {
857     D3D7ETest *d3d7et = Context;
858     if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
859         d3d7et->rgb++;
860     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
861         d3d7et->hal++;
862     else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
863         d3d7et->tnlhal++;
864     else
865         d3d7et->unk++;
866
867     d3d7et->total++;
868
869     return DDENUMRET_OK;
870 }
871
872
873 /*  Check the deviceGUID of devices enumerated by
874     IDirect3D7_EnumDevices. */
875 static void D3D7EnumTest(void)
876 {
877     D3D7ETest d3d7et;
878
879     if (!lpD3D) {
880         skip("No Direct3D7 interface.\n");
881         return;
882     }
883
884     memset(&d3d7et, 0, sizeof(d3d7et));
885     IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et);
886
887     /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
888     ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
889
890     /* We make two additional assumptions. */
891     ok(d3d7et.rgb, "No RGB Device enumerated.\n");
892
893     if(d3d7et.tnlhal)
894         ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
895 }
896
897 static void CapsTest(void)
898 {
899     IDirect3D3 *d3d3;
900     IDirect3D3 *d3d2;
901     IDirectDraw *dd1;
902     HRESULT hr;
903     UINT ver;
904
905     hr = DirectDrawCreate(NULL, &dd1, NULL);
906     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
907     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
908     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
909     ver = 3;
910     IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
911
912     IDirect3D3_Release(d3d3);
913     IDirectDraw_Release(dd1);
914
915     hr = DirectDrawCreate(NULL, &dd1, NULL);
916     ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
917     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
918     ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
919     ver = 2;
920     IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
921
922     IDirect3D2_Release(d3d2);
923     IDirectDraw_Release(dd1);
924 }
925
926 struct v_in {
927     float x, y, z;
928 };
929 struct v_out {
930     float x, y, z, rhw;
931 };
932
933 static BOOL D3D1_createObjects(void)
934 {
935     HRESULT hr;
936     DDSURFACEDESC ddsd;
937     D3DEXECUTEBUFFERDESC desc;
938     D3DVIEWPORT vp_data;
939
940     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
941     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
942     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
943     if (!DirectDraw1) {
944         return FALSE;
945     }
946
947     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
948     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
949
950     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
951     if (hr == E_NOINTERFACE) return FALSE;
952     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
953     if (!Direct3D1) {
954         return FALSE;
955     }
956
957     memset(&ddsd, 0, sizeof(ddsd));
958     ddsd.dwSize = sizeof(ddsd);
959     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
960     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
961     ddsd.dwWidth = 256;
962     ddsd.dwHeight = 256;
963     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
964     if (!Surface1) {
965         skip("DDSCAPS_3DDEVICE surface not available\n");
966         return FALSE;
967     }
968
969     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
970     ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
971     if(!Direct3DDevice1) {
972         return FALSE;
973     }
974
975     memset(&desc, 0, sizeof(desc));
976     desc.dwSize = sizeof(desc);
977     desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
978     desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
979     desc.dwBufferSize = 128;
980     desc.lpData = NULL;
981     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
982     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
983     if(!ExecuteBuffer) {
984         return FALSE;
985     }
986
987     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
988     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
989     if(!Viewport) {
990         return FALSE;
991     }
992
993     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
994     ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
995
996     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
997     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
998     vp_data.dwSize = sizeof(vp_data);
999     vp_data.dwX = 0;
1000     vp_data.dwY = 0;
1001     vp_data.dwWidth = 256;
1002     vp_data.dwHeight = 256;
1003     vp_data.dvScaleX = 1;
1004     vp_data.dvScaleY = 1;
1005     vp_data.dvMaxX = 256;
1006     vp_data.dvMaxY = 256;
1007     vp_data.dvMinZ = 0;
1008     vp_data.dvMaxZ = 1;
1009     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1010     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1011
1012     hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1013     ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1014     if (!Light)
1015         return FALSE;
1016
1017     return TRUE;
1018 }
1019
1020 static void D3D1_releaseObjects(void)
1021 {
1022     if (Light) IDirect3DLight_Release(Light);
1023     if (Viewport) IDirect3DViewport_Release(Viewport);
1024     if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1025     if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1026     if (Surface1) IDirectDrawSurface_Release(Surface1);
1027     if (Direct3D1) IDirect3D_Release(Direct3D1);
1028     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1029 }
1030
1031 #define SET_VP_DATA(vp_data) \
1032     vp_data.dwSize = sizeof(vp_data); \
1033     vp_data.dwX = 0; \
1034     vp_data.dwY = 0; \
1035     vp_data.dwWidth = 256; \
1036     vp_data.dwHeight = 256; \
1037     vp_data.dvMaxX = 256; \
1038     vp_data.dvMaxY = 256; \
1039     vp_data.dvScaleX = 5; \
1040     vp_data.dvScaleY = 5; \
1041     vp_data.dvMinZ = -25; \
1042     vp_data.dvMaxZ = 60;
1043
1044 static void Direct3D1Test(void)
1045 {
1046     HRESULT hr;
1047     D3DEXECUTEBUFFERDESC desc;
1048     D3DVIEWPORT vp_data;
1049     D3DINSTRUCTION *instr;
1050     D3DBRANCH *branch;
1051     IDirect3D *Direct3D_alt;
1052     IDirect3DLight *d3dlight;
1053     ULONG refcount;
1054     unsigned int idx = 0;
1055     static struct v_in testverts[] = {
1056         {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
1057         {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1058     };
1059     static struct v_in cliptest[] = {
1060         {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
1061         {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1062     };
1063     static struct v_in offscreentest[] = {
1064         {128.1, 0.0, 0.0},
1065     };
1066     struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1067     D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1068     D3DTRANSFORMDATA transformdata;
1069     DWORD i = FALSE;
1070
1071     /* Interface consistency check. */
1072     hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1073     ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1074     if (hr == D3D_OK)
1075         ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1076
1077     memset(&desc, 0, sizeof(desc));
1078     desc.dwSize = sizeof(desc);
1079     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1080     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1081
1082     memset(desc.lpData, 0, 128);
1083     instr = desc.lpData;
1084     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1085     instr[idx].bSize = sizeof(*branch);
1086     instr[idx].wCount = 1;
1087     idx++;
1088     branch = (D3DBRANCH *) &instr[idx];
1089     branch->dwMask = 0x0;
1090     branch->dwValue = 1;
1091     branch->bNegate = TRUE;
1092     branch->dwOffset = 0;
1093     idx += (sizeof(*branch) / sizeof(*instr));
1094     instr[idx].bOpcode = D3DOP_EXIT;
1095     instr[idx].bSize = 0;
1096     instr[idx].wCount = 0;
1097     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1098     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1099
1100     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1101     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1102
1103     memset(&desc, 0, sizeof(desc));
1104     desc.dwSize = sizeof(desc);
1105
1106     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1107     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1108
1109     memset(desc.lpData, 0, 128);
1110     instr = desc.lpData;
1111     idx = 0;
1112     instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1113     instr[idx].bSize = sizeof(*branch);
1114     instr[idx].wCount = 1;
1115     idx++;
1116     branch = (D3DBRANCH *) &instr[idx];
1117     branch->dwMask = 0x0;
1118     branch->dwValue = 1;
1119     branch->bNegate = TRUE;
1120     branch->dwOffset = 64;
1121     instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1122     instr[0].bOpcode = D3DOP_EXIT;
1123     instr[0].bSize = 0;
1124     instr[0].wCount = 0;
1125     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1126     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1127
1128     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1129     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1130
1131     /* Test rendering 0 triangles */
1132     memset(&desc, 0, sizeof(desc));
1133     desc.dwSize = sizeof(desc);
1134
1135     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1136     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1137
1138     memset(desc.lpData, 0, 128);
1139     instr = desc.lpData;
1140     idx = 0;
1141
1142     instr->bOpcode = D3DOP_TRIANGLE;
1143     instr->bSize = sizeof(D3DOP_TRIANGLE);
1144     instr->wCount = 0;
1145     instr++;
1146     instr->bOpcode = D3DOP_EXIT;
1147     instr->bSize = 0;
1148     instr->wCount = 0;
1149     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1150     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1151
1152     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1153     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1154
1155     memset(&transformdata, 0, sizeof(transformdata));
1156     transformdata.dwSize = sizeof(transformdata);
1157     transformdata.lpIn = testverts;
1158     transformdata.dwInSize = sizeof(testverts[0]);
1159     transformdata.lpOut = out;
1160     transformdata.dwOutSize = sizeof(out[0]);
1161
1162     transformdata.lpHOut = NULL;
1163     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1164                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1165                                              &i);
1166     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1167
1168     transformdata.lpHOut = outH;
1169     memset(outH, 0xcc, sizeof(outH));
1170     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1171                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1172                                              &i);
1173     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1174     ok(i == 0, "Offscreen is %d\n", i);
1175
1176     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1177         static const struct v_out cmp[] = {
1178             {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
1179             {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
1180         };
1181
1182         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1183            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1184            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1185            out[i].x, out[i].y, out[i].z, out[i].rhw,
1186            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1187     }
1188     for(i = 0; i < sizeof(outH); i++) {
1189         if(((unsigned char *) outH)[i] != 0xcc) {
1190             ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1191             break;
1192         }
1193     }
1194
1195     SET_VP_DATA(vp_data);
1196     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1197     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1198     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1199                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1200                                              &i);
1201     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1202     ok(i == 0, "Offscreen is %d\n", i);
1203
1204     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1205         static const struct v_out cmp[] = {
1206             {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
1207             {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
1208         };
1209         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1210            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1211            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1212            out[i].x, out[i].y, out[i].z, out[i].rhw,
1213            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1214     }
1215
1216     SET_VP_DATA(vp_data);
1217     vp_data.dwX = 10;
1218     vp_data.dwY = 20;
1219     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1220     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1221     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1222                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1223                                              &i);
1224     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1225     ok(i == 0, "Offscreen is %d\n", i);
1226     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1227         static const struct v_out cmp[] = {
1228             {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
1229             {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
1230         };
1231         ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1232            cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1233            "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1234            out[i].x, out[i].y, out[i].z, out[i].rhw,
1235            cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1236     }
1237
1238     memset(out, 0xcc, sizeof(out));
1239     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1240                                              &transformdata, D3DTRANSFORM_CLIPPED,
1241                                              &i);
1242     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1243     ok(i == 0, "Offscreen is %d\n", i);
1244     for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1245         static const D3DHVERTEX cmpH[] = {
1246             {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1247             {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1248             {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1249         };
1250         ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1251            U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1252            "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1253            outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1254            cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1255
1256         /* No scheme has been found behind those return values. It seems to be
1257          * whatever data windows has when throwing the vertex away. Modify the
1258          * input test vertices to test this more. Depending on the input data
1259          * it can happen that the z coord gets written into y, or similar things
1260          */
1261         if(0)
1262         {
1263             static const struct v_out cmp[] = {
1264                 {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
1265                 {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1266             };
1267             ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1268                cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1269                 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1270                out[i].x, out[i].y, out[i].z, out[i].rhw,
1271                cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1272         }
1273     }
1274     for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1275         ok(((DWORD *) out)[i] != 0xcccccccc,
1276                 "Regular output DWORD %d remained untouched\n", i);
1277     }
1278
1279     transformdata.lpIn = cliptest;
1280     transformdata.dwInSize = sizeof(cliptest[0]);
1281     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1282                                              &transformdata, D3DTRANSFORM_CLIPPED,
1283                                              &i);
1284     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1285     ok(i == 0, "Offscreen is %d\n", i);
1286     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1287         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1288         {
1289             0,
1290             0,
1291             D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
1292             D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1293         };
1294         ok(Flags[i] == outH[i].dwFlags,
1295            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1296            outH[i].dwFlags, Flags[i]);
1297     }
1298
1299     SET_VP_DATA(vp_data);
1300     vp_data.dwWidth = 10;
1301     vp_data.dwHeight = 1000;
1302     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1303     i = 10;
1304     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1305     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[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(cliptest) / sizeof(cliptest[0]); i++) {
1311         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1312         {
1313             D3DCLIP_RIGHT,
1314             D3DCLIP_LEFT,
1315             D3DCLIP_RIGHT | D3DCLIP_BACK,
1316             D3DCLIP_LEFT  | D3DCLIP_FRONT,
1317         };
1318         ok(Flags[i] == outH[i].dwFlags,
1319            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1320            outH[i].dwFlags, Flags[i]);
1321     }
1322
1323     SET_VP_DATA(vp_data);
1324     vp_data.dwWidth = 256;
1325     vp_data.dwHeight = 256;
1326     vp_data.dvScaleX = 1;
1327     vp_data.dvScaleY = 1;
1328     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1329     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1330     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1331                                              &transformdata, D3DTRANSFORM_CLIPPED,
1332                                              &i);
1333     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1334     ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1335     for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1336         DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1337         {
1338             0,
1339             0,
1340             D3DCLIP_BACK,
1341             D3DCLIP_FRONT,
1342         };
1343         ok(Flags[i] == outH[i].dwFlags,
1344            "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1345            outH[i].dwFlags, Flags[i]);
1346     }
1347
1348     /* Finally try to figure out how the DWORD dwOffscreen works.
1349      * Apparently no vertex is offscreen with clipping off,
1350      * and with clipping on the offscreen flag is set if only one vertex
1351      * is transformed, and this vertex is offscreen.
1352      */
1353     SET_VP_DATA(vp_data);
1354     vp_data.dwWidth = 5;
1355     vp_data.dwHeight = 5;
1356     vp_data.dvScaleX = 10000;
1357     vp_data.dvScaleY = 10000;
1358     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1359     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1360     transformdata.lpIn = cliptest;
1361     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1362                                              &transformdata, D3DTRANSFORM_UNCLIPPED,
1363                                              &i);
1364     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1365     ok(i == 0, "Offscreen is %d\n", i);
1366     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1367                                              &transformdata, D3DTRANSFORM_CLIPPED,
1368                                              &i);
1369     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1370     ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1371     hr = IDirect3DViewport_TransformVertices(Viewport, 2,
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     transformdata.lpIn = cliptest + 1;
1377     hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1378                                              &transformdata, D3DTRANSFORM_CLIPPED,
1379                                              &i);
1380     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1381     ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1382
1383     transformdata.lpIn = offscreentest;
1384     transformdata.dwInSize = sizeof(offscreentest[0]);
1385     SET_VP_DATA(vp_data);
1386     vp_data.dwWidth = 257;
1387     vp_data.dwHeight = 257;
1388     vp_data.dvScaleX = 1;
1389     vp_data.dvScaleY = 1;
1390     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1391     i = 12345;
1392     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1393                                              &transformdata, D3DTRANSFORM_CLIPPED,
1394                                              &i);
1395     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1396     ok(i == 0, "Offscreen is %d\n", i);
1397     vp_data.dwWidth = 256;
1398     vp_data.dwHeight = 256;
1399     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1400     i = 12345;
1401     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1402                                              &transformdata, D3DTRANSFORM_CLIPPED,
1403                                              &i);
1404     ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1405     ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1406
1407     hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1408                                              &transformdata, 0,
1409                                              &i);
1410     ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1411
1412     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1413     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1414
1415     hr = IDirect3DViewport_AddLight(Viewport, Light);
1416     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1417     refcount = getRefcount((IUnknown*) Light);
1418     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1419
1420     hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1421     ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1422     ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1423     refcount = getRefcount((IUnknown*) Light);
1424     ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1425
1426     hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1427     ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1428     refcount = getRefcount((IUnknown*) Light);
1429     ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1430
1431     IDirect3DLight_Release(Light);
1432 }
1433
1434 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1435 {
1436     int i;
1437
1438     for (i = 0; i < 256; i++) {
1439        if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1440            table1[i].peBlue != table2[i].peBlue) return FALSE;
1441     }
1442
1443     return TRUE;
1444 }
1445
1446 /* test palette handling in IDirect3DTexture_Load */
1447 static void TextureLoadTest(void)
1448 {
1449     IDirectDrawSurface *TexSurface = NULL;
1450     IDirect3DTexture *Texture = NULL;
1451     IDirectDrawSurface *TexSurface2 = NULL;
1452     IDirect3DTexture *Texture2 = NULL;
1453     IDirectDrawPalette *palette = NULL;
1454     IDirectDrawPalette *palette2 = NULL;
1455     IDirectDrawPalette *palette_tmp = NULL;
1456     PALETTEENTRY table1[256], table2[256], table_tmp[256];
1457     HRESULT hr;
1458     DDSURFACEDESC ddsd;
1459     int i;
1460
1461     memset (&ddsd, 0, sizeof (ddsd));
1462     ddsd.dwSize = sizeof (ddsd);
1463     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1464     ddsd.dwHeight = 128;
1465     ddsd.dwWidth = 128;
1466     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1467     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1468     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1469     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1470
1471     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1472     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1473     if (FAILED(hr)) {
1474         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1475         goto cleanup;
1476     }
1477
1478     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1479                 (void *)&Texture);
1480     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1481     if (FAILED(hr)) {
1482         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1483         goto cleanup;
1484     }
1485
1486     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1487     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1488     if (FAILED(hr)) {
1489         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1490         goto cleanup;
1491     }
1492
1493     hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1494                 (void *)&Texture2);
1495     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1496     if (FAILED(hr)) {
1497         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1498         goto cleanup;
1499     }
1500
1501     /* test load of Texture to Texture */
1502     hr = IDirect3DTexture_Load(Texture, Texture);
1503     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1504
1505     /* test Load when both textures have no palette */
1506     hr = IDirect3DTexture_Load(Texture2, Texture);
1507     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1508
1509     for (i = 0; i < 256; i++) {
1510         table1[i].peRed = i;
1511         table1[i].peGreen = i;
1512         table1[i].peBlue = i;
1513         table1[i].peFlags = 0;
1514     }
1515
1516     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1517     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1518     if (FAILED(hr)) {
1519         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1520         goto cleanup;
1521     }
1522
1523     /* test Load when source texture has palette and destination has no palette */
1524     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1525     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1526     hr = IDirect3DTexture_Load(Texture2, Texture);
1527     ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1528
1529     for (i = 0; i < 256; i++) {
1530         table2[i].peRed = 255 - i;
1531         table2[i].peGreen = 255 - i;
1532         table2[i].peBlue = 255 - i;
1533         table2[i].peFlags = 0;
1534     }
1535
1536     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1537     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1538     if (FAILED(hr)) {
1539         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1540         goto cleanup;
1541     }
1542
1543     /* test Load when source has no palette and destination has a palette */
1544     hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1545     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1546     hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1547     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1548     hr = IDirect3DTexture_Load(Texture2, Texture);
1549     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1550     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1551     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1552     if (!palette_tmp) {
1553         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1554         goto cleanup;
1555     } else {
1556         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1557         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1558         ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1559         IDirectDrawPalette_Release(palette_tmp);
1560     }
1561
1562     /* test Load when both textures have palettes */
1563     hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1564     ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1565     hr = IDirect3DTexture_Load(Texture2, Texture);
1566     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1567     hr = IDirect3DTexture_Load(Texture2, Texture);
1568     ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1569     hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1570     ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1571     if (!palette_tmp) {
1572         skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1573         goto cleanup;
1574     } else {
1575         hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1576         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1577         ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1578         IDirectDrawPalette_Release(palette_tmp);
1579     }
1580
1581     cleanup:
1582
1583     if (palette) IDirectDrawPalette_Release(palette);
1584     if (palette2) IDirectDrawPalette_Release(palette2);
1585     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1586     if (Texture) IDirect3DTexture_Release(Texture);
1587     if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1588     if (Texture2) IDirect3DTexture_Release(Texture2);
1589 }
1590
1591 static void VertexBufferDescTest(void)
1592 {
1593     HRESULT rc;
1594     D3DVERTEXBUFFERDESC desc;
1595     union mem_t
1596     {
1597         D3DVERTEXBUFFERDESC desc2;
1598         unsigned char buffer[512];
1599     } mem;
1600
1601     memset(&desc, 0, sizeof(desc));
1602     desc.dwSize = sizeof(desc);
1603     desc.dwCaps = 0;
1604     desc.dwFVF = D3DFVF_XYZ;
1605     desc.dwNumVertices = 1;
1606     rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1607     ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1608     if (!lpVBufSrc)
1609     {
1610         trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1611         goto out;
1612     }
1613
1614     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1615     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1616     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1617     if(rc != D3D_OK)
1618         skip("GetVertexBuffer Failed!\n");
1619     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1620     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1621     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1622     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1623     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1624
1625     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1626     mem.desc2.dwSize = 0;
1627     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1628     if(rc != D3D_OK)
1629         skip("GetVertexBuffer Failed!\n");
1630     ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1631     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1632     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1633     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1634     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1635
1636     memset(mem.buffer, 0x12, sizeof(mem.buffer));
1637     mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1638     rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1639     if(rc != D3D_OK)
1640         skip("GetVertexBuffer Failed!\n");
1641     ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1642     ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1643     ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1644     ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1645     ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1646
1647 out:
1648     IDirect3DVertexBuffer7_Release(lpVBufSrc);
1649 }
1650
1651 static void D3D7_OldRenderStateTest(void)
1652 {
1653     HRESULT rc;
1654     DWORD val;
1655
1656     /* Test reaction to some deprecated states in D3D7.
1657
1658      * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1659      * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1660      * need not to be handled in D3D7.
1661      */
1662     todo_wine {
1663         rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1664         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1665
1666         rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1667         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1668
1669         rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1670         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1671
1672         rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1673         ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1674     }
1675 }
1676
1677 #define IS_VALUE_NEAR(a, b)    ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1678 #define MIN(a, b)    ((a) < (b) ? (a) : (b))
1679
1680 static void DeviceLoadTest(void)
1681 {
1682     DDSURFACEDESC2 ddsd;
1683     IDirectDrawSurface7 *texture_levels[2][8];
1684     IDirectDrawSurface7 *cube_face_levels[2][6][8];
1685     DWORD flags;
1686     HRESULT hr;
1687     DDBLTFX ddbltfx;
1688     RECT loadrect;
1689     POINT loadpoint;
1690     int i, i1, i2;
1691     unsigned diff_count = 0, diff_count2 = 0;
1692     unsigned x, y;
1693     BOOL load_mip_subset_broken = FALSE;
1694     IDirectDrawPalette *palettes[5];
1695     PALETTEENTRY table1[256];
1696     DDCOLORKEY ddckey;
1697     D3DDEVICEDESC7 d3dcaps;
1698
1699     /* Test loading of texture subrectangle with a mipmap surface. */
1700     memset(texture_levels, 0, sizeof(texture_levels));
1701     memset(cube_face_levels, 0, sizeof(cube_face_levels));
1702     memset(palettes, 0, sizeof(palettes));
1703
1704     for (i = 0; i < 2; i++)
1705     {
1706         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1707         ddsd.dwSize = sizeof(ddsd);
1708         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1709         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1710         ddsd.dwWidth = 128;
1711         ddsd.dwHeight = 128;
1712         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1713         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1714         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1715         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1716         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1717         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1718         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1719         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1720         if (FAILED(hr)) goto out;
1721
1722         /* Check the number of created mipmaps */
1723         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1724         ddsd.dwSize = sizeof(ddsd);
1725         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1726         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1727         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1728         if (U2(ddsd).dwMipMapCount != 8) goto out;
1729
1730         for (i1 = 1; i1 < 8; i1++)
1731         {
1732             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1733             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1734             if (FAILED(hr)) goto out;
1735         }
1736     }
1737
1738     for (i1 = 0; i1 < 8; i1++)
1739     {
1740         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1741         ddsd.dwSize = sizeof(ddsd);
1742         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1743         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1744         if (FAILED(hr)) goto out;
1745
1746         for (y = 0 ; y < ddsd.dwHeight; y++)
1747         {
1748             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1749
1750             for (x = 0; x < ddsd.dwWidth;  x++)
1751             {
1752                 /* x stored in green component, y in blue. */
1753                 DWORD color = 0xff0000 | (x << 8)  | y;
1754                 *textureRow++ = color;
1755             }
1756         }
1757
1758         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1759         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1760     }
1761
1762     for (i1 = 0; i1 < 8; i1++)
1763     {
1764         memset(&ddbltfx, 0, sizeof(ddbltfx));
1765         ddbltfx.dwSize = sizeof(ddbltfx);
1766         U5(ddbltfx).dwFillColor = 0;
1767         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1768         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1769     }
1770
1771     /* First test some broken coordinates. */
1772     loadpoint.x = loadpoint.y = 0;
1773     loadrect.left = 0;
1774     loadrect.top = 0;
1775     loadrect.right = 0;
1776     loadrect.bottom = 0;
1777     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1778     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1779
1780     loadpoint.x = loadpoint.y = 50;
1781     loadrect.left = 0;
1782     loadrect.top = 0;
1783     loadrect.right = 100;
1784     loadrect.bottom = 100;
1785     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1786     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1787
1788     /* Test actual loading. */
1789     loadpoint.x = loadpoint.y = 31;
1790     loadrect.left = 30;
1791     loadrect.top = 20;
1792     loadrect.right = 93;
1793     loadrect.bottom = 52;
1794
1795     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1796     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1797
1798     for (i1 = 0; i1 < 8; i1++)
1799     {
1800         diff_count = 0;
1801         diff_count2 = 0;
1802
1803         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1804         ddsd.dwSize = sizeof(ddsd);
1805         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1806         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1807         if (FAILED(hr)) goto out;
1808
1809         for (y = 0 ; y < ddsd.dwHeight; y++)
1810         {
1811             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1812
1813             for (x = 0; x < ddsd.dwWidth;  x++)
1814             {
1815                 DWORD color = *textureRow++;
1816
1817                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1818                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1819                 {
1820                     if (color & 0xffffff) diff_count++;
1821                 }
1822                 else
1823                 {
1824                     DWORD r = (color & 0xff0000) >> 16;
1825                     DWORD g = (color & 0xff00) >> 8;
1826                     DWORD b = (color & 0xff);
1827
1828                     if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1829                 }
1830
1831                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1832                    technically be correct as it's not precisely defined by docs. */
1833                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1834                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1835                 {
1836                     if (color & 0xffffff) diff_count2++;
1837                 }
1838                 else
1839                 {
1840                     DWORD r = (color & 0xff0000) >> 16;
1841                     DWORD g = (color & 0xff00) >> 8;
1842                     DWORD b = (color & 0xff);
1843
1844                     if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1845                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1846                 }
1847             }
1848         }
1849
1850         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1851         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1852
1853         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1854                 MIN(diff_count, diff_count2), i1);
1855
1856         loadpoint.x /= 2;
1857         loadpoint.y /= 2;
1858         loadrect.top /= 2;
1859         loadrect.left /= 2;
1860         loadrect.right = (loadrect.right + 1) / 2;
1861         loadrect.bottom = (loadrect.bottom + 1) / 2;
1862     }
1863
1864     /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1865      * qemu Win98 / directx7 / RGB software rasterizer):
1866      * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1867     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1868     */
1869
1870     /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1871     for (i = 0; i < 2; i++)
1872     {
1873         for (i1 = 7; i1 >= 0; i1--)
1874         {
1875             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1876         }
1877     }
1878     memset(texture_levels, 0, sizeof(texture_levels));
1879
1880     /* Test texture size mismatch. */
1881     for (i = 0; i < 2; i++)
1882     {
1883         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1884         ddsd.dwSize = sizeof(ddsd);
1885         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1886         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1887         ddsd.dwWidth = i ? 256 : 128;
1888         ddsd.dwHeight = 128;
1889         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1890         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1891         if (FAILED(hr)) goto out;
1892     }
1893
1894     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1895     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1896
1897     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1898     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1899
1900     IDirectDrawSurface7_Release(texture_levels[0][0]);
1901     IDirectDrawSurface7_Release(texture_levels[1][0]);
1902     memset(texture_levels, 0, sizeof(texture_levels));
1903
1904     memset(&d3dcaps, 0, sizeof(d3dcaps));
1905     hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1906     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1907
1908     if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1909     {
1910         skip("No cubemap support\n");
1911     }
1912     else
1913     {
1914         /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1915         for (i = 0; i < 2; i++)
1916         {
1917             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1918             ddsd.dwSize = sizeof(ddsd);
1919             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1920             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1921             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1922             ddsd.dwWidth = 128;
1923             ddsd.dwHeight = 128;
1924             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1925             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1926             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1927             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1928             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1929             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1930             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1931             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1932             if (FAILED(hr)) goto out;
1933
1934             flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1935             for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1936             {
1937                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1938                 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1939                 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1940                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1941                 if (FAILED(hr)) goto out;
1942             }
1943
1944             for (i1 = 0; i1 < 6; i1++)
1945             {
1946                 /* Check the number of created mipmaps */
1947                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1948                 ddsd.dwSize = sizeof(ddsd);
1949                 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1950                 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1951                 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1952                 if (U2(ddsd).dwMipMapCount != 8) goto out;
1953
1954                 for (i2 = 1; i2 < 8; i2++)
1955                 {
1956                     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1957                     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1958                     hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1959                     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1960                     if (FAILED(hr)) goto out;
1961                 }
1962             }
1963         }
1964
1965         for (i = 0; i < 6; i++)
1966             for (i1 = 0; i1 < 8; i1++)
1967             {
1968                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1969                 ddsd.dwSize = sizeof(ddsd);
1970                 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1971                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1972                 if (FAILED(hr)) goto out;
1973
1974                 for (y = 0 ; y < ddsd.dwHeight; y++)
1975                 {
1976                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1977
1978                     for (x = 0; x < ddsd.dwWidth;  x++)
1979                     {
1980                         /* face number in low 4 bits of red, x stored in green component, y in blue. */
1981                         DWORD color = 0xf00000 | (i << 16) | (x << 8)  | y;
1982                         *textureRow++ = color;
1983                     }
1984                 }
1985
1986                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1987                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1988             }
1989
1990         for (i = 0; i < 6; i++)
1991             for (i1 = 0; i1 < 8; i1++)
1992             {
1993                 memset(&ddbltfx, 0, sizeof(ddbltfx));
1994                 ddbltfx.dwSize = sizeof(ddbltfx);
1995                 U5(ddbltfx).dwFillColor = 0;
1996                 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1997                 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1998             }
1999
2000         loadpoint.x = loadpoint.y = 10;
2001         loadrect.left = 30;
2002         loadrect.top = 20;
2003         loadrect.right = 93;
2004         loadrect.bottom = 52;
2005
2006         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2007                                         DDSCAPS2_CUBEMAP_ALLFACES);
2008         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2009
2010         for (i = 0; i < 6; i++)
2011         {
2012             loadpoint.x = loadpoint.y = 10;
2013             loadrect.left = 30;
2014             loadrect.top = 20;
2015             loadrect.right = 93;
2016             loadrect.bottom = 52;
2017
2018             for (i1 = 0; i1 < 8; i1++)
2019             {
2020                 diff_count = 0;
2021                 diff_count2 = 0;
2022
2023                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2024                 ddsd.dwSize = sizeof(ddsd);
2025                 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2026                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2027                 if (FAILED(hr)) goto out;
2028
2029                 for (y = 0 ; y < ddsd.dwHeight; y++)
2030                 {
2031                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2032
2033                     for (x = 0; x < ddsd.dwWidth;  x++)
2034                     {
2035                         DWORD color = *textureRow++;
2036
2037                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2038                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2039                         {
2040                             if (color & 0xffffff) diff_count++;
2041                         }
2042                         else
2043                         {
2044                             DWORD r = (color & 0xff0000) >> 16;
2045                             DWORD g = (color & 0xff00) >> 8;
2046                             DWORD b = (color & 0xff);
2047
2048                             if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2049                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2050                         }
2051
2052                         /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2053                         technically be correct as it's not precisely defined by docs. */
2054                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2055                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2056                         {
2057                             if (color & 0xffffff) diff_count2++;
2058                         }
2059                         else
2060                         {
2061                             DWORD r = (color & 0xff0000) >> 16;
2062                             DWORD g = (color & 0xff00) >> 8;
2063                             DWORD b = (color & 0xff);
2064
2065                             if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2066                                 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2067                         }
2068                     }
2069                 }
2070
2071                 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2072                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2073
2074                 ok(diff_count == 0 || diff_count2 == 0,
2075                     "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2076                     MIN(diff_count, diff_count2), i, i1);
2077
2078                 loadpoint.x /= 2;
2079                 loadpoint.y /= 2;
2080                 loadrect.top /= 2;
2081                 loadrect.left /= 2;
2082                 loadrect.right = (loadrect.right + 1) / 2;
2083                 loadrect.bottom = (loadrect.bottom + 1) / 2;
2084             }
2085         }
2086
2087         for (i = 0; i < 2; i++)
2088             for (i1 = 5; i1 >= 0; i1--)
2089                 for (i2 = 7; i2 >= 0; i2--)
2090                 {
2091                     if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2092                 }
2093         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2094
2095         /* Test cubemap loading from regular texture. */
2096         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2097         ddsd.dwSize = sizeof(ddsd);
2098         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2099         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2100         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2101         ddsd.dwWidth = 128;
2102         ddsd.dwHeight = 128;
2103         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2104         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2105         if (FAILED(hr)) goto out;
2106
2107         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2108         ddsd.dwSize = sizeof(ddsd);
2109         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2110         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2111         ddsd.dwWidth = 128;
2112         ddsd.dwHeight = 128;
2113         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2114         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2115         if (FAILED(hr)) goto out;
2116
2117         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2118                                         DDSCAPS2_CUBEMAP_ALLFACES);
2119         ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2120
2121         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2122         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2123         IDirectDrawSurface7_Release(texture_levels[0][0]);
2124         memset(texture_levels, 0, sizeof(texture_levels));
2125
2126         /* Test cubemap loading from cubemap with different number of faces. */
2127         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2128         ddsd.dwSize = sizeof(ddsd);
2129         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2130         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2131         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2132         ddsd.dwWidth = 128;
2133         ddsd.dwHeight = 128;
2134         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2135         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2136         if (FAILED(hr)) goto out;
2137
2138         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2139         ddsd.dwSize = sizeof(ddsd);
2140         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2141         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2142         ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2143         ddsd.dwWidth = 128;
2144         ddsd.dwHeight = 128;
2145         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2146         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2147         if (FAILED(hr)) goto out;
2148
2149         /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2150             (the above created cubemaps will have all faces. */
2151         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2152                                         DDSCAPS2_CUBEMAP_ALLFACES);
2153         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2154
2155         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2156                                         DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2157         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2158
2159         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2160                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2161         todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2162
2163         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2164                                         DDSCAPS2_CUBEMAP_ALLFACES);
2165         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2166
2167         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2168                                         DDSCAPS2_CUBEMAP_POSITIVEX);
2169         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2170
2171         hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2172                                         DDSCAPS2_CUBEMAP_POSITIVEZ);
2173         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2174
2175         IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2176         IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2177         memset(cube_face_levels, 0, sizeof(cube_face_levels));
2178     }
2179
2180     /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2181     for (i = 0; i < 2; i++)
2182     {
2183         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2184         ddsd.dwSize = sizeof(ddsd);
2185         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2186         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2187         ddsd.dwWidth = 128;
2188         ddsd.dwHeight = 128;
2189         U2(ddsd).dwMipMapCount = i ? 4 : 8;
2190         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2191         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2192         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2193         U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2194         U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2195         U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2196         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2197         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2198         if (FAILED(hr)) goto out;
2199
2200         /* Check the number of created mipmaps */
2201         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2202         ddsd.dwSize = sizeof(ddsd);
2203         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2204         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2205         ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2206         if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2207
2208         for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2209         {
2210             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2211             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2212             if (FAILED(hr)) goto out;
2213         }
2214     }
2215
2216     for (i1 = 0; i1 < 8; i1++)
2217     {
2218         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2219         ddsd.dwSize = sizeof(ddsd);
2220         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2221         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2222         if (FAILED(hr)) goto out;
2223
2224         for (y = 0 ; y < ddsd.dwHeight; y++)
2225         {
2226             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2227
2228             for (x = 0; x < ddsd.dwWidth;  x++)
2229             {
2230                 /* x stored in green component, y in blue. */
2231                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2232                 *textureRow++ = color;
2233             }
2234         }
2235
2236         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2237         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2238     }
2239
2240     for (i1 = 0; i1 < 4; i1++)
2241     {
2242         memset(&ddbltfx, 0, sizeof(ddbltfx));
2243         ddbltfx.dwSize = sizeof(ddbltfx);
2244         U5(ddbltfx).dwFillColor = 0;
2245         hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2246         ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2247     }
2248
2249     loadpoint.x = loadpoint.y = 31;
2250     loadrect.left = 30;
2251     loadrect.top = 20;
2252     loadrect.right = 93;
2253     loadrect.bottom = 52;
2254
2255     /* Destination mip levels are a subset of source mip levels. */
2256     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2257     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2258
2259     for (i1 = 0; i1 < 4; i1++)
2260     {
2261         diff_count = 0;
2262         diff_count2 = 0;
2263
2264         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2265         ddsd.dwSize = sizeof(ddsd);
2266         hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2267         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2268         if (FAILED(hr)) goto out;
2269
2270         for (y = 0 ; y < ddsd.dwHeight; y++)
2271         {
2272             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2273
2274             for (x = 0; x < ddsd.dwWidth;  x++)
2275             {
2276                 DWORD color = *textureRow++;
2277
2278                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2279                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2280                 {
2281                     if (color & 0xffffff) diff_count++;
2282                 }
2283                 else
2284                 {
2285                     DWORD r = (color & 0xff0000) >> 16;
2286                     DWORD g = (color & 0xff00) >> 8;
2287                     DWORD b = (color & 0xff);
2288
2289                     if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2290                         b != y + loadrect.top - loadpoint.y) diff_count++;
2291                 }
2292
2293                 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2294                 technically be correct as it's not precisely defined by docs. */
2295                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2296                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2297                 {
2298                     if (color & 0xffffff) diff_count2++;
2299                 }
2300                 else
2301                 {
2302                     DWORD r = (color & 0xff0000) >> 16;
2303                     DWORD g = (color & 0xff00) >> 8;
2304                     DWORD b = (color & 0xff);
2305
2306                     if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2307                         !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2308                 }
2309             }
2310         }
2311
2312         hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2313         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2314
2315         ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2316              MIN(diff_count, diff_count2), i1);
2317
2318         loadpoint.x /= 2;
2319         loadpoint.y /= 2;
2320         loadrect.top /= 2;
2321         loadrect.left /= 2;
2322         loadrect.right = (loadrect.right + 1) / 2;
2323         loadrect.bottom = (loadrect.bottom + 1) / 2;
2324     }
2325
2326     /* Destination mip levels are a superset of source mip levels (should fail). */
2327     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2328     ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2329
2330     for (i = 0; i < 2; i++)
2331     {
2332         for (i1 = 7; i1 >= 0; i1--)
2333         {
2334             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2335         }
2336     }
2337     memset(texture_levels, 0, sizeof(texture_levels));
2338
2339     /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2340     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2341     ddsd.dwSize = sizeof(ddsd);
2342     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2343     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2344     ddsd.dwWidth = 128;
2345     ddsd.dwHeight = 128;
2346     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2347     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2348     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2349     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2350     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2351     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2352     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2353     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2354     if (FAILED(hr)) goto out;
2355
2356     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2357     ddsd.dwSize = sizeof(ddsd);
2358     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2359     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2360     ddsd.dwWidth = 32;
2361     ddsd.dwHeight = 32;
2362     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2363     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2364     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2365     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2366     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2367     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2368     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2369     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2370     if (FAILED(hr)) goto out;
2371
2372     for (i1 = 1; i1 < 8; i1++)
2373     {
2374         hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2375         ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2376         if (FAILED(hr)) goto out;
2377     }
2378
2379     for (i1 = 0; i1 < 8; i1++)
2380     {
2381         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2382         ddsd.dwSize = sizeof(ddsd);
2383         hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2384         ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2385         if (FAILED(hr)) goto out;
2386
2387         for (y = 0 ; y < ddsd.dwHeight; y++)
2388         {
2389             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2390
2391             for (x = 0; x < ddsd.dwWidth;  x++)
2392             {
2393                 /* x stored in green component, y in blue. */
2394                 DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2395                 *textureRow++ = color;
2396             }
2397         }
2398
2399         hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2400         ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2401     }
2402
2403     memset(&ddbltfx, 0, sizeof(ddbltfx));
2404     ddbltfx.dwSize = sizeof(ddbltfx);
2405     U5(ddbltfx).dwFillColor = 0;
2406     hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2407     ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2408
2409     loadpoint.x = loadpoint.y = 32;
2410     loadrect.left = 32;
2411     loadrect.top = 32;
2412     loadrect.right = 96;
2413     loadrect.bottom = 96;
2414
2415     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2416     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2417
2418     loadpoint.x /= 4;
2419     loadpoint.y /= 4;
2420     loadrect.top /= 4;
2421     loadrect.left /= 4;
2422     loadrect.right = (loadrect.right + 3) / 4;
2423     loadrect.bottom = (loadrect.bottom + 3) / 4;
2424
2425     /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2426      * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2427      * copied subrectangles divided more than needed, without apparent logic. But it works
2428      * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2429      * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2430      * The following code attempts to detect broken results, actual tests will then be skipped
2431      */
2432     load_mip_subset_broken = TRUE;
2433     diff_count = 0;
2434
2435     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2436     ddsd.dwSize = sizeof(ddsd);
2437     hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2438     ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2439     if (FAILED(hr)) goto out;
2440
2441     for (y = 0 ; y < ddsd.dwHeight; y++)
2442     {
2443         DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2444
2445         for (x = 0; x < ddsd.dwWidth;  x++)
2446         {
2447             DWORD color = *textureRow++;
2448
2449             if (x < 2 || x >= 2 + 4 ||
2450                 y < 2 || y >= 2 + 4)
2451             {
2452                 if (color & 0xffffff) diff_count++;
2453             }
2454             else
2455             {
2456                 DWORD r = (color & 0xff0000) >> 16;
2457
2458                 if ((r & (0xf0)) != 0xf0) diff_count++;
2459             }
2460         }
2461     }
2462
2463     if (diff_count) load_mip_subset_broken = FALSE;
2464
2465     if (load_mip_subset_broken) {
2466         skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2467     } else {
2468         diff_count = 0;
2469
2470         for (y = 0 ; y < ddsd.dwHeight; y++)
2471         {
2472             DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2473
2474             for (x = 0; x < ddsd.dwWidth;  x++)
2475             {
2476                 DWORD color = *textureRow++;
2477
2478                 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2479                     y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2480                 {
2481                     if (color & 0xffffff) diff_count++;
2482                 }
2483                 else
2484                 {
2485                     DWORD r = (color & 0xff0000) >> 16;
2486                     DWORD g = (color & 0xff00) >> 8;
2487                     DWORD b = (color & 0xff);
2488
2489                     if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2490                         b != y + loadrect.top - loadpoint.y) diff_count++;
2491                 }
2492             }
2493         }
2494     }
2495
2496     hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2497     ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2498
2499     ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2500
2501     for (i = 0; i < 2; i++)
2502     {
2503         for (i1 = 7; i1 >= 0; i1--)
2504         {
2505             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2506         }
2507     }
2508     memset(texture_levels, 0, sizeof(texture_levels));
2509
2510     if (!load_mip_subset_broken)
2511     {
2512         /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2513         * surface (than first source mip level)
2514         */
2515         for (i = 0; i < 2; i++)
2516         {
2517             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2518             ddsd.dwSize = sizeof(ddsd);
2519             ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2520             if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2521             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2522             ddsd.dwWidth = i ? 32 : 128;
2523             ddsd.dwHeight = i ? 32 : 128;
2524             if (i) U2(ddsd).dwMipMapCount = 4;
2525             U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2526             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2527             U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2528             U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2529             U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2530             U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2531             hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2532             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2533             if (FAILED(hr)) goto out;
2534
2535             /* Check the number of created mipmaps */
2536             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2537             ddsd.dwSize = sizeof(ddsd);
2538             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2539             ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2540             ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2541             if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2542
2543             for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2544             {
2545                 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2546                 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2547                 if (FAILED(hr)) goto out;
2548             }
2549         }
2550
2551         for (i1 = 0; i1 < 8; i1++)
2552         {
2553             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2554             ddsd.dwSize = sizeof(ddsd);
2555             hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2556             ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2557             if (FAILED(hr)) goto out;
2558
2559             for (y = 0 ; y < ddsd.dwHeight; y++)
2560             {
2561                 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2562
2563                 for (x = 0; x < ddsd.dwWidth;  x++)
2564                 {
2565                     /* x stored in green component, y in blue. */
2566                     DWORD color = 0xf00000 | (i1 << 16) | (x << 8)  | y;
2567                     *textureRow++ = color;
2568                 }
2569             }
2570
2571             hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2572             ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2573         }
2574
2575         for (i1 = 0; i1 < 4; i1++)
2576         {
2577             memset(&ddbltfx, 0, sizeof(ddbltfx));
2578             ddbltfx.dwSize = sizeof(ddbltfx);
2579             U5(ddbltfx).dwFillColor = 0;
2580             hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2581             ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2582         }
2583
2584         loadpoint.x = loadpoint.y = 0;
2585         loadrect.left = 0;
2586         loadrect.top = 0;
2587         loadrect.right = 64;
2588         loadrect.bottom = 64;
2589
2590         hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2591         ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2592
2593         i = 0;
2594         for (i1 = 0; i1 < 8 && i < 4; i1++)
2595         {
2596             DDSURFACEDESC2 ddsd2;
2597
2598             memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2599             ddsd.dwSize = sizeof(ddsd);
2600             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2601
2602             memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2603             ddsd2.dwSize = sizeof(ddsd2);
2604             hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2605
2606             if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2607             {
2608                 diff_count = 0;
2609
2610                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2611                 ddsd.dwSize = sizeof(ddsd);
2612                 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2613                 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2614                 if (FAILED(hr)) goto out;
2615
2616                 for (y = 0 ; y < ddsd.dwHeight; y++)
2617                 {
2618                     DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2619
2620                     for (x = 0; x < ddsd.dwWidth;  x++)
2621                     {
2622                         DWORD color = *textureRow++;
2623
2624                         if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2625                             y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2626                         {
2627                             if (color & 0xffffff) diff_count++;
2628                         }
2629                         else
2630                         {
2631                             DWORD r = (color & 0xff0000) >> 16;
2632                             DWORD g = (color & 0xff00) >> 8;
2633                             DWORD b = (color & 0xff);
2634
2635                             if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2636                                 b != y + loadrect.top - loadpoint.y) diff_count++;
2637                         }
2638                     }
2639                 }
2640
2641                 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2642                 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2643
2644                 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2645
2646                 i++;
2647             }
2648
2649             loadpoint.x /= 2;
2650             loadpoint.y /= 2;
2651             loadrect.top /= 2;
2652             loadrect.left /= 2;
2653             loadrect.right = (loadrect.right + 1) / 2;
2654             loadrect.bottom = (loadrect.bottom + 1) / 2;
2655         }
2656
2657         for (i = 0; i < 2; i++)
2658         {
2659             for (i1 = 7; i1 >= 0; i1--)
2660             {
2661                 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2662             }
2663         }
2664         memset(texture_levels, 0, sizeof(texture_levels));
2665     }
2666
2667     /* Test palette copying. */
2668     for (i = 0; i < 2; i++)
2669     {
2670         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2671         ddsd.dwSize = sizeof(ddsd);
2672         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2673         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2674         ddsd.dwWidth = 128;
2675         ddsd.dwHeight = 128;
2676         U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2677         U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2678         U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2679         hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2680         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2681         if (FAILED(hr)) goto out;
2682
2683         /* Check the number of created mipmaps */
2684         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2685         ddsd.dwSize = sizeof(ddsd);
2686         hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2687         ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2688         ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2689         if (U2(ddsd).dwMipMapCount != 8) goto out;
2690
2691         for (i1 = 1; i1 < 8; i1++)
2692         {
2693             hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2694             ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2695             if (FAILED(hr)) goto out;
2696         }
2697     }
2698
2699     memset(table1, 0, sizeof(table1));
2700     for (i = 0; i < 3; i++)
2701     {
2702         table1[0].peBlue = i + 1;
2703         hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2704         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2705         if (FAILED(hr))
2706         {
2707             skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2708             goto out;
2709         }
2710     }
2711
2712     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2713     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2714
2715     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2716     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2717
2718     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2719     ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2720
2721     hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2722     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2723     hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2724     ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2725
2726     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2727     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2728
2729     memset(table1, 0, sizeof(table1));
2730     hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2731     ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2732     if (SUCCEEDED(hr))
2733     {
2734         hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2735         ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2736         ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2737     }
2738
2739     /* Test colorkey copying. */
2740     ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2741     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2742     ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2743     hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2744     todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2745
2746     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2747     ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2748
2749     hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2750     ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2751
2752     hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2753     ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2754     ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2755         "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2756
2757     out:
2758
2759     for (i = 0; i < 5; i++)
2760     {
2761         if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2762     }
2763
2764     for (i = 0; i < 2; i++)
2765     {
2766         for (i1 = 7; i1 >= 0; i1--)
2767         {
2768             if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2769         }
2770     }
2771
2772     for (i = 0; i < 2; i++)
2773         for (i1 = 5; i1 >= 0; i1--)
2774             for (i2 = 7; i2 >= 0; i2--)
2775             {
2776                 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2777             }
2778 }
2779
2780 static void SetMaterialTest(void)
2781 {
2782     HRESULT rc;
2783
2784     rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2785     ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2786 }
2787
2788 static void ComputeSphereVisibility(void)
2789 {
2790     D3DMATRIX proj, view, world;
2791     D3DVALUE radius[3];
2792     D3DVECTOR center[3];
2793     DWORD result[3];
2794     HRESULT rc;
2795
2796     world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2797     world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2798     world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2799     world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2800
2801     view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2802     view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2803     view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2804     view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2805
2806     proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2807     proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2808     proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2809     proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2810
2811     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2812     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2813     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2814
2815     U1(center[0]).x=11.461533;
2816     U2(center[0]).y=-4.761727;
2817     U3(center[0]).z=-1.171646;
2818
2819     radius[0]=38.252632;
2820
2821     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2822
2823     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2824     ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2825
2826     U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
2827     radius[0]=4.354097;
2828     U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
2829     radius[1]=12.500704;
2830     U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
2831     radius[2]=17.251318;
2832
2833     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2834
2835     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2836     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2837     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2838     ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2839     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2840     ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2841
2842     view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2843     view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2844     view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2845     view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2846
2847     proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2848     proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2849     proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2850     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2851
2852     U1(center[0]).x=0.0;
2853     U2(center[0]).y=0.0;
2854     U3(center[0]).z=0.05;
2855
2856     radius[0]=0.04;
2857
2858     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2859     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2860
2861     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2862
2863     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2864     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2865
2866     proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2867     proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2868     proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2869     proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2870
2871     IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2872
2873     U1(center[0]).x=0.0;
2874     U2(center[0]).y=0.0;
2875     U3(center[0]).z=0.5;
2876
2877     radius[0]=0.5;
2878
2879     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2880
2881     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2882     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2883
2884     U1(center[0]).x=0.0;
2885     U2(center[0]).y=0.0;
2886     U3(center[0]).z=0.0;
2887
2888     radius[0]=0.0;
2889
2890     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2891
2892     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2893     ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2894
2895     U1(center[0]).x=-1.0;
2896     U2(center[0]).y=-1.0;
2897     U3(center[0]).z=0.50;
2898
2899     radius[0]=0.25;
2900
2901     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2902
2903     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2904     ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
2905
2906     U1(center[0]).x=-20.0;
2907     U2(center[0]).y=0.0;
2908     U3(center[0]).z=0.50;
2909
2910     radius[0]=3.0;
2911
2912     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2913
2914     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2915     ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2916
2917     U1(center[0]).x=20.0;
2918     U2(center[0]).y=0.0;
2919     U3(center[0]).z=0.50;
2920
2921     radius[0]=3.0f;
2922
2923     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2924
2925     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2926     ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
2927
2928     U1(center[0]).x=0.0;
2929     U2(center[0]).y=-20.0;
2930     U3(center[0]).z=0.50;
2931
2932     radius[0]=3.0;
2933
2934     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2935
2936     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2937     ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
2938
2939     U1(center[0]).x=0.0;
2940     U2(center[0]).y=20.0;
2941     U3(center[0]).z=0.5;
2942
2943     radius[0]=3.0;
2944
2945     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2946
2947     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2948     ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
2949
2950     U1(center[0]).x=0.0;
2951     U2(center[0]).y=0.0;
2952     U3(center[0]).z=-20;
2953
2954     radius[0]=3.0;
2955
2956     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2957
2958     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2959     ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
2960
2961     U1(center[0]).x=0.0;
2962     U2(center[0]).y=0.0;
2963     U3(center[0]).z=20.0;
2964
2965     radius[0]=3.0;
2966
2967     rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2968
2969     ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2970     ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
2971 }
2972
2973 static void SetRenderTargetTest(void)
2974 {
2975     HRESULT hr;
2976     IDirectDrawSurface7 *newrt, *oldrt;
2977     D3DVIEWPORT7 vp;
2978     DDSURFACEDESC2 ddsd;
2979     DWORD stateblock;
2980
2981     memset(&ddsd, 0, sizeof(ddsd));
2982     ddsd.dwSize = sizeof(ddsd);
2983     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2984     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
2985     ddsd.dwWidth = 64;
2986     ddsd.dwHeight = 64;
2987     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
2988     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
2989     if(FAILED(hr))
2990     {
2991         skip("Skipping SetRenderTarget test\n");
2992         return;
2993     }
2994
2995     memset(&vp, 0, sizeof(vp));
2996     vp.dwX = 10;
2997     vp.dwY = 10;
2998     vp.dwWidth = 246;
2999     vp.dwHeight = 246;
3000     vp.dvMinZ = 0.25;
3001     vp.dvMaxZ = 0.75;
3002     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3003     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3004
3005     hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3006     ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3007
3008     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3009     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3010     memset(&vp, 0xff, sizeof(vp));
3011     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3012     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3013     ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3014     ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3015     ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3016     ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3017     ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.1\n", vp.dvMinZ);
3018     ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.9\n", vp.dvMaxZ);
3019
3020     memset(&vp, 0, sizeof(vp));
3021     vp.dwX = 0;
3022     vp.dwY = 0;
3023     vp.dwWidth = 64;
3024     vp.dwHeight = 64;
3025     vp.dvMinZ = 0.0;
3026     vp.dvMaxZ = 1.0;
3027     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3028     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3029
3030     hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3031     ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3032     hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3033     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3034
3035     /* Check this twice, before and after ending the stateblock */
3036     memset(&vp, 0xff, sizeof(vp));
3037     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3038     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3039     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3040     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3041     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3042     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3043     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3044     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3045
3046     hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3047     ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3048
3049     memset(&vp, 0xff, sizeof(vp));
3050     hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3051     ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3052     ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3053     ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3054     ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3055     ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3056     ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3057     ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3058
3059     hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3060     ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3061
3062     memset(&vp, 0, sizeof(vp));
3063     vp.dwX = 0;
3064     vp.dwY = 0;
3065     vp.dwWidth = 256;
3066     vp.dwHeight = 256;
3067     vp.dvMinZ = 0.0;
3068     vp.dvMaxZ = 0.0;
3069     hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3070     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3071
3072     IDirectDrawSurface7_Release(oldrt);
3073     IDirectDrawSurface7_Release(newrt);
3074 }
3075
3076 START_TEST(d3d)
3077 {
3078     init_function_pointers();
3079     if(!pDirectDrawCreateEx) {
3080         win_skip("function DirectDrawCreateEx not available\n");
3081         return;
3082     }
3083
3084     if(!CreateDirect3D()) {
3085         skip("Skipping d3d7 tests\n");
3086     } else {
3087         LightTest();
3088         ProcessVerticesTest();
3089         StateTest();
3090         SceneTest();
3091         LimitTest();
3092         D3D7EnumTest();
3093         SetMaterialTest();
3094         ComputeSphereVisibility();
3095         CapsTest();
3096         VertexBufferDescTest();
3097         D3D7_OldRenderStateTest();
3098         DeviceLoadTest();
3099         SetRenderTargetTest();
3100         ReleaseDirect3D();
3101     }
3102
3103     if (!D3D1_createObjects()) {
3104         skip("Skipping d3d1 tests\n");
3105     } else {
3106         Direct3D1Test();
3107         TextureLoadTest();
3108         D3D1_releaseObjects();
3109     }
3110 }