2 * Some unit tests for d3d functions
4 * Copyright (C) 2005 Antoine Chavasse
5 * Copyright (C) 2006 Stefan Dösinger for CodeWeavers
6 * Copyright (C) 2008 Alexander Dorofeyev
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.
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.
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
24 #include "wine/test.h"
29 static LPDIRECTDRAW7 lpDD = NULL;
30 static LPDIRECT3D7 lpD3D = NULL;
31 static LPDIRECTDRAWSURFACE7 lpDDS = NULL;
32 static LPDIRECTDRAWSURFACE7 lpDDSdepth = NULL;
33 static LPDIRECT3DDEVICE7 lpD3DDevice = NULL;
34 static LPDIRECT3DVERTEXBUFFER7 lpVBufSrc = NULL;
35 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest1 = NULL;
36 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest2 = NULL;
38 static IDirectDraw *DirectDraw1 = NULL;
39 static IDirectDrawSurface *Surface1 = NULL;
40 static IDirect3D *Direct3D1 = NULL;
41 static IDirect3DDevice *Direct3DDevice1 = NULL;
42 static IDirect3DExecuteBuffer *ExecuteBuffer = NULL;
43 static IDirect3DViewport *Viewport = NULL;
53 /* To compare bad floating point numbers. Not the ideal way to do it,
54 * but it should be enough for here */
55 #define comparefloat(a, b) ( (((a) - (b)) < 0.0001) && (((a) - (b)) > -0.0001) )
57 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
59 typedef struct _VERTEX
61 float x, y, z; /* position */
64 typedef struct _TVERTEX
66 float x, y, z; /* position */
68 } TVERTEX, *LPTVERTEX;
71 static void init_function_pointers(void)
73 HMODULE hmod = GetModuleHandleA("ddraw.dll");
74 pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
78 static BOOL CreateDirect3D(void)
83 rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
84 &IID_IDirectDraw7, NULL);
85 ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
87 trace("DirectDrawCreateEx() failed with an error %x\n", rc);
91 rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
92 ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
94 rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
95 if (rc == E_NOINTERFACE) return FALSE;
96 ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
98 memset(&ddsd, 0, sizeof(ddsd));
99 ddsd.dwSize = sizeof(ddsd);
100 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
101 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
104 rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
108 memset(&ddsd, 0, sizeof(ddsd));
109 ddsd.dwSize = sizeof(ddsd);
110 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
111 ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
112 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
113 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
114 U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 16;
115 U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
118 rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDSdepth, NULL);
119 ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
120 if (!SUCCEEDED(rc)) {
123 rc = IDirectDrawSurface_AddAttachedSurface(lpDDS, lpDDSdepth);
124 ok(rc == DD_OK, "IDirectDrawSurface_AddAttachedSurface returned %x\n", rc);
129 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
131 ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
133 trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
134 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
137 trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
138 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
141 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
150 static void ReleaseDirect3D(void)
152 if (lpD3DDevice != NULL)
154 IDirect3DDevice7_Release(lpD3DDevice);
158 if (lpDDSdepth != NULL)
160 IDirectDrawSurface_Release(lpDDSdepth);
166 IDirectDrawSurface_Release(lpDDS);
172 IDirect3D7_Release(lpD3D);
178 IDirectDraw_Release(lpDD);
183 static void LightTest(void)
187 D3DLIGHT7 defaultlight;
188 BOOL bEnabled = FALSE;
196 /* Set a few lights with funky indices. */
197 memset(&light, 0, sizeof(light));
198 light.dltType = D3DLIGHT_DIRECTIONAL;
199 U1(light.dcvDiffuse).r = 0.5f;
200 U2(light.dcvDiffuse).g = 0.6f;
201 U3(light.dcvDiffuse).b = 0.7f;
202 U2(light.dvDirection).y = 1.f;
204 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
205 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
206 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
207 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
208 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
209 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
212 /* Try to retrieve a light beyond the indices of the lights that have
214 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
215 ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
216 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
217 ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
220 /* Try to retrieve one of the lights that have been set */
221 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
222 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
225 /* Enable a light that have been previously set. */
226 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
227 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
230 /* Enable some lights that have not been previously set, and verify that
231 they have been initialized with proper default values. */
232 memset(&defaultlight, 0, sizeof(D3DLIGHT7));
233 defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
234 U1(defaultlight.dcvDiffuse).r = 1.f;
235 U2(defaultlight.dcvDiffuse).g = 1.f;
236 U3(defaultlight.dcvDiffuse).b = 1.f;
237 U3(defaultlight.dvDirection).z = 1.f;
239 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
240 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
241 memset(&light, 0, sizeof(D3DLIGHT7));
242 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
243 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
244 ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
245 "light data doesn't match expected default values\n" );
247 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
248 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
249 memset(&light, 0, sizeof(D3DLIGHT7));
250 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
251 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
252 ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
253 "light data doesn't match expected default values\n" );
256 /* Disable one of the light that have been previously enabled. */
257 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
258 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
260 /* Try to retrieve the enable status of some lights */
261 /* Light 20 is supposed to be disabled */
262 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
263 ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
264 ok(!bEnabled, "GetLightEnable says the light is enabled\n");
266 /* Light 10 is supposed to be enabled */
268 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
269 ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
270 ok(bEnabled, "GetLightEnable says the light is disabled\n");
272 /* Light 80 has not been set */
273 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
274 ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
276 /* Light 23 has not been set */
277 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
278 ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
280 /* Set some lights with invalid parameters */
281 memset(&light, 0, sizeof(D3DLIGHT7));
283 U1(light.dcvDiffuse).r = 1.f;
284 U2(light.dcvDiffuse).g = 1.f;
285 U3(light.dcvDiffuse).b = 1.f;
286 U3(light.dvDirection).z = 1.f;
287 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
288 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
290 memset(&light, 0, sizeof(D3DLIGHT7));
291 light.dltType = 12345;
292 U1(light.dcvDiffuse).r = 1.f;
293 U2(light.dcvDiffuse).g = 1.f;
294 U3(light.dcvDiffuse).b = 1.f;
295 U3(light.dvDirection).z = 1.f;
296 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
297 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
299 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
300 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
302 memset(&light, 0, sizeof(D3DLIGHT7));
303 light.dltType = D3DLIGHT_SPOT;
304 U1(light.dcvDiffuse).r = 1.f;
305 U2(light.dcvDiffuse).g = 1.f;
306 U3(light.dcvDiffuse).b = 1.f;
307 U3(light.dvDirection).z = 1.f;
309 light.dvAttenuation0 = -one / zero; /* -INFINITY */
310 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
311 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
313 light.dvAttenuation0 = -1.0;
314 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
315 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
317 light.dvAttenuation0 = 0.0;
318 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
319 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
321 light.dvAttenuation0 = 1.0;
322 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
323 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
325 light.dvAttenuation0 = one / zero; /* +INFINITY */
326 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
327 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
329 light.dvAttenuation0 = zero / zero; /* NaN */
330 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
332 broken(rc==DDERR_INVALIDPARAMS), "SetLight returned: %x\n", rc);
334 /* Directional light ignores attenuation */
335 light.dltType = D3DLIGHT_DIRECTIONAL;
336 light.dvAttenuation0 = -1.0;
337 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
338 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
340 memset(&mat, 0, sizeof(mat));
341 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
342 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial returned: %x\n", rc);
344 U4(mat).power = 129.0;
345 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
346 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = 129.0) returned: %x\n", rc);
347 memset(&mat, 0, sizeof(mat));
348 rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
349 ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
350 ok(U4(mat).power == 129, "Returned power is %f\n", U4(mat).power);
352 U4(mat).power = -1.0;
353 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
354 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = -1.0) returned: %x\n", rc);
355 memset(&mat, 0, sizeof(mat));
356 rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
357 ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
358 ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
360 memset(&caps, 0, sizeof(caps));
361 rc = IDirect3DDevice7_GetCaps(lpD3DDevice, &caps);
362 ok(rc == D3D_OK, "IDirect3DDevice7_GetCaps failed with %x\n", rc);
364 if ( caps.dwMaxActiveLights == (DWORD) -1) {
365 /* Some cards without T&L Support return -1 (Examples: Voodoo Banshee, RivaTNT / NV4) */
366 skip("T&L not supported\n");
370 for(i = 1; i <= caps.dwMaxActiveLights; i++) {
371 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, TRUE);
372 ok(rc == D3D_OK, "Enabling light %u failed with %x\n", i, rc);
373 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i, &enabled);
374 ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i, rc);
375 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
378 /* TODO: Test the rendering results in this situation */
379 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, TRUE);
380 ok(rc == D3D_OK, "Enabling one light more than supported returned %x\n", rc);
381 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i + 1, &enabled);
382 ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i + 1, rc);
383 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
384 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, FALSE);
385 ok(rc == D3D_OK, "Disabling the additional returned %x\n", rc);
387 for(i = 1; i <= caps.dwMaxActiveLights; i++) {
388 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, FALSE);
389 ok(rc == D3D_OK, "Disabling light %u failed with %x\n", i, rc);
393 static void ProcessVerticesTest(void)
395 D3DVERTEXBUFFERDESC desc;
401 D3DMATRIX view = { 2.0, 0.0, 0.0, 0.0,
404 0.0, 0.0, 0.0, 3.0 };
406 D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
409 0.0, 1.0, 1.0, 1.0 };
411 D3DMATRIX proj = { 1.0, 0.0, 0.0, 1.0,
414 1.0, 0.0, 0.0, 1.0 };
415 /* Create some vertex buffers */
417 memset(&desc, 0, sizeof(desc));
418 desc.dwSize = sizeof(desc);
420 desc.dwFVF = D3DFVF_XYZ;
421 desc.dwNumVertices = 16;
422 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
423 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
426 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
430 memset(&desc, 0, sizeof(desc));
431 desc.dwSize = sizeof(desc);
433 desc.dwFVF = D3DFVF_XYZRHW;
434 desc.dwNumVertices = 16;
435 /* Msdn says that the last parameter must be 0 - check that */
436 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
437 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
440 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
444 memset(&desc, 0, sizeof(desc));
445 desc.dwSize = sizeof(desc);
447 desc.dwFVF = D3DFVF_XYZ;
448 desc.dwNumVertices = 16;
449 /* Msdn says that the last parameter must be 0 - check that */
450 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
451 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
454 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
458 rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
459 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
462 /* Check basic transformation */
479 rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
480 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
482 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
483 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
485 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
486 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
488 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
489 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
492 /* Check the results */
493 ok( comparefloat(out[0].x, 128.0 ) &&
494 comparefloat(out[0].y, 128.0 ) &&
495 comparefloat(out[0].z, 0.0 ) &&
496 comparefloat(out[0].rhw, 1.0 ),
497 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
499 ok( comparefloat(out[1].x, 256.0 ) &&
500 comparefloat(out[1].y, 0.0 ) &&
501 comparefloat(out[1].z, 1.0 ) &&
502 comparefloat(out[1].rhw, 1.0 ),
503 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
505 ok( comparefloat(out[2].x, 0.0 ) &&
506 comparefloat(out[2].y, 256.0 ) &&
507 comparefloat(out[2].z, 0.5 ) &&
508 comparefloat(out[2].rhw, 1.0 ),
509 "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
511 ok( comparefloat(out[3].x, 192.0 ) &&
512 comparefloat(out[3].y, 192.0 ) &&
513 comparefloat(out[3].z, 0.25 ) &&
514 comparefloat(out[3].rhw, 1.0 ),
515 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
517 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
518 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
521 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
522 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
524 /* Small thing without much practical meaning, but I stumbled upon it,
525 * so let's check for it: If the output vertex buffer has to RHW value,
526 * The RHW value of the last vertex is written into the next vertex
528 ok( comparefloat(out2[4].x, 1.0 ) &&
529 comparefloat(out2[4].y, 0.0 ) &&
530 comparefloat(out2[4].z, 0.0 ),
531 "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
533 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
534 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
537 /* Try a more complicated viewport, same vertices */
538 memset(&vp, 0, sizeof(vp));
545 rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
546 ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
549 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
550 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
552 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
553 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
556 /* Check the results */
557 ok( comparefloat(out[0].x, 133.0 ) &&
558 comparefloat(out[0].y, 70.0 ) &&
559 comparefloat(out[0].z, -2.0 ) &&
560 comparefloat(out[0].rhw, 1.0 ),
561 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
563 ok( comparefloat(out[1].x, 256.0 ) &&
564 comparefloat(out[1].y, 5.0 ) &&
565 comparefloat(out[1].z, 4.0 ) &&
566 comparefloat(out[1].rhw, 1.0 ),
567 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
569 ok( comparefloat(out[2].x, 10.0 ) &&
570 comparefloat(out[2].y, 135.0 ) &&
571 comparefloat(out[2].z, 1.0 ) &&
572 comparefloat(out[2].rhw, 1.0 ),
573 "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
575 ok( comparefloat(out[3].x, 194.5 ) &&
576 comparefloat(out[3].y, 102.5 ) &&
577 comparefloat(out[3].z, -0.5 ) &&
578 comparefloat(out[3].rhw, 1.0 ),
579 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
581 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
582 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
585 /* Play with some matrices. */
587 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
588 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
590 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
591 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
593 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
594 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
596 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
597 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
599 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
600 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
603 /* Keep the viewport simpler, otherwise we get bad numbers to compare */
610 rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
611 ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
613 /* Check the results */
614 ok( comparefloat(out[0].x, 256.0 ) && /* X coordinate is cut at the surface edges */
615 comparefloat(out[0].y, 70.0 ) &&
616 comparefloat(out[0].z, -2.0 ) &&
617 comparefloat(out[0].rhw, (1.0 / 3.0)),
618 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
620 ok( comparefloat(out[1].x, 256.0 ) &&
621 comparefloat(out[1].y, 78.125000 ) &&
622 comparefloat(out[1].z, -2.750000 ) &&
623 comparefloat(out[1].rhw, 0.125000 ),
624 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
626 ok( comparefloat(out[2].x, 256.0 ) &&
627 comparefloat(out[2].y, 44.000000 ) &&
628 comparefloat(out[2].z, 0.400000 ) &&
629 comparefloat(out[2].rhw, 0.400000 ),
630 "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
632 ok( comparefloat(out[3].x, 256.0 ) &&
633 comparefloat(out[3].y, 81.818184 ) &&
634 comparefloat(out[3].z, -3.090909 ) &&
635 comparefloat(out[3].rhw, 0.363636 ),
636 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
638 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
639 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
643 IDirect3DVertexBuffer7_Release(lpVBufSrc);
644 IDirect3DVertexBuffer7_Release(lpVBufDest1);
645 IDirect3DVertexBuffer7_Release(lpVBufDest2);
648 static void StateTest( void )
652 /* The msdn says its undocumented, does it return an error too? */
653 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
654 ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
655 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
656 ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
660 static void SceneTest(void)
664 /* Test an EndScene without beginscene. Should return an error */
665 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
666 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
668 /* Test a normal BeginScene / EndScene pair, this should work */
669 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
670 ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
674 memset(&fx, 0, sizeof(fx));
675 fx.dwSize = sizeof(fx);
678 hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
679 ok(hr == D3D_OK, "Depthfill failed in a BeginScene / EndScene pair\n");
681 skip("Depth stencil creation failed at startup, skipping\n");
683 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
684 ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
687 /* Test another EndScene without having begun a new scene. Should return an error */
688 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
689 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
691 /* Two nested BeginScene and EndScene calls */
692 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
693 ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
694 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
695 ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
696 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
697 ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
698 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
699 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
701 /* TODO: Verify that blitting works in the same way as in d3d9 */
704 static void LimitTest(void)
706 IDirectDrawSurface7 *pTexture = NULL;
711 memset(&ddsd, 0, sizeof(ddsd));
712 ddsd.dwSize = sizeof(ddsd);
713 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
714 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
717 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
718 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
719 if(!pTexture) return;
721 for(i = 0; i < 8; i++) {
722 hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
723 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
724 hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
725 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
726 hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
727 ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
730 IDirectDrawSurface7_Release(pTexture);
733 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
735 UINT ver = *((UINT *) ctx);
736 if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
738 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
739 "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
740 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
741 "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
742 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
743 "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
744 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
745 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
747 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
748 "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
749 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
750 "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
751 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
752 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
753 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
754 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
756 else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
758 /* pow2 is hardware dependent */
760 ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
761 "HAL Device %d hal line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
762 ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
763 "HAL Device %d hal tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
764 ok((hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
765 "HAL Device %d hel line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
766 ok((hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
767 "HAL Device %d hel tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
769 else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
771 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
772 "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
773 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
774 "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
775 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
776 "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
777 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
778 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
780 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
781 "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
782 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
783 "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
784 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
785 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
786 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
787 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
789 else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
791 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
792 "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
793 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
794 "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
795 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
796 "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
797 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
798 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
800 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
801 "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
802 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
803 "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
804 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
805 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
806 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
807 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
809 else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
811 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
812 "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
813 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
814 "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
815 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
816 "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
817 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
818 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
820 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
821 "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
822 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
823 "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
824 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
825 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
826 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
827 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
831 ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
832 if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
833 else trace("hal line does NOT have pow2 set\n");
834 if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
835 else trace("hal tri does NOT have pow2 set\n");
836 if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
837 else trace("hel line does NOT have pow2 set\n");
838 if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
839 else trace("hel tri does NOT have pow2 set\n");
844 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
846 D3D7ETest *d3d7et = (D3D7ETest*)Context;
847 if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
849 else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
851 else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
862 /* Check the deviceGUID of devices enumerated by
863 IDirect3D7_EnumDevices. */
864 static void D3D7EnumTest(void)
869 skip("No Direct3D7 interface.\n");
873 memset(&d3d7et, 0, sizeof(d3d7et));
874 IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, (LPVOID) &d3d7et);
877 /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
878 ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
880 /* We make two additional assumptions. */
881 ok(d3d7et.rgb, "No RGB Device enumerated.\n");
884 ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
889 static void CapsTest(void)
897 hr = DirectDrawCreate(NULL, &dd1, NULL);
898 ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
899 hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
900 ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
902 IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
904 IDirect3D3_Release(d3d3);
905 IDirectDraw_Release(dd1);
907 hr = DirectDrawCreate(NULL, &dd1, NULL);
908 ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
909 hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
910 ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
912 IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
914 IDirect3D2_Release(d3d2);
915 IDirectDraw_Release(dd1);
925 static BOOL D3D1_createObjects(void)
929 D3DEXECUTEBUFFERDESC desc;
932 /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
933 hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
934 ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
939 hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
940 ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
942 hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
943 ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
948 memset(&ddsd, 0, sizeof(ddsd));
949 ddsd.dwSize = sizeof(ddsd);
950 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
951 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
954 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
956 skip("DDSCAPS_3DDEVICE surface not available\n");
960 hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
961 ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
962 if(!Direct3DDevice1) {
966 memset(&desc, 0, sizeof(desc));
967 desc.dwSize = sizeof(desc);
968 desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
969 desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
970 desc.dwBufferSize = 128;
972 hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
973 ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
978 hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
979 ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
984 hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
985 ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
987 hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
988 ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
989 vp_data.dwSize = sizeof(vp_data);
992 vp_data.dwWidth = 256;
993 vp_data.dwHeight = 256;
994 vp_data.dvScaleX = 1;
995 vp_data.dvScaleY = 1;
996 vp_data.dvMaxX = 256;
997 vp_data.dvMaxY = 256;
1000 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1001 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1006 static void D3D1_releaseObjects(void)
1008 if (Viewport) IDirect3DViewport_Release(Viewport);
1009 if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1010 if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1011 if (Surface1) IDirectDrawSurface_Release(Surface1);
1012 if (Direct3D1) IDirect3D_Release(Direct3D1);
1013 if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1016 #define SET_VP_DATA(vp_data) \
1017 vp_data.dwSize = sizeof(vp_data); \
1020 vp_data.dwWidth = 256; \
1021 vp_data.dwHeight = 256; \
1022 vp_data.dvMaxX = 256; \
1023 vp_data.dvMaxY = 256; \
1024 vp_data.dvScaleX = 5; \
1025 vp_data.dvScaleY = 5; \
1026 vp_data.dvMinZ = -25; \
1027 vp_data.dvMaxZ = 60;
1029 static void Direct3D1Test(void)
1032 D3DEXECUTEBUFFERDESC desc;
1033 D3DVIEWPORT vp_data;
1034 D3DINSTRUCTION *instr;
1036 unsigned int idx = 0;
1037 static struct v_in testverts[] = {
1038 {0.0, 0.0, 0.0}, { 1.0, 1.0, 1.0}, {-1.0, -1.0, -1.0},
1039 {0.5, 0.5, 0.5}, {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1041 static struct v_in cliptest[] = {
1042 {25.59, 25.59, 1.0}, {-25.59, -25.59, 0.0},
1043 {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1045 static struct v_in offscreentest[] = {
1048 struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1049 D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1050 D3DTRANSFORMDATA transformdata;
1053 memset(&desc, 0, sizeof(desc));
1054 desc.dwSize = sizeof(desc);
1055 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1056 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1058 memset(desc.lpData, 0, 128);
1059 instr = desc.lpData;
1060 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1061 instr[idx].bSize = sizeof(*branch);
1062 instr[idx].wCount = 1;
1064 branch = (D3DBRANCH *) &instr[idx];
1065 branch->dwMask = 0x0;
1066 branch->dwValue = 1;
1067 branch->bNegate = TRUE;
1068 branch->dwOffset = 0;
1069 idx += (sizeof(*branch) / sizeof(*instr));
1070 instr[idx].bOpcode = D3DOP_EXIT;
1071 instr[idx].bSize = 0;
1072 instr[idx].wCount = 0;
1073 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1074 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1076 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1077 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1079 memset(&desc, 0, sizeof(desc));
1080 desc.dwSize = sizeof(desc);
1082 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1083 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1085 memset(desc.lpData, 0, 128);
1086 instr = desc.lpData;
1088 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1089 instr[idx].bSize = sizeof(*branch);
1090 instr[idx].wCount = 1;
1092 branch = (D3DBRANCH *) &instr[idx];
1093 branch->dwMask = 0x0;
1094 branch->dwValue = 1;
1095 branch->bNegate = TRUE;
1096 branch->dwOffset = 64;
1097 instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1098 instr[0].bOpcode = D3DOP_EXIT;
1100 instr[0].wCount = 0;
1101 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1102 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1104 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1105 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1107 /* Test rendering 0 triangles */
1108 memset(&desc, 0, sizeof(desc));
1109 desc.dwSize = sizeof(desc);
1111 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1112 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1114 memset(desc.lpData, 0, 128);
1115 instr = desc.lpData;
1118 instr->bOpcode = D3DOP_TRIANGLE;
1119 instr->bSize = sizeof(D3DOP_TRIANGLE);
1121 instr = ((D3DINSTRUCTION*)(instr))+1;
1122 instr->bOpcode = D3DOP_EXIT;
1125 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1126 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1128 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1129 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1131 memset(&transformdata, 0, sizeof(transformdata));
1132 transformdata.dwSize = sizeof(transformdata);
1133 transformdata.lpIn = (void *) testverts;
1134 transformdata.dwInSize = sizeof(testverts[0]);
1135 transformdata.lpOut = out;
1136 transformdata.dwOutSize = sizeof(out[0]);
1138 transformdata.lpHOut = NULL;
1139 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1140 &transformdata, D3DTRANSFORM_UNCLIPPED,
1142 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1144 transformdata.lpHOut = outH;
1145 memset(outH, 0xcc, sizeof(outH));
1146 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1147 &transformdata, D3DTRANSFORM_UNCLIPPED,
1149 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1150 ok(i == 0, "Offscreen is %d\n", i);
1152 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1153 static const struct v_out cmp[] = {
1154 {128.0, 128.0, 0.0, 1}, {129.0, 127.0, 1.0, 1}, {127.0, 129.0, -1, 1},
1155 {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5, 0, 1}
1158 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1159 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1160 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1161 out[i].x, out[i].y, out[i].z, out[i].rhw,
1162 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1164 for(i = 0; i < sizeof(outH); i++) {
1165 if(((unsigned char *) outH)[i] != 0xcc) {
1166 ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1171 SET_VP_DATA(vp_data);
1172 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1173 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1174 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1175 &transformdata, D3DTRANSFORM_UNCLIPPED,
1177 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1178 ok(i == 0, "Offscreen is %d\n", i);
1180 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1181 static const struct v_out cmp[] = {
1182 {128.0, 128.0, 0.0, 1}, {133.0, 123.0, 1.0, 1}, {123.0, 133.0, -1, 1},
1183 {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5, 0, 1}
1185 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1186 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1187 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1188 out[i].x, out[i].y, out[i].z, out[i].rhw,
1189 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1192 SET_VP_DATA(vp_data);
1195 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1196 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1197 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1198 &transformdata, D3DTRANSFORM_UNCLIPPED,
1200 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1201 ok(i == 0, "Offscreen is %d\n", i);
1202 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1203 static const struct v_out cmp[] = {
1204 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, {133.0, 153.0, -1, 1},
1205 {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5, 0, 1}
1207 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1208 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1209 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1210 out[i].x, out[i].y, out[i].z, out[i].rhw,
1211 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1214 memset(out, 0xcc, sizeof(out));
1215 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1216 &transformdata, D3DTRANSFORM_CLIPPED,
1218 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1219 ok(i == 0, "Offscreen is %d\n", i);
1220 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1221 static const D3DHVERTEX cmpH[] = {
1222 {0, { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1223 {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1224 {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1226 ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1227 U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1228 "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1229 outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1230 cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1232 /* No scheme has been found behind those return values. It seems to be
1233 * whatever data windows has when throwing the vertex away. Modify the
1234 * input test vertices to test this more. Depending on the input data
1235 * it can happen that the z coord gets written into y, or similar things
1239 static const struct v_out cmp[] = {
1240 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, { -1.0, -1.0, 0.5, 1},
1241 {140.5, 145.5, 0.5, 1}, { -0.5, -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1243 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1244 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1245 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1246 out[i].x, out[i].y, out[i].z, out[i].rhw,
1247 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1250 for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1251 ok(((DWORD *) out)[i] != 0xcccccccc,
1252 "Regular output DWORD %d remained untouched\n", i);
1255 transformdata.lpIn = (void *) cliptest;
1256 transformdata.dwInSize = sizeof(cliptest[0]);
1257 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1258 &transformdata, D3DTRANSFORM_CLIPPED,
1260 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1261 ok(i == 0, "Offscreen is %d\n", i);
1262 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1263 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1267 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
1268 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1270 ok(Flags[i] == outH[i].dwFlags,
1271 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1272 outH[i].dwFlags, Flags[i]);
1275 SET_VP_DATA(vp_data);
1276 vp_data.dwWidth = 10;
1277 vp_data.dwHeight = 1000;
1278 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1280 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1281 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1282 &transformdata, D3DTRANSFORM_CLIPPED,
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])] =
1291 D3DCLIP_RIGHT | D3DCLIP_BACK,
1292 D3DCLIP_LEFT | D3DCLIP_FRONT,
1294 ok(Flags[i] == outH[i].dwFlags,
1295 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1296 outH[i].dwFlags, Flags[i]);
1299 SET_VP_DATA(vp_data);
1300 vp_data.dwWidth = 256;
1301 vp_data.dwHeight = 256;
1302 vp_data.dvScaleX = 1;
1303 vp_data.dvScaleY = 1;
1304 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1305 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1306 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1307 &transformdata, D3DTRANSFORM_CLIPPED,
1309 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1310 ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1311 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1312 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1319 ok(Flags[i] == outH[i].dwFlags,
1320 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1321 outH[i].dwFlags, Flags[i]);
1324 /* Finally try to figure out how the DWORD dwOffscreen works.
1325 * Apparently no vertex is offscreen with clipping off,
1326 * and with clipping on the offscreen flag is set if only one vertex
1327 * is transformed, and this vertex is offscreen.
1329 SET_VP_DATA(vp_data);
1330 vp_data.dwWidth = 5;
1331 vp_data.dwHeight = 5;
1332 vp_data.dvScaleX = 10000;
1333 vp_data.dvScaleY = 10000;
1334 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1335 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1336 transformdata.lpIn = cliptest;
1337 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1338 &transformdata, D3DTRANSFORM_UNCLIPPED,
1340 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1341 ok(i == 0, "Offscreen is %d\n", i);
1342 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1343 &transformdata, D3DTRANSFORM_CLIPPED,
1345 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1346 ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1347 hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1348 &transformdata, D3DTRANSFORM_CLIPPED,
1350 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1351 ok(i == 0, "Offscreen is %d\n", i);
1352 transformdata.lpIn = cliptest + 1;
1353 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1354 &transformdata, D3DTRANSFORM_CLIPPED,
1356 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1357 ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1359 transformdata.lpIn = (void *) offscreentest;
1360 transformdata.dwInSize = sizeof(offscreentest[0]);
1361 SET_VP_DATA(vp_data);
1362 vp_data.dwWidth = 257;
1363 vp_data.dwHeight = 257;
1364 vp_data.dvScaleX = 1;
1365 vp_data.dvScaleY = 1;
1366 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1368 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1369 &transformdata, D3DTRANSFORM_CLIPPED,
1371 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1372 ok(i == 0, "Offscreen is %d\n", i);
1373 vp_data.dwWidth = 256;
1374 vp_data.dwHeight = 256;
1375 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1377 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1378 &transformdata, D3DTRANSFORM_CLIPPED,
1380 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1381 ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1383 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1386 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1388 hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1389 ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1392 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1396 for (i = 0; i < 256; i++) {
1397 if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1398 table1[i].peBlue != table2[i].peBlue) return FALSE;
1404 /* test palette handling in IDirect3DTexture_Load */
1405 static void TextureLoadTest(void)
1407 IDirectDrawSurface *TexSurface = NULL;
1408 IDirect3DTexture *Texture = NULL;
1409 IDirectDrawSurface *TexSurface2 = NULL;
1410 IDirect3DTexture *Texture2 = NULL;
1411 IDirectDrawPalette *palette = NULL;
1412 IDirectDrawPalette *palette2 = NULL;
1413 IDirectDrawPalette *palette_tmp = NULL;
1414 PALETTEENTRY table1[256], table2[256], table_tmp[256];
1419 memset (&ddsd, 0, sizeof (ddsd));
1420 ddsd.dwSize = sizeof (ddsd);
1421 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1422 ddsd.dwHeight = 128;
1424 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1425 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1426 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1427 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1429 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1430 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1432 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1436 hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1438 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1440 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1444 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1445 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1447 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1451 hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1453 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1455 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1459 /* test load of Texture to Texture */
1460 hr = IDirect3DTexture_Load(Texture, Texture);
1461 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1463 /* test Load when both textures have no palette */
1464 hr = IDirect3DTexture_Load(Texture2, Texture);
1465 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1467 for (i = 0; i < 256; i++) {
1468 table1[i].peRed = i;
1469 table1[i].peGreen = i;
1470 table1[i].peBlue = i;
1471 table1[i].peFlags = 0;
1474 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1475 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1477 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1481 /* test Load when source texture has palette and destination has no palette */
1482 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1483 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1484 hr = IDirect3DTexture_Load(Texture2, Texture);
1485 ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1487 for (i = 0; i < 256; i++) {
1488 table2[i].peRed = 255 - i;
1489 table2[i].peGreen = 255 - i;
1490 table2[i].peBlue = 255 - i;
1491 table2[i].peFlags = 0;
1494 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1495 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1497 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1501 /* test Load when source has no palette and destination has a palette */
1502 hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1503 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1504 hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1505 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1506 hr = IDirect3DTexture_Load(Texture2, Texture);
1507 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1508 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1509 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1511 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1514 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1515 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1516 ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1517 IDirectDrawPalette_Release(palette_tmp);
1520 /* test Load when both textures have palettes */
1521 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1522 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1523 hr = IDirect3DTexture_Load(Texture2, Texture);
1524 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1525 hr = IDirect3DTexture_Load(Texture2, Texture);
1526 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1527 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1528 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1530 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1533 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1534 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1535 ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1536 IDirectDrawPalette_Release(palette_tmp);
1541 if (palette) IDirectDrawPalette_Release(palette);
1542 if (palette2) IDirectDrawPalette_Release(palette2);
1543 if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1544 if (Texture) IDirect3DTexture_Release(Texture);
1545 if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1546 if (Texture2) IDirect3DTexture_Release(Texture2);
1549 static void VertexBufferDescTest(void)
1552 D3DVERTEXBUFFERDESC desc;
1555 D3DVERTEXBUFFERDESC desc2;
1556 unsigned char buffer[512];
1559 memset(&desc, 0, sizeof(desc));
1560 desc.dwSize = sizeof(desc);
1562 desc.dwFVF = D3DFVF_XYZ;
1563 desc.dwNumVertices = 1;
1564 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1565 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1568 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1572 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1573 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1574 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1576 skip("GetVertexBuffer Failed!\n");
1577 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1578 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1579 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1580 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1581 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1583 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1584 mem.desc2.dwSize = 0;
1585 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1587 skip("GetVertexBuffer Failed!\n");
1588 ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1589 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1590 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1591 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1592 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1594 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1595 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1596 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1598 skip("GetVertexBuffer Failed!\n");
1599 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1600 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1601 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1602 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1603 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1606 IDirect3DVertexBuffer7_Release(lpVBufSrc);
1609 static void D3D7_OldRenderStateTest(void)
1614 /* Test reaction to some deprecated states in D3D7.
1616 * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1617 * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1618 * need not to be handled in D3D7.
1621 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1622 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1624 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1625 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1627 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1628 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1630 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1631 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1635 #define IS_VALUE_NEAR(a, b) ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1636 #define MIN(a, b) ((a) < (b) ? (a) : (b))
1638 static void DeviceLoadTest()
1640 DDSURFACEDESC2 ddsd;
1641 IDirectDrawSurface7 *texture_levels[2][8];
1642 IDirectDrawSurface7 *cube_face_levels[2][6][8];
1649 unsigned diff_count = 0, diff_count2 = 0;
1651 BOOL load_mip_subset_broken = FALSE;
1652 IDirectDrawPalette *palettes[5];
1653 PALETTEENTRY table1[256];
1656 /* Test loading of texture subrectangle with a mipmap surface. */
1657 memset(texture_levels, 0, sizeof(texture_levels));
1658 memset(cube_face_levels, 0, sizeof(cube_face_levels));
1659 memset(palettes, 0, sizeof(palettes));
1661 for (i = 0; i < 2; i++)
1663 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1664 ddsd.dwSize = sizeof(ddsd);
1665 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1666 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1668 ddsd.dwHeight = 128;
1669 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1670 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1671 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1672 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1673 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1674 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1675 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1676 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1677 if (FAILED(hr)) goto out;
1679 /* Check the number of created mipmaps */
1680 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1681 ddsd.dwSize = sizeof(ddsd);
1682 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1683 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1684 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1685 if (U2(ddsd).dwMipMapCount != 8) goto out;
1687 for (i1 = 1; i1 < 8; i1++)
1689 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1690 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1691 if (FAILED(hr)) goto out;
1695 for (i1 = 0; i1 < 8; i1++)
1697 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1698 ddsd.dwSize = sizeof(ddsd);
1699 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1700 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1701 if (FAILED(hr)) goto out;
1703 for (y = 0 ; y < ddsd.dwHeight; y++)
1705 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1707 for (x = 0; x < ddsd.dwWidth; x++)
1709 /* x stored in green component, y in blue. */
1710 DWORD color = 0xff0000 | (x << 8) | y;
1711 *textureRow++ = color;
1715 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1716 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1719 for (i1 = 0; i1 < 8; i1++)
1721 memset(&ddbltfx, 0, sizeof(ddbltfx));
1722 ddbltfx.dwSize = sizeof(ddbltfx);
1723 U5(ddbltfx).dwFillColor = 0;
1724 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1725 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1728 /* First test some broken coordinates. */
1729 loadpoint.x = loadpoint.y = 0;
1733 loadrect.bottom = 0;
1734 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1735 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1737 loadpoint.x = loadpoint.y = 50;
1740 loadrect.right = 100;
1741 loadrect.bottom = 100;
1742 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1743 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1745 /* Test actual loading. */
1746 loadpoint.x = loadpoint.y = 31;
1749 loadrect.right = 93;
1750 loadrect.bottom = 52;
1752 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1753 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1755 for (i1 = 0; i1 < 8; i1++)
1760 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1761 ddsd.dwSize = sizeof(ddsd);
1762 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1763 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1764 if (FAILED(hr)) goto out;
1766 for (y = 0 ; y < ddsd.dwHeight; y++)
1768 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1770 for (x = 0; x < ddsd.dwWidth; x++)
1772 DWORD color = *textureRow++;
1774 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1775 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1777 if (color & 0xffffff) diff_count++;
1781 DWORD r = (color & 0xff0000) >> 16;
1782 DWORD g = (color & 0xff00) >> 8;
1783 DWORD b = (color & 0xff);
1785 if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1788 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1789 technically be correct as it's not precisely defined by docs. */
1790 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1791 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1793 if (color & 0xffffff) diff_count2++;
1797 DWORD r = (color & 0xff0000) >> 16;
1798 DWORD g = (color & 0xff00) >> 8;
1799 DWORD b = (color & 0xff);
1801 if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1802 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1807 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1808 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1810 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1811 MIN(diff_count, diff_count2), i1);
1817 loadrect.right = (loadrect.right + 1) / 2;
1818 loadrect.bottom = (loadrect.bottom + 1) / 2;
1821 /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1822 * qemu Win98 / directx7 / RGB software rasterizer):
1823 * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1824 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1827 /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1828 for (i = 0; i < 2; i++)
1830 for (i1 = 7; i1 >= 0; i1--)
1832 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1835 memset(texture_levels, 0, sizeof(texture_levels));
1837 /* Test texture size mismatch. */
1838 for (i = 0; i < 2; i++)
1840 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1841 ddsd.dwSize = sizeof(ddsd);
1842 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1843 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1844 ddsd.dwWidth = i ? 256 : 128;
1845 ddsd.dwHeight = 128;
1846 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1847 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1848 if (FAILED(hr)) goto out;
1851 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1852 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1854 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1855 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1857 IDirectDrawSurface7_Release(texture_levels[0][0]);
1858 IDirectDrawSurface7_Release(texture_levels[1][0]);
1859 memset(texture_levels, 0, sizeof(texture_levels));
1861 /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1862 for (i = 0; i < 2; i++)
1864 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1865 ddsd.dwSize = sizeof(ddsd);
1866 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1867 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1868 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1870 ddsd.dwHeight = 128;
1871 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1872 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1873 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1874 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1875 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1876 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1877 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1878 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1879 if (FAILED(hr)) goto out;
1881 flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1882 for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1884 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1885 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1886 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1887 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1888 if (FAILED(hr)) goto out;
1891 for (i1 = 0; i1 < 6; i1++)
1893 /* Check the number of created mipmaps */
1894 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1895 ddsd.dwSize = sizeof(ddsd);
1896 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1897 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1898 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1899 if (U2(ddsd).dwMipMapCount != 8) goto out;
1901 for (i2 = 1; i2 < 8; i2++)
1903 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1904 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1905 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1906 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1907 if (FAILED(hr)) goto out;
1912 for (i = 0; i < 6; i++)
1913 for (i1 = 0; i1 < 8; i1++)
1915 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1916 ddsd.dwSize = sizeof(ddsd);
1917 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1918 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1919 if (FAILED(hr)) goto out;
1921 for (y = 0 ; y < ddsd.dwHeight; y++)
1923 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1925 for (x = 0; x < ddsd.dwWidth; x++)
1927 /* face number in low 4 bits of red, x stored in green component, y in blue. */
1928 DWORD color = 0xf00000 | (i << 16) | (x << 8) | y;
1929 *textureRow++ = color;
1933 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1934 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1937 for (i = 0; i < 6; i++)
1938 for (i1 = 0; i1 < 8; i1++)
1940 memset(&ddbltfx, 0, sizeof(ddbltfx));
1941 ddbltfx.dwSize = sizeof(ddbltfx);
1942 U5(ddbltfx).dwFillColor = 0;
1943 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1944 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1947 loadpoint.x = loadpoint.y = 10;
1950 loadrect.right = 93;
1951 loadrect.bottom = 52;
1953 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
1954 DDSCAPS2_CUBEMAP_ALLFACES);
1955 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1957 for (i = 0; i < 6; i++)
1959 loadpoint.x = loadpoint.y = 10;
1962 loadrect.right = 93;
1963 loadrect.bottom = 52;
1965 for (i1 = 0; i1 < 8; i1++)
1970 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1971 ddsd.dwSize = sizeof(ddsd);
1972 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1973 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1974 if (FAILED(hr)) goto out;
1976 for (y = 0 ; y < ddsd.dwHeight; y++)
1978 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1980 for (x = 0; x < ddsd.dwWidth; x++)
1982 DWORD color = *textureRow++;
1984 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1985 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1987 if (color & 0xffffff) diff_count++;
1991 DWORD r = (color & 0xff0000) >> 16;
1992 DWORD g = (color & 0xff00) >> 8;
1993 DWORD b = (color & 0xff);
1995 if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
1996 b != y + loadrect.top - loadpoint.y) diff_count++;
1999 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2000 technically be correct as it's not precisely defined by docs. */
2001 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2002 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2004 if (color & 0xffffff) diff_count2++;
2008 DWORD r = (color & 0xff0000) >> 16;
2009 DWORD g = (color & 0xff00) >> 8;
2010 DWORD b = (color & 0xff);
2012 if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2013 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2018 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2019 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2021 ok(diff_count == 0 || diff_count2 == 0,
2022 "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2023 MIN(diff_count, diff_count2), i, i1);
2029 loadrect.right = (loadrect.right + 1) / 2;
2030 loadrect.bottom = (loadrect.bottom + 1) / 2;
2034 for (i = 0; i < 2; i++)
2035 for (i1 = 5; i1 >= 0; i1--)
2036 for (i2 = 7; i2 >= 0; i2--)
2038 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2040 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2042 /* Test cubemap loading from regular texture. */
2043 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2044 ddsd.dwSize = sizeof(ddsd);
2045 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2046 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2047 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2049 ddsd.dwHeight = 128;
2050 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2051 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2052 if (FAILED(hr)) goto out;
2054 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2055 ddsd.dwSize = sizeof(ddsd);
2056 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2057 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2059 ddsd.dwHeight = 128;
2060 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2061 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2062 if (FAILED(hr)) goto out;
2064 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2065 DDSCAPS2_CUBEMAP_ALLFACES);
2066 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2068 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2069 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2070 IDirectDrawSurface7_Release(texture_levels[0][0]);
2071 memset(texture_levels, 0, sizeof(texture_levels));
2073 /* Test cubemap loading from cubemap with different number of faces. */
2074 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2075 ddsd.dwSize = sizeof(ddsd);
2076 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2077 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2078 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2080 ddsd.dwHeight = 128;
2081 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2082 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2083 if (FAILED(hr)) goto out;
2085 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2086 ddsd.dwSize = sizeof(ddsd);
2087 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2088 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2089 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2091 ddsd.dwHeight = 128;
2092 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2093 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2094 if (FAILED(hr)) goto out;
2096 /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2097 (the above created cubemaps will have all faces. */
2098 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2099 DDSCAPS2_CUBEMAP_ALLFACES);
2100 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2102 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2103 DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2104 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2106 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2107 DDSCAPS2_CUBEMAP_POSITIVEX);
2108 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2110 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2111 DDSCAPS2_CUBEMAP_ALLFACES);
2112 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2114 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2115 DDSCAPS2_CUBEMAP_POSITIVEX);
2116 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2118 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2119 DDSCAPS2_CUBEMAP_POSITIVEZ);
2120 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2122 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2123 IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2124 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2126 /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2127 for (i = 0; i < 2; i++)
2129 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2130 ddsd.dwSize = sizeof(ddsd);
2131 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2132 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2134 ddsd.dwHeight = 128;
2135 U2(ddsd).dwMipMapCount = i ? 4 : 8;
2136 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2137 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2138 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2139 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2140 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2141 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2142 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2143 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2144 if (FAILED(hr)) goto out;
2146 /* Check the number of created mipmaps */
2147 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2148 ddsd.dwSize = sizeof(ddsd);
2149 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2150 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2151 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2152 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2154 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2156 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2157 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2158 if (FAILED(hr)) goto out;
2162 for (i1 = 0; i1 < 8; i1++)
2164 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2165 ddsd.dwSize = sizeof(ddsd);
2166 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2167 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2168 if (FAILED(hr)) goto out;
2170 for (y = 0 ; y < ddsd.dwHeight; y++)
2172 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2174 for (x = 0; x < ddsd.dwWidth; x++)
2176 /* x stored in green component, y in blue. */
2177 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2178 *textureRow++ = color;
2182 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2183 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2186 for (i1 = 0; i1 < 4; i1++)
2188 memset(&ddbltfx, 0, sizeof(ddbltfx));
2189 ddbltfx.dwSize = sizeof(ddbltfx);
2190 U5(ddbltfx).dwFillColor = 0;
2191 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2192 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2195 loadpoint.x = loadpoint.y = 31;
2198 loadrect.right = 93;
2199 loadrect.bottom = 52;
2201 /* Destination mip levels are a subset of source mip levels. */
2202 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2203 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2205 for (i1 = 0; i1 < 4; i1++)
2210 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2211 ddsd.dwSize = sizeof(ddsd);
2212 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2213 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2214 if (FAILED(hr)) goto out;
2216 for (y = 0 ; y < ddsd.dwHeight; y++)
2218 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2220 for (x = 0; x < ddsd.dwWidth; x++)
2222 DWORD color = *textureRow++;
2224 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2225 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2227 if (color & 0xffffff) diff_count++;
2231 DWORD r = (color & 0xff0000) >> 16;
2232 DWORD g = (color & 0xff00) >> 8;
2233 DWORD b = (color & 0xff);
2235 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2236 b != y + loadrect.top - loadpoint.y) diff_count++;
2239 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2240 technically be correct as it's not precisely defined by docs. */
2241 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2242 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2244 if (color & 0xffffff) diff_count2++;
2248 DWORD r = (color & 0xff0000) >> 16;
2249 DWORD g = (color & 0xff00) >> 8;
2250 DWORD b = (color & 0xff);
2252 if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2253 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2258 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2259 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2261 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2262 MIN(diff_count, diff_count2), i1);
2268 loadrect.right = (loadrect.right + 1) / 2;
2269 loadrect.bottom = (loadrect.bottom + 1) / 2;
2272 /* Destination mip levels are a superset of source mip levels (should fail). */
2273 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2274 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2276 for (i = 0; i < 2; i++)
2278 for (i1 = 7; i1 >= 0; i1--)
2280 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2283 memset(texture_levels, 0, sizeof(texture_levels));
2285 /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2286 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2287 ddsd.dwSize = sizeof(ddsd);
2288 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2289 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2291 ddsd.dwHeight = 128;
2292 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2293 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2294 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2295 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2296 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2297 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2298 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2299 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2300 if (FAILED(hr)) goto out;
2302 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2303 ddsd.dwSize = sizeof(ddsd);
2304 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2305 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2308 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2309 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2310 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2311 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2312 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2313 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2314 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2315 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2316 if (FAILED(hr)) goto out;
2318 for (i1 = 1; i1 < 8; i1++)
2320 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2321 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2322 if (FAILED(hr)) goto out;
2325 for (i1 = 0; i1 < 8; i1++)
2327 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2328 ddsd.dwSize = sizeof(ddsd);
2329 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2330 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2331 if (FAILED(hr)) goto out;
2333 for (y = 0 ; y < ddsd.dwHeight; y++)
2335 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2337 for (x = 0; x < ddsd.dwWidth; x++)
2339 /* x stored in green component, y in blue. */
2340 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2341 *textureRow++ = color;
2345 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2346 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2349 memset(&ddbltfx, 0, sizeof(ddbltfx));
2350 ddbltfx.dwSize = sizeof(ddbltfx);
2351 U5(ddbltfx).dwFillColor = 0;
2352 hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2353 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2355 loadpoint.x = loadpoint.y = 32;
2358 loadrect.right = 96;
2359 loadrect.bottom = 96;
2361 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2362 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2368 loadrect.right = (loadrect.right + 3) / 4;
2369 loadrect.bottom = (loadrect.bottom + 3) / 4;
2371 /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2372 * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2373 * copied subrectangles divided more than needed, without apparent logic. But it works
2374 * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2375 * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2376 * The following code attempts to detect broken results, actual tests will then be skipped
2378 load_mip_subset_broken = TRUE;
2381 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2382 ddsd.dwSize = sizeof(ddsd);
2383 hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2384 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2385 if (FAILED(hr)) goto out;
2387 for (y = 0 ; y < ddsd.dwHeight; y++)
2389 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2391 for (x = 0; x < ddsd.dwWidth; x++)
2393 DWORD color = *textureRow++;
2395 if (x < 2 || x >= 2 + 4 ||
2396 y < 2 || y >= 2 + 4)
2398 if (color & 0xffffff) diff_count++;
2402 DWORD r = (color & 0xff0000) >> 16;
2404 if ((r & (0xf0)) != 0xf0) diff_count++;
2409 if (diff_count) load_mip_subset_broken = FALSE;
2411 if (load_mip_subset_broken) {
2412 skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2416 for (y = 0 ; y < ddsd.dwHeight; y++)
2418 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2420 for (x = 0; x < ddsd.dwWidth; x++)
2422 DWORD color = *textureRow++;
2424 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2425 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2427 if (color & 0xffffff) diff_count++;
2431 DWORD r = (color & 0xff0000) >> 16;
2432 DWORD g = (color & 0xff00) >> 8;
2433 DWORD b = (color & 0xff);
2435 if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2436 b != y + loadrect.top - loadpoint.y) diff_count++;
2442 hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2443 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2445 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2447 for (i = 0; i < 2; i++)
2449 for (i1 = 7; i1 >= 0; i1--)
2451 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2454 memset(texture_levels, 0, sizeof(texture_levels));
2456 if (!load_mip_subset_broken)
2458 /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2459 * surface (than first source mip level)
2461 for (i = 0; i < 2; i++)
2463 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2464 ddsd.dwSize = sizeof(ddsd);
2465 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2466 if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2467 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2468 ddsd.dwWidth = i ? 32 : 128;
2469 ddsd.dwHeight = i ? 32 : 128;
2470 if (i) U2(ddsd).dwMipMapCount = 4;
2471 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2472 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2473 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2474 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2475 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2476 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2477 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2478 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2479 if (FAILED(hr)) goto out;
2481 /* Check the number of created mipmaps */
2482 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2483 ddsd.dwSize = sizeof(ddsd);
2484 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2485 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2486 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2487 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2489 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2491 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2492 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2493 if (FAILED(hr)) goto out;
2497 for (i1 = 0; i1 < 8; i1++)
2499 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2500 ddsd.dwSize = sizeof(ddsd);
2501 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2502 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2503 if (FAILED(hr)) goto out;
2505 for (y = 0 ; y < ddsd.dwHeight; y++)
2507 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2509 for (x = 0; x < ddsd.dwWidth; x++)
2511 /* x stored in green component, y in blue. */
2512 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2513 *textureRow++ = color;
2517 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2518 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2521 for (i1 = 0; i1 < 4; i1++)
2523 memset(&ddbltfx, 0, sizeof(ddbltfx));
2524 ddbltfx.dwSize = sizeof(ddbltfx);
2525 U5(ddbltfx).dwFillColor = 0;
2526 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2527 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2530 loadpoint.x = loadpoint.y = 0;
2533 loadrect.right = 64;
2534 loadrect.bottom = 64;
2536 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2537 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2540 for (i1 = 0; i1 < 8 && i < 4; i1++)
2542 DDSURFACEDESC2 ddsd2;
2544 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2545 ddsd.dwSize = sizeof(ddsd);
2546 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2548 memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2549 ddsd2.dwSize = sizeof(ddsd2);
2550 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2552 if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2556 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2557 ddsd.dwSize = sizeof(ddsd);
2558 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2559 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2560 if (FAILED(hr)) goto out;
2562 for (y = 0 ; y < ddsd.dwHeight; y++)
2564 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2566 for (x = 0; x < ddsd.dwWidth; x++)
2568 DWORD color = *textureRow++;
2570 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2571 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2573 if (color & 0xffffff) diff_count++;
2577 DWORD r = (color & 0xff0000) >> 16;
2578 DWORD g = (color & 0xff00) >> 8;
2579 DWORD b = (color & 0xff);
2581 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2582 b != y + loadrect.top - loadpoint.y) diff_count++;
2587 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2588 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2590 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2599 loadrect.right = (loadrect.right + 1) / 2;
2600 loadrect.bottom = (loadrect.bottom + 1) / 2;
2603 for (i = 0; i < 2; i++)
2605 for (i1 = 7; i1 >= 0; i1--)
2607 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2610 memset(texture_levels, 0, sizeof(texture_levels));
2613 /* Test palette copying. */
2614 for (i = 0; i < 2; i++)
2616 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2617 ddsd.dwSize = sizeof(ddsd);
2618 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2619 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2621 ddsd.dwHeight = 128;
2622 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2623 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2624 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2625 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2626 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2627 if (FAILED(hr)) goto out;
2629 /* Check the number of created mipmaps */
2630 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2631 ddsd.dwSize = sizeof(ddsd);
2632 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2633 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2634 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2635 if (U2(ddsd).dwMipMapCount != 8) goto out;
2637 for (i1 = 1; i1 < 8; i1++)
2639 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2640 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2641 if (FAILED(hr)) goto out;
2645 memset(table1, 0, sizeof(table1));
2646 for (i = 0; i < 3; i++)
2648 table1[0].peBlue = i + 1;
2649 hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2650 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2653 skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2658 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2659 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2661 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2662 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2664 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2665 ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2667 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2668 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2669 hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2670 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2672 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2673 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2675 memset(table1, 0, sizeof(table1));
2676 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2677 ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2680 hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2681 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2682 ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2685 /* Test colorkey copying. */
2686 ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2687 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2688 ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2689 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2690 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2692 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2693 ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2695 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2696 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2698 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2699 ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2700 ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2701 "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2705 for (i = 0; i < 5; i++)
2707 if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2710 for (i = 0; i < 2; i++)
2712 for (i1 = 7; i1 >= 0; i1--)
2714 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2718 for (i = 0; i < 2; i++)
2719 for (i1 = 5; i1 >= 0; i1--)
2720 for (i2 = 7; i2 >= 0; i2--)
2722 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2728 init_function_pointers();
2729 if(!pDirectDrawCreateEx) {
2730 skip("function DirectDrawCreateEx not available\n");
2734 if(!CreateDirect3D()) {
2735 skip("Skipping d3d7 tests\n");
2738 ProcessVerticesTest();
2744 VertexBufferDescTest();
2745 D3D7_OldRenderStateTest();
2750 if (!D3D1_createObjects()) {
2751 skip("Skipping d3d1 tests\n");
2755 D3D1_releaseObjects();