push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / dlls / ddraw / tests / d3d.c
blob57e1da002d666d5abc18e43c212ae73bac3c8da0
1 /*
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
23 #define COBJMACROS
25 #include <assert.h>
26 #include "wine/test.h"
27 #include "initguid.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "unknwn.h"
32 static LPDIRECTDRAW7 lpDD = NULL;
33 static LPDIRECT3D7 lpD3D = NULL;
34 static LPDIRECTDRAWSURFACE7 lpDDS = NULL;
35 static LPDIRECTDRAWSURFACE7 lpDDSdepth = NULL;
36 static LPDIRECT3DDEVICE7 lpD3DDevice = NULL;
37 static LPDIRECT3DVERTEXBUFFER7 lpVBufSrc = NULL;
38 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest1 = NULL;
39 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest2 = NULL;
41 static IDirectDraw *DirectDraw1 = NULL;
42 static IDirectDrawSurface *Surface1 = NULL;
43 static IDirect3D *Direct3D1 = NULL;
44 static IDirect3DDevice *Direct3DDevice1 = NULL;
45 static IDirect3DExecuteBuffer *ExecuteBuffer = NULL;
46 static IDirect3DViewport *Viewport = NULL;
47 static IDirect3DLight *Light = NULL;
49 typedef struct {
50 int total;
51 int rgb;
52 int hal;
53 int tnlhal;
54 int unk;
55 } D3D7ETest;
57 /* To compare bad floating point numbers. Not the ideal way to do it,
58 * but it should be enough for here */
59 #define comparefloat(a, b) ( (((a) - (b)) < 0.0001) && (((a) - (b)) > -0.0001) )
61 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
63 typedef struct _VERTEX
65 float x, y, z; /* position */
66 } VERTEX, *LPVERTEX;
68 typedef struct _TVERTEX
70 float x, y, z; /* position */
71 float rhw;
72 } TVERTEX, *LPTVERTEX;
75 static void init_function_pointers(void)
77 HMODULE hmod = GetModuleHandleA("ddraw.dll");
78 pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
82 static ULONG getRefcount(IUnknown *iface)
84 IUnknown_AddRef(iface);
85 return IUnknown_Release(iface);
89 static BOOL CreateDirect3D(void)
91 HRESULT rc;
92 DDSURFACEDESC2 ddsd;
94 rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
95 &IID_IDirectDraw7, NULL);
96 ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
97 if (!lpDD) {
98 trace("DirectDrawCreateEx() failed with an error %x\n", rc);
99 return FALSE;
102 rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
103 ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
105 rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
106 if (rc == E_NOINTERFACE) return FALSE;
107 ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
109 memset(&ddsd, 0, sizeof(ddsd));
110 ddsd.dwSize = sizeof(ddsd);
111 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
112 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
113 ddsd.dwWidth = 256;
114 ddsd.dwHeight = 256;
115 rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
116 if (FAILED(rc))
117 return FALSE;
119 memset(&ddsd, 0, sizeof(ddsd));
120 ddsd.dwSize = sizeof(ddsd);
121 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
122 ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
123 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
124 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
125 U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 16;
126 U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
127 ddsd.dwWidth = 256;
128 ddsd.dwHeight = 256;
129 rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDSdepth, NULL);
130 ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
131 if (FAILED(rc)) {
132 lpDDSdepth = NULL;
133 } else {
134 rc = IDirectDrawSurface_AddAttachedSurface(lpDDS, lpDDSdepth);
135 ok(rc == DD_OK, "IDirectDrawSurface_AddAttachedSurface returned %x\n", rc);
136 if (FAILED(rc))
137 return FALSE;
140 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
141 &lpD3DDevice);
142 ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
143 if (!lpD3DDevice) {
144 trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
145 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
146 &lpD3DDevice);
147 if (!lpD3DDevice) {
148 trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
149 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
150 &lpD3DDevice);
151 if (!lpD3DDevice) {
152 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
153 return FALSE;
158 return TRUE;
161 static void ReleaseDirect3D(void)
163 if (lpD3DDevice != NULL)
165 IDirect3DDevice7_Release(lpD3DDevice);
166 lpD3DDevice = NULL;
169 if (lpDDSdepth != NULL)
171 IDirectDrawSurface_Release(lpDDSdepth);
172 lpDDSdepth = NULL;
175 if (lpDDS != NULL)
177 IDirectDrawSurface_Release(lpDDS);
178 lpDDS = NULL;
181 if (lpD3D != NULL)
183 IDirect3D7_Release(lpD3D);
184 lpD3D = NULL;
187 if (lpDD != NULL)
189 IDirectDraw_Release(lpDD);
190 lpDD = NULL;
194 static void LightTest(void)
196 HRESULT rc;
197 D3DLIGHT7 light;
198 D3DLIGHT7 defaultlight;
199 BOOL bEnabled = FALSE;
200 float one = 1.0f;
201 float zero= 0.0f;
202 D3DMATERIAL7 mat;
203 BOOL enabled;
204 unsigned int i;
205 D3DDEVICEDESC7 caps;
207 /* Set a few lights with funky indices. */
208 memset(&light, 0, sizeof(light));
209 light.dltType = D3DLIGHT_DIRECTIONAL;
210 U1(light.dcvDiffuse).r = 0.5f;
211 U2(light.dcvDiffuse).g = 0.6f;
212 U3(light.dcvDiffuse).b = 0.7f;
213 U2(light.dvDirection).y = 1.f;
215 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
216 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
217 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
218 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
219 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
220 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
223 /* Try to retrieve a light beyond the indices of the lights that have
224 been set. */
225 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
226 ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
227 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
228 ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
231 /* Try to retrieve one of the lights that have been set */
232 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
233 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
236 /* Enable a light that have been previously set. */
237 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
238 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
241 /* Enable some lights that have not been previously set, and verify that
242 they have been initialized with proper default values. */
243 memset(&defaultlight, 0, sizeof(D3DLIGHT7));
244 defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
245 U1(defaultlight.dcvDiffuse).r = 1.f;
246 U2(defaultlight.dcvDiffuse).g = 1.f;
247 U3(defaultlight.dcvDiffuse).b = 1.f;
248 U3(defaultlight.dvDirection).z = 1.f;
250 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
251 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
252 memset(&light, 0, sizeof(D3DLIGHT7));
253 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
254 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
255 ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
256 "light data doesn't match expected default values\n" );
258 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
259 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
260 memset(&light, 0, sizeof(D3DLIGHT7));
261 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
262 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
263 ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
264 "light data doesn't match expected default values\n" );
267 /* Disable one of the light that have been previously enabled. */
268 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
269 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
271 /* Try to retrieve the enable status of some lights */
272 /* Light 20 is supposed to be disabled */
273 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
274 ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
275 ok(!bEnabled, "GetLightEnable says the light is enabled\n");
277 /* Light 10 is supposed to be enabled */
278 bEnabled = FALSE;
279 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
280 ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
281 ok(bEnabled, "GetLightEnable says the light is disabled\n");
283 /* Light 80 has not been set */
284 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
285 ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
287 /* Light 23 has not been set */
288 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
289 ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
291 /* Set some lights with invalid parameters */
292 memset(&light, 0, sizeof(D3DLIGHT7));
293 light.dltType = 0;
294 U1(light.dcvDiffuse).r = 1.f;
295 U2(light.dcvDiffuse).g = 1.f;
296 U3(light.dcvDiffuse).b = 1.f;
297 U3(light.dvDirection).z = 1.f;
298 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
299 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
301 memset(&light, 0, sizeof(D3DLIGHT7));
302 light.dltType = 12345;
303 U1(light.dcvDiffuse).r = 1.f;
304 U2(light.dcvDiffuse).g = 1.f;
305 U3(light.dcvDiffuse).b = 1.f;
306 U3(light.dvDirection).z = 1.f;
307 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
308 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
310 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
311 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
313 memset(&light, 0, sizeof(D3DLIGHT7));
314 light.dltType = D3DLIGHT_SPOT;
315 U1(light.dcvDiffuse).r = 1.f;
316 U2(light.dcvDiffuse).g = 1.f;
317 U3(light.dcvDiffuse).b = 1.f;
318 U3(light.dvDirection).z = 1.f;
320 light.dvAttenuation0 = -one / zero; /* -INFINITY */
321 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
322 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
324 light.dvAttenuation0 = -1.0;
325 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
326 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
328 light.dvAttenuation0 = 0.0;
329 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
330 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
332 light.dvAttenuation0 = 1.0;
333 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
334 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
336 light.dvAttenuation0 = one / zero; /* +INFINITY */
337 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
338 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
340 light.dvAttenuation0 = zero / zero; /* NaN */
341 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
342 ok(rc==D3D_OK ||
343 broken(rc==DDERR_INVALIDPARAMS), "SetLight returned: %x\n", rc);
345 /* Directional light ignores attenuation */
346 light.dltType = D3DLIGHT_DIRECTIONAL;
347 light.dvAttenuation0 = -1.0;
348 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
349 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
351 memset(&mat, 0, sizeof(mat));
352 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
353 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial returned: %x\n", rc);
355 U4(mat).power = 129.0;
356 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
357 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = 129.0) returned: %x\n", rc);
358 memset(&mat, 0, sizeof(mat));
359 rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
360 ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
361 ok(U4(mat).power == 129, "Returned power is %f\n", U4(mat).power);
363 U4(mat).power = -1.0;
364 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
365 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = -1.0) returned: %x\n", rc);
366 memset(&mat, 0, sizeof(mat));
367 rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
368 ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
369 ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
371 memset(&caps, 0, sizeof(caps));
372 rc = IDirect3DDevice7_GetCaps(lpD3DDevice, &caps);
373 ok(rc == D3D_OK, "IDirect3DDevice7_GetCaps failed with %x\n", rc);
375 if ( caps.dwMaxActiveLights == (DWORD) -1) {
376 /* Some cards without T&L Support return -1 (Examples: Voodoo Banshee, RivaTNT / NV4) */
377 skip("T&L not supported\n");
378 return;
381 for(i = 1; i <= caps.dwMaxActiveLights; i++) {
382 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, TRUE);
383 ok(rc == D3D_OK, "Enabling light %u failed with %x\n", i, rc);
384 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i, &enabled);
385 ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i, rc);
386 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
389 /* TODO: Test the rendering results in this situation */
390 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, TRUE);
391 ok(rc == D3D_OK, "Enabling one light more than supported returned %x\n", rc);
392 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i + 1, &enabled);
393 ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i + 1, rc);
394 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
395 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, FALSE);
396 ok(rc == D3D_OK, "Disabling the additional returned %x\n", rc);
398 for(i = 1; i <= caps.dwMaxActiveLights; i++) {
399 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, FALSE);
400 ok(rc == D3D_OK, "Disabling light %u failed with %x\n", i, rc);
404 static void ProcessVerticesTest(void)
406 D3DVERTEXBUFFERDESC desc;
407 HRESULT rc;
408 VERTEX *in;
409 TVERTEX *out;
410 VERTEX *out2;
411 D3DVIEWPORT7 vp;
412 D3DMATRIX view = { 2.0, 0.0, 0.0, 0.0,
413 0.0, -1.0, 0.0, 0.0,
414 0.0, 0.0, 1.0, 0.0,
415 0.0, 0.0, 0.0, 3.0 };
417 D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
418 1.0, 0.0, 0.0, 0.0,
419 0.0, 0.0, 0.0, 1.0,
420 0.0, 1.0, 1.0, 1.0 };
422 D3DMATRIX proj = { 1.0, 0.0, 0.0, 1.0,
423 0.0, 1.0, 1.0, 0.0,
424 0.0, 1.0, 1.0, 0.0,
425 1.0, 0.0, 0.0, 1.0 };
426 /* Create some vertex buffers */
428 memset(&desc, 0, sizeof(desc));
429 desc.dwSize = sizeof(desc);
430 desc.dwCaps = 0;
431 desc.dwFVF = D3DFVF_XYZ;
432 desc.dwNumVertices = 16;
433 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
434 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
435 if (!lpVBufSrc)
437 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
438 goto out;
441 memset(&desc, 0, sizeof(desc));
442 desc.dwSize = sizeof(desc);
443 desc.dwCaps = 0;
444 desc.dwFVF = D3DFVF_XYZRHW;
445 desc.dwNumVertices = 16;
446 /* Msdn says that the last parameter must be 0 - check that */
447 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
448 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
449 if (!lpVBufDest1)
451 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
452 goto out;
455 memset(&desc, 0, sizeof(desc));
456 desc.dwSize = sizeof(desc);
457 desc.dwCaps = 0;
458 desc.dwFVF = D3DFVF_XYZ;
459 desc.dwNumVertices = 16;
460 /* Msdn says that the last parameter must be 0 - check that */
461 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
462 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
463 if (!lpVBufDest2)
465 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
466 goto out;
469 rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
470 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
471 if(!in) goto out;
473 /* Check basic transformation */
475 in[0].x = 0.0;
476 in[0].y = 0.0;
477 in[0].z = 0.0;
479 in[1].x = 1.0;
480 in[1].y = 1.0;
481 in[1].z = 1.0;
483 in[2].x = -1.0;
484 in[2].y = -1.0;
485 in[2].z = 0.5;
487 in[3].x = 0.5;
488 in[3].y = -0.5;
489 in[3].z = 0.25;
490 rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
491 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
493 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
494 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
496 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
497 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
499 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
500 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
501 if(!out) goto out;
503 /* Check the results */
504 ok( comparefloat(out[0].x, 128.0 ) &&
505 comparefloat(out[0].y, 128.0 ) &&
506 comparefloat(out[0].z, 0.0 ) &&
507 comparefloat(out[0].rhw, 1.0 ),
508 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
510 ok( comparefloat(out[1].x, 256.0 ) &&
511 comparefloat(out[1].y, 0.0 ) &&
512 comparefloat(out[1].z, 1.0 ) &&
513 comparefloat(out[1].rhw, 1.0 ),
514 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
516 ok( comparefloat(out[2].x, 0.0 ) &&
517 comparefloat(out[2].y, 256.0 ) &&
518 comparefloat(out[2].z, 0.5 ) &&
519 comparefloat(out[2].rhw, 1.0 ),
520 "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
522 ok( comparefloat(out[3].x, 192.0 ) &&
523 comparefloat(out[3].y, 192.0 ) &&
524 comparefloat(out[3].z, 0.25 ) &&
525 comparefloat(out[3].rhw, 1.0 ),
526 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
528 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
529 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
530 out = NULL;
532 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
533 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
534 if(!out2) goto out;
535 /* Small thing without much practical meaning, but I stumbled upon it,
536 * so let's check for it: If the output vertex buffer has to RHW value,
537 * The RHW value of the last vertex is written into the next vertex
539 ok( comparefloat(out2[4].x, 1.0 ) &&
540 comparefloat(out2[4].y, 0.0 ) &&
541 comparefloat(out2[4].z, 0.0 ),
542 "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
544 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
545 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
546 out = NULL;
548 /* Try a more complicated viewport, same vertices */
549 memset(&vp, 0, sizeof(vp));
550 vp.dwX = 10;
551 vp.dwY = 5;
552 vp.dwWidth = 246;
553 vp.dwHeight = 130;
554 vp.dvMinZ = -2.0;
555 vp.dvMaxZ = 4.0;
556 rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
557 ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
559 /* Process again */
560 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
561 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
563 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
564 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
565 if(!out) goto out;
567 /* Check the results */
568 ok( comparefloat(out[0].x, 133.0 ) &&
569 comparefloat(out[0].y, 70.0 ) &&
570 comparefloat(out[0].z, -2.0 ) &&
571 comparefloat(out[0].rhw, 1.0 ),
572 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
574 ok( comparefloat(out[1].x, 256.0 ) &&
575 comparefloat(out[1].y, 5.0 ) &&
576 comparefloat(out[1].z, 4.0 ) &&
577 comparefloat(out[1].rhw, 1.0 ),
578 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
580 ok( comparefloat(out[2].x, 10.0 ) &&
581 comparefloat(out[2].y, 135.0 ) &&
582 comparefloat(out[2].z, 1.0 ) &&
583 comparefloat(out[2].rhw, 1.0 ),
584 "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
586 ok( comparefloat(out[3].x, 194.5 ) &&
587 comparefloat(out[3].y, 102.5 ) &&
588 comparefloat(out[3].z, -0.5 ) &&
589 comparefloat(out[3].rhw, 1.0 ),
590 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
592 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
593 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
594 out = NULL;
596 /* Play with some matrices. */
598 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
599 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
601 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
602 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
604 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
605 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
607 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
608 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
610 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
611 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
612 if(!out) goto out;
614 /* Keep the viewport simpler, otherwise we get bad numbers to compare */
615 vp.dwX = 0;
616 vp.dwY = 0;
617 vp.dwWidth = 100;
618 vp.dwHeight = 100;
619 vp.dvMinZ = 1.0;
620 vp.dvMaxZ = 0.0;
621 rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
622 ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
624 /* Check the results */
625 ok( comparefloat(out[0].x, 256.0 ) && /* X coordinate is cut at the surface edges */
626 comparefloat(out[0].y, 70.0 ) &&
627 comparefloat(out[0].z, -2.0 ) &&
628 comparefloat(out[0].rhw, (1.0 / 3.0)),
629 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
631 ok( comparefloat(out[1].x, 256.0 ) &&
632 comparefloat(out[1].y, 78.125000 ) &&
633 comparefloat(out[1].z, -2.750000 ) &&
634 comparefloat(out[1].rhw, 0.125000 ),
635 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
637 ok( comparefloat(out[2].x, 256.0 ) &&
638 comparefloat(out[2].y, 44.000000 ) &&
639 comparefloat(out[2].z, 0.400000 ) &&
640 comparefloat(out[2].rhw, 0.400000 ),
641 "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
643 ok( comparefloat(out[3].x, 256.0 ) &&
644 comparefloat(out[3].y, 81.818184 ) &&
645 comparefloat(out[3].z, -3.090909 ) &&
646 comparefloat(out[3].rhw, 0.363636 ),
647 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
649 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
650 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
651 out = NULL;
653 out:
654 IDirect3DVertexBuffer7_Release(lpVBufSrc);
655 IDirect3DVertexBuffer7_Release(lpVBufDest1);
656 IDirect3DVertexBuffer7_Release(lpVBufDest2);
659 static void StateTest( void )
661 HRESULT rc;
663 /* The msdn says its undocumented, does it return an error too? */
664 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
665 ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
666 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
667 ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
671 static void SceneTest(void)
673 HRESULT hr;
675 /* Test an EndScene without beginscene. Should return an error */
676 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
677 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
679 /* Test a normal BeginScene / EndScene pair, this should work */
680 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
681 ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
682 if(SUCCEEDED(hr))
684 DDBLTFX fx;
685 memset(&fx, 0, sizeof(fx));
686 fx.dwSize = sizeof(fx);
688 if(lpDDSdepth) {
689 hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
690 ok(hr == D3D_OK, "Depthfill failed in a BeginScene / EndScene pair\n");
691 } else {
692 skip("Depth stencil creation failed at startup, skipping\n");
694 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
695 ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
698 /* Test another EndScene without having begun a new scene. Should return an error */
699 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
700 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
702 /* Two nested BeginScene and EndScene calls */
703 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
704 ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
705 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
706 ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
707 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
708 ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
709 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
710 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
712 /* TODO: Verify that blitting works in the same way as in d3d9 */
715 static void LimitTest(void)
717 IDirectDrawSurface7 *pTexture = NULL;
718 HRESULT hr;
719 int i;
720 DDSURFACEDESC2 ddsd;
722 memset(&ddsd, 0, sizeof(ddsd));
723 ddsd.dwSize = sizeof(ddsd);
724 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
725 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
726 ddsd.dwWidth = 16;
727 ddsd.dwHeight = 16;
728 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
729 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
730 if(!pTexture) return;
732 for(i = 0; i < 8; i++) {
733 hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
734 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
735 hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
736 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
737 hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
738 ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
741 IDirectDrawSurface7_Release(pTexture);
744 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
746 UINT ver = *((UINT *) ctx);
747 if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
749 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
750 "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
751 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
752 "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
753 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
754 "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
755 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
756 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
758 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
759 "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
760 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
761 "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
762 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
763 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
764 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
765 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
767 else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
769 /* pow2 is hardware dependent */
771 ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
772 "HAL Device %d hal line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
773 ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
774 "HAL Device %d hal tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
775 ok((hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
776 "HAL Device %d hel line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
777 ok((hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
778 "HAL Device %d hel tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
780 else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
782 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
783 "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
784 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
785 "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
786 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
787 "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
788 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
789 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
791 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
792 "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
793 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
794 "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
795 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
796 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
797 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
798 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
800 else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
802 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
803 "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
804 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
805 "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
806 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
807 "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
808 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
809 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
811 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
812 "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
813 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
814 "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
815 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
816 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
817 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
818 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
820 else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
822 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
823 "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
824 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
825 "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
826 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
827 "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
828 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
829 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
831 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
832 "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
833 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
834 "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
835 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
836 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
837 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
838 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
840 else
842 ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
843 if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
844 else trace("hal line does NOT have pow2 set\n");
845 if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
846 else trace("hal tri does NOT have pow2 set\n");
847 if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
848 else trace("hel line does NOT have pow2 set\n");
849 if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
850 else trace("hel tri does NOT have pow2 set\n");
852 return DDENUMRET_OK;
855 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
857 D3D7ETest *d3d7et = Context;
858 if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
859 d3d7et->rgb++;
860 else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
861 d3d7et->hal++;
862 else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
863 d3d7et->tnlhal++;
864 else
865 d3d7et->unk++;
867 d3d7et->total++;
869 return DDENUMRET_OK;
873 /* Check the deviceGUID of devices enumerated by
874 IDirect3D7_EnumDevices. */
875 static void D3D7EnumTest(void)
877 D3D7ETest d3d7et;
879 if (!lpD3D) {
880 skip("No Direct3D7 interface.\n");
881 return;
884 memset(&d3d7et, 0, sizeof(d3d7et));
885 IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et);
888 /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
889 ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
891 /* We make two additional assumptions. */
892 ok(d3d7et.rgb, "No RGB Device enumerated.\n");
894 if(d3d7et.tnlhal)
895 ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
897 return;
900 static void CapsTest(void)
902 IDirect3D3 *d3d3;
903 IDirect3D3 *d3d2;
904 IDirectDraw *dd1;
905 HRESULT hr;
906 UINT ver;
908 hr = DirectDrawCreate(NULL, &dd1, NULL);
909 ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
910 hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
911 ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
912 ver = 3;
913 IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
915 IDirect3D3_Release(d3d3);
916 IDirectDraw_Release(dd1);
918 hr = DirectDrawCreate(NULL, &dd1, NULL);
919 ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
920 hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
921 ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
922 ver = 2;
923 IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
925 IDirect3D2_Release(d3d2);
926 IDirectDraw_Release(dd1);
929 struct v_in {
930 float x, y, z;
932 struct v_out {
933 float x, y, z, rhw;
936 static BOOL D3D1_createObjects(void)
938 HRESULT hr;
939 DDSURFACEDESC ddsd;
940 D3DEXECUTEBUFFERDESC desc;
941 D3DVIEWPORT vp_data;
943 /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
944 hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
945 ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
946 if (!DirectDraw1) {
947 return FALSE;
950 hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
951 ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
953 hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
954 ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
955 if (!Direct3D1) {
956 return FALSE;
959 memset(&ddsd, 0, sizeof(ddsd));
960 ddsd.dwSize = sizeof(ddsd);
961 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
962 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
963 ddsd.dwWidth = 256;
964 ddsd.dwHeight = 256;
965 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
966 if (!Surface1) {
967 skip("DDSCAPS_3DDEVICE surface not available\n");
968 return FALSE;
971 hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
972 ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
973 if(!Direct3DDevice1) {
974 return FALSE;
977 memset(&desc, 0, sizeof(desc));
978 desc.dwSize = sizeof(desc);
979 desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
980 desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
981 desc.dwBufferSize = 128;
982 desc.lpData = NULL;
983 hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
984 ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
985 if(!ExecuteBuffer) {
986 return FALSE;
989 hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
990 ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
991 if(!Viewport) {
992 return FALSE;
995 hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
996 ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
998 hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
999 ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1000 vp_data.dwSize = sizeof(vp_data);
1001 vp_data.dwX = 0;
1002 vp_data.dwY = 0;
1003 vp_data.dwWidth = 256;
1004 vp_data.dwHeight = 256;
1005 vp_data.dvScaleX = 1;
1006 vp_data.dvScaleY = 1;
1007 vp_data.dvMaxX = 256;
1008 vp_data.dvMaxY = 256;
1009 vp_data.dvMinZ = 0;
1010 vp_data.dvMaxZ = 1;
1011 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1012 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1014 hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1015 ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1016 if (!Light)
1017 return FALSE;
1019 return TRUE;
1022 static void D3D1_releaseObjects(void)
1024 if (Light) IDirect3DLight_Release(Light);
1025 if (Viewport) IDirect3DViewport_Release(Viewport);
1026 if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1027 if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1028 if (Surface1) IDirectDrawSurface_Release(Surface1);
1029 if (Direct3D1) IDirect3D_Release(Direct3D1);
1030 if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1033 #define SET_VP_DATA(vp_data) \
1034 vp_data.dwSize = sizeof(vp_data); \
1035 vp_data.dwX = 0; \
1036 vp_data.dwY = 0; \
1037 vp_data.dwWidth = 256; \
1038 vp_data.dwHeight = 256; \
1039 vp_data.dvMaxX = 256; \
1040 vp_data.dvMaxY = 256; \
1041 vp_data.dvScaleX = 5; \
1042 vp_data.dvScaleY = 5; \
1043 vp_data.dvMinZ = -25; \
1044 vp_data.dvMaxZ = 60;
1046 static void Direct3D1Test(void)
1048 HRESULT hr;
1049 D3DEXECUTEBUFFERDESC desc;
1050 D3DVIEWPORT vp_data;
1051 D3DINSTRUCTION *instr;
1052 D3DBRANCH *branch;
1053 IDirect3D *Direct3D_alt;
1054 IDirect3DLight *d3dlight;
1055 ULONG refcount;
1056 unsigned int idx = 0;
1057 static struct v_in testverts[] = {
1058 {0.0, 0.0, 0.0}, { 1.0, 1.0, 1.0}, {-1.0, -1.0, -1.0},
1059 {0.5, 0.5, 0.5}, {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1061 static struct v_in cliptest[] = {
1062 {25.59, 25.59, 1.0}, {-25.59, -25.59, 0.0},
1063 {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1065 static struct v_in offscreentest[] = {
1066 {128.1, 0.0, 0.0},
1068 struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1069 D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1070 D3DTRANSFORMDATA transformdata;
1071 DWORD i = FALSE;
1073 /* Interface consistency check. */
1074 hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1075 ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1076 if (hr == D3D_OK)
1077 ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1079 memset(&desc, 0, sizeof(desc));
1080 desc.dwSize = sizeof(desc);
1081 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1082 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1084 memset(desc.lpData, 0, 128);
1085 instr = desc.lpData;
1086 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1087 instr[idx].bSize = sizeof(*branch);
1088 instr[idx].wCount = 1;
1089 idx++;
1090 branch = (D3DBRANCH *) &instr[idx];
1091 branch->dwMask = 0x0;
1092 branch->dwValue = 1;
1093 branch->bNegate = TRUE;
1094 branch->dwOffset = 0;
1095 idx += (sizeof(*branch) / sizeof(*instr));
1096 instr[idx].bOpcode = D3DOP_EXIT;
1097 instr[idx].bSize = 0;
1098 instr[idx].wCount = 0;
1099 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1100 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1102 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1103 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1105 memset(&desc, 0, sizeof(desc));
1106 desc.dwSize = sizeof(desc);
1108 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1109 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1111 memset(desc.lpData, 0, 128);
1112 instr = desc.lpData;
1113 idx = 0;
1114 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1115 instr[idx].bSize = sizeof(*branch);
1116 instr[idx].wCount = 1;
1117 idx++;
1118 branch = (D3DBRANCH *) &instr[idx];
1119 branch->dwMask = 0x0;
1120 branch->dwValue = 1;
1121 branch->bNegate = TRUE;
1122 branch->dwOffset = 64;
1123 instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1124 instr[0].bOpcode = D3DOP_EXIT;
1125 instr[0].bSize = 0;
1126 instr[0].wCount = 0;
1127 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1128 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1130 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1131 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1133 /* Test rendering 0 triangles */
1134 memset(&desc, 0, sizeof(desc));
1135 desc.dwSize = sizeof(desc);
1137 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1138 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1140 memset(desc.lpData, 0, 128);
1141 instr = desc.lpData;
1142 idx = 0;
1144 instr->bOpcode = D3DOP_TRIANGLE;
1145 instr->bSize = sizeof(D3DOP_TRIANGLE);
1146 instr->wCount = 0;
1147 instr++;
1148 instr->bOpcode = D3DOP_EXIT;
1149 instr->bSize = 0;
1150 instr->wCount = 0;
1151 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1152 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1154 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1155 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1157 memset(&transformdata, 0, sizeof(transformdata));
1158 transformdata.dwSize = sizeof(transformdata);
1159 transformdata.lpIn = testverts;
1160 transformdata.dwInSize = sizeof(testverts[0]);
1161 transformdata.lpOut = out;
1162 transformdata.dwOutSize = sizeof(out[0]);
1164 transformdata.lpHOut = NULL;
1165 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1166 &transformdata, D3DTRANSFORM_UNCLIPPED,
1167 &i);
1168 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1170 transformdata.lpHOut = outH;
1171 memset(outH, 0xcc, sizeof(outH));
1172 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1173 &transformdata, D3DTRANSFORM_UNCLIPPED,
1174 &i);
1175 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1176 ok(i == 0, "Offscreen is %d\n", i);
1178 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1179 static const struct v_out cmp[] = {
1180 {128.0, 128.0, 0.0, 1}, {129.0, 127.0, 1.0, 1}, {127.0, 129.0, -1, 1},
1181 {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5, 0, 1}
1184 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1185 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1186 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1187 out[i].x, out[i].y, out[i].z, out[i].rhw,
1188 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1190 for(i = 0; i < sizeof(outH); i++) {
1191 if(((unsigned char *) outH)[i] != 0xcc) {
1192 ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1193 break;
1197 SET_VP_DATA(vp_data);
1198 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1199 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1200 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1201 &transformdata, D3DTRANSFORM_UNCLIPPED,
1202 &i);
1203 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1204 ok(i == 0, "Offscreen is %d\n", i);
1206 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1207 static const struct v_out cmp[] = {
1208 {128.0, 128.0, 0.0, 1}, {133.0, 123.0, 1.0, 1}, {123.0, 133.0, -1, 1},
1209 {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5, 0, 1}
1211 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1212 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1213 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1214 out[i].x, out[i].y, out[i].z, out[i].rhw,
1215 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1218 SET_VP_DATA(vp_data);
1219 vp_data.dwX = 10;
1220 vp_data.dwY = 20;
1221 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1222 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1223 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1224 &transformdata, D3DTRANSFORM_UNCLIPPED,
1225 &i);
1226 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1227 ok(i == 0, "Offscreen is %d\n", i);
1228 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1229 static const struct v_out cmp[] = {
1230 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, {133.0, 153.0, -1, 1},
1231 {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5, 0, 1}
1233 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1234 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1235 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1236 out[i].x, out[i].y, out[i].z, out[i].rhw,
1237 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1240 memset(out, 0xcc, sizeof(out));
1241 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1242 &transformdata, D3DTRANSFORM_CLIPPED,
1243 &i);
1244 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1245 ok(i == 0, "Offscreen is %d\n", i);
1246 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1247 static const D3DHVERTEX cmpH[] = {
1248 {0, { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1249 {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1250 {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1252 ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1253 U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1254 "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1255 outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1256 cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1258 /* No scheme has been found behind those return values. It seems to be
1259 * whatever data windows has when throwing the vertex away. Modify the
1260 * input test vertices to test this more. Depending on the input data
1261 * it can happen that the z coord gets written into y, or similar things
1263 if(0)
1265 static const struct v_out cmp[] = {
1266 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, { -1.0, -1.0, 0.5, 1},
1267 {140.5, 145.5, 0.5, 1}, { -0.5, -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1269 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1270 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1271 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1272 out[i].x, out[i].y, out[i].z, out[i].rhw,
1273 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1276 for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1277 ok(((DWORD *) out)[i] != 0xcccccccc,
1278 "Regular output DWORD %d remained untouched\n", i);
1281 transformdata.lpIn = cliptest;
1282 transformdata.dwInSize = sizeof(cliptest[0]);
1283 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1284 &transformdata, D3DTRANSFORM_CLIPPED,
1285 &i);
1286 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1287 ok(i == 0, "Offscreen is %d\n", i);
1288 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1289 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1293 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
1294 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1296 ok(Flags[i] == outH[i].dwFlags,
1297 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1298 outH[i].dwFlags, Flags[i]);
1301 SET_VP_DATA(vp_data);
1302 vp_data.dwWidth = 10;
1303 vp_data.dwHeight = 1000;
1304 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1305 i = 10;
1306 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1307 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1308 &transformdata, D3DTRANSFORM_CLIPPED,
1309 &i);
1310 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1311 ok(i == 0, "Offscreen is %d\n", i);
1312 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1313 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1315 D3DCLIP_RIGHT,
1316 D3DCLIP_LEFT,
1317 D3DCLIP_RIGHT | D3DCLIP_BACK,
1318 D3DCLIP_LEFT | D3DCLIP_FRONT,
1320 ok(Flags[i] == outH[i].dwFlags,
1321 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1322 outH[i].dwFlags, Flags[i]);
1325 SET_VP_DATA(vp_data);
1326 vp_data.dwWidth = 256;
1327 vp_data.dwHeight = 256;
1328 vp_data.dvScaleX = 1;
1329 vp_data.dvScaleY = 1;
1330 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1331 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1332 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1333 &transformdata, D3DTRANSFORM_CLIPPED,
1334 &i);
1335 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1336 ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1337 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1338 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1342 D3DCLIP_BACK,
1343 D3DCLIP_FRONT,
1345 ok(Flags[i] == outH[i].dwFlags,
1346 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1347 outH[i].dwFlags, Flags[i]);
1350 /* Finally try to figure out how the DWORD dwOffscreen works.
1351 * Apparently no vertex is offscreen with clipping off,
1352 * and with clipping on the offscreen flag is set if only one vertex
1353 * is transformed, and this vertex is offscreen.
1355 SET_VP_DATA(vp_data);
1356 vp_data.dwWidth = 5;
1357 vp_data.dwHeight = 5;
1358 vp_data.dvScaleX = 10000;
1359 vp_data.dvScaleY = 10000;
1360 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1361 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1362 transformdata.lpIn = cliptest;
1363 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1364 &transformdata, D3DTRANSFORM_UNCLIPPED,
1365 &i);
1366 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1367 ok(i == 0, "Offscreen is %d\n", i);
1368 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1369 &transformdata, D3DTRANSFORM_CLIPPED,
1370 &i);
1371 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1372 ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1373 hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1374 &transformdata, D3DTRANSFORM_CLIPPED,
1375 &i);
1376 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1377 ok(i == 0, "Offscreen is %d\n", i);
1378 transformdata.lpIn = cliptest + 1;
1379 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1380 &transformdata, D3DTRANSFORM_CLIPPED,
1381 &i);
1382 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1383 ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1385 transformdata.lpIn = offscreentest;
1386 transformdata.dwInSize = sizeof(offscreentest[0]);
1387 SET_VP_DATA(vp_data);
1388 vp_data.dwWidth = 257;
1389 vp_data.dwHeight = 257;
1390 vp_data.dvScaleX = 1;
1391 vp_data.dvScaleY = 1;
1392 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1393 i = 12345;
1394 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1395 &transformdata, D3DTRANSFORM_CLIPPED,
1396 &i);
1397 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1398 ok(i == 0, "Offscreen is %d\n", i);
1399 vp_data.dwWidth = 256;
1400 vp_data.dwHeight = 256;
1401 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1402 i = 12345;
1403 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1404 &transformdata, D3DTRANSFORM_CLIPPED,
1405 &i);
1406 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1407 ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1409 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1410 &transformdata, 0,
1411 &i);
1412 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1414 hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1415 ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1417 hr = IDirect3DViewport_AddLight(Viewport, Light);
1418 ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1419 refcount = getRefcount((IUnknown*) Light);
1420 ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1422 hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1423 ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1424 ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1425 refcount = getRefcount((IUnknown*) Light);
1426 ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1428 hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1429 ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1430 refcount = getRefcount((IUnknown*) Light);
1431 ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1433 IDirect3DLight_Release(Light);
1436 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1438 int i;
1440 for (i = 0; i < 256; i++) {
1441 if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1442 table1[i].peBlue != table2[i].peBlue) return FALSE;
1445 return TRUE;
1448 /* test palette handling in IDirect3DTexture_Load */
1449 static void TextureLoadTest(void)
1451 IDirectDrawSurface *TexSurface = NULL;
1452 IDirect3DTexture *Texture = NULL;
1453 IDirectDrawSurface *TexSurface2 = NULL;
1454 IDirect3DTexture *Texture2 = NULL;
1455 IDirectDrawPalette *palette = NULL;
1456 IDirectDrawPalette *palette2 = NULL;
1457 IDirectDrawPalette *palette_tmp = NULL;
1458 PALETTEENTRY table1[256], table2[256], table_tmp[256];
1459 HRESULT hr;
1460 DDSURFACEDESC ddsd;
1461 int i;
1463 memset (&ddsd, 0, sizeof (ddsd));
1464 ddsd.dwSize = sizeof (ddsd);
1465 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1466 ddsd.dwHeight = 128;
1467 ddsd.dwWidth = 128;
1468 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1469 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1470 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1471 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1473 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1474 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1475 if (FAILED(hr)) {
1476 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1477 goto cleanup;
1480 hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1481 (void *)&Texture);
1482 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1483 if (FAILED(hr)) {
1484 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1485 goto cleanup;
1488 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1489 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1490 if (FAILED(hr)) {
1491 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1492 goto cleanup;
1495 hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1496 (void *)&Texture2);
1497 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1498 if (FAILED(hr)) {
1499 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1500 goto cleanup;
1503 /* test load of Texture to Texture */
1504 hr = IDirect3DTexture_Load(Texture, Texture);
1505 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1507 /* test Load when both textures have no palette */
1508 hr = IDirect3DTexture_Load(Texture2, Texture);
1509 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1511 for (i = 0; i < 256; i++) {
1512 table1[i].peRed = i;
1513 table1[i].peGreen = i;
1514 table1[i].peBlue = i;
1515 table1[i].peFlags = 0;
1518 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1519 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1520 if (FAILED(hr)) {
1521 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1522 goto cleanup;
1525 /* test Load when source texture has palette and destination has no palette */
1526 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1527 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1528 hr = IDirect3DTexture_Load(Texture2, Texture);
1529 ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1531 for (i = 0; i < 256; i++) {
1532 table2[i].peRed = 255 - i;
1533 table2[i].peGreen = 255 - i;
1534 table2[i].peBlue = 255 - i;
1535 table2[i].peFlags = 0;
1538 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1539 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1540 if (FAILED(hr)) {
1541 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1542 goto cleanup;
1545 /* test Load when source has no palette and destination has a palette */
1546 hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1547 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1548 hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1549 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1550 hr = IDirect3DTexture_Load(Texture2, Texture);
1551 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1552 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1553 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1554 if (!palette_tmp) {
1555 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1556 goto cleanup;
1557 } else {
1558 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1559 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1560 ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1561 IDirectDrawPalette_Release(palette_tmp);
1564 /* test Load when both textures have palettes */
1565 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1566 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1567 hr = IDirect3DTexture_Load(Texture2, Texture);
1568 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1569 hr = IDirect3DTexture_Load(Texture2, Texture);
1570 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1571 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1572 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1573 if (!palette_tmp) {
1574 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1575 goto cleanup;
1576 } else {
1577 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1578 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1579 ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1580 IDirectDrawPalette_Release(palette_tmp);
1583 cleanup:
1585 if (palette) IDirectDrawPalette_Release(palette);
1586 if (palette2) IDirectDrawPalette_Release(palette2);
1587 if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1588 if (Texture) IDirect3DTexture_Release(Texture);
1589 if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1590 if (Texture2) IDirect3DTexture_Release(Texture2);
1593 static void VertexBufferDescTest(void)
1595 HRESULT rc;
1596 D3DVERTEXBUFFERDESC desc;
1597 union mem_t
1599 D3DVERTEXBUFFERDESC desc2;
1600 unsigned char buffer[512];
1601 } mem;
1603 memset(&desc, 0, sizeof(desc));
1604 desc.dwSize = sizeof(desc);
1605 desc.dwCaps = 0;
1606 desc.dwFVF = D3DFVF_XYZ;
1607 desc.dwNumVertices = 1;
1608 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1609 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1610 if (!lpVBufSrc)
1612 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1613 goto out;
1616 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1617 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1618 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1619 if(rc != D3D_OK)
1620 skip("GetVertexBuffer Failed!\n");
1621 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1622 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1623 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1624 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1625 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1627 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1628 mem.desc2.dwSize = 0;
1629 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1630 if(rc != D3D_OK)
1631 skip("GetVertexBuffer Failed!\n");
1632 ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1633 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1634 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1635 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1636 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1638 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1639 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1640 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1641 if(rc != D3D_OK)
1642 skip("GetVertexBuffer Failed!\n");
1643 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1644 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1645 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1646 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1647 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1649 out:
1650 IDirect3DVertexBuffer7_Release(lpVBufSrc);
1653 static void D3D7_OldRenderStateTest(void)
1655 HRESULT rc;
1656 DWORD val;
1658 /* Test reaction to some deprecated states in D3D7.
1660 * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1661 * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1662 * need not to be handled in D3D7.
1664 todo_wine {
1665 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1666 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1668 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1669 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1671 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1672 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1674 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1675 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1679 #define IS_VALUE_NEAR(a, b) ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1680 #define MIN(a, b) ((a) < (b) ? (a) : (b))
1682 static void DeviceLoadTest(void)
1684 DDSURFACEDESC2 ddsd;
1685 IDirectDrawSurface7 *texture_levels[2][8];
1686 IDirectDrawSurface7 *cube_face_levels[2][6][8];
1687 DWORD flags;
1688 HRESULT hr;
1689 DDBLTFX ddbltfx;
1690 RECT loadrect;
1691 POINT loadpoint;
1692 int i, i1, i2;
1693 unsigned diff_count = 0, diff_count2 = 0;
1694 unsigned x, y;
1695 BOOL load_mip_subset_broken = FALSE;
1696 IDirectDrawPalette *palettes[5];
1697 PALETTEENTRY table1[256];
1698 DDCOLORKEY ddckey;
1699 D3DDEVICEDESC7 d3dcaps;
1701 /* Test loading of texture subrectangle with a mipmap surface. */
1702 memset(texture_levels, 0, sizeof(texture_levels));
1703 memset(cube_face_levels, 0, sizeof(cube_face_levels));
1704 memset(palettes, 0, sizeof(palettes));
1706 for (i = 0; i < 2; i++)
1708 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1709 ddsd.dwSize = sizeof(ddsd);
1710 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1711 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1712 ddsd.dwWidth = 128;
1713 ddsd.dwHeight = 128;
1714 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1715 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1716 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1717 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1718 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1719 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1720 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1721 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1722 if (FAILED(hr)) goto out;
1724 /* Check the number of created mipmaps */
1725 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1726 ddsd.dwSize = sizeof(ddsd);
1727 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1728 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1729 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1730 if (U2(ddsd).dwMipMapCount != 8) goto out;
1732 for (i1 = 1; i1 < 8; i1++)
1734 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1735 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1736 if (FAILED(hr)) goto out;
1740 for (i1 = 0; i1 < 8; i1++)
1742 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1743 ddsd.dwSize = sizeof(ddsd);
1744 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1745 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1746 if (FAILED(hr)) goto out;
1748 for (y = 0 ; y < ddsd.dwHeight; y++)
1750 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1752 for (x = 0; x < ddsd.dwWidth; x++)
1754 /* x stored in green component, y in blue. */
1755 DWORD color = 0xff0000 | (x << 8) | y;
1756 *textureRow++ = color;
1760 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1761 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1764 for (i1 = 0; i1 < 8; i1++)
1766 memset(&ddbltfx, 0, sizeof(ddbltfx));
1767 ddbltfx.dwSize = sizeof(ddbltfx);
1768 U5(ddbltfx).dwFillColor = 0;
1769 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1770 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1773 /* First test some broken coordinates. */
1774 loadpoint.x = loadpoint.y = 0;
1775 loadrect.left = 0;
1776 loadrect.top = 0;
1777 loadrect.right = 0;
1778 loadrect.bottom = 0;
1779 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1780 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1782 loadpoint.x = loadpoint.y = 50;
1783 loadrect.left = 0;
1784 loadrect.top = 0;
1785 loadrect.right = 100;
1786 loadrect.bottom = 100;
1787 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1788 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1790 /* Test actual loading. */
1791 loadpoint.x = loadpoint.y = 31;
1792 loadrect.left = 30;
1793 loadrect.top = 20;
1794 loadrect.right = 93;
1795 loadrect.bottom = 52;
1797 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1798 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1800 for (i1 = 0; i1 < 8; i1++)
1802 diff_count = 0;
1803 diff_count2 = 0;
1805 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1806 ddsd.dwSize = sizeof(ddsd);
1807 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1808 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1809 if (FAILED(hr)) goto out;
1811 for (y = 0 ; y < ddsd.dwHeight; y++)
1813 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1815 for (x = 0; x < ddsd.dwWidth; x++)
1817 DWORD color = *textureRow++;
1819 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1820 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1822 if (color & 0xffffff) diff_count++;
1824 else
1826 DWORD r = (color & 0xff0000) >> 16;
1827 DWORD g = (color & 0xff00) >> 8;
1828 DWORD b = (color & 0xff);
1830 if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1833 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1834 technically be correct as it's not precisely defined by docs. */
1835 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1836 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1838 if (color & 0xffffff) diff_count2++;
1840 else
1842 DWORD r = (color & 0xff0000) >> 16;
1843 DWORD g = (color & 0xff00) >> 8;
1844 DWORD b = (color & 0xff);
1846 if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1847 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1852 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1853 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1855 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1856 MIN(diff_count, diff_count2), i1);
1858 loadpoint.x /= 2;
1859 loadpoint.y /= 2;
1860 loadrect.top /= 2;
1861 loadrect.left /= 2;
1862 loadrect.right = (loadrect.right + 1) / 2;
1863 loadrect.bottom = (loadrect.bottom + 1) / 2;
1866 /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1867 * qemu Win98 / directx7 / RGB software rasterizer):
1868 * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1869 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1872 /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1873 for (i = 0; i < 2; i++)
1875 for (i1 = 7; i1 >= 0; i1--)
1877 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1880 memset(texture_levels, 0, sizeof(texture_levels));
1882 /* Test texture size mismatch. */
1883 for (i = 0; i < 2; i++)
1885 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1886 ddsd.dwSize = sizeof(ddsd);
1887 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1888 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1889 ddsd.dwWidth = i ? 256 : 128;
1890 ddsd.dwHeight = 128;
1891 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1892 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1893 if (FAILED(hr)) goto out;
1896 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1897 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1899 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1900 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1902 IDirectDrawSurface7_Release(texture_levels[0][0]);
1903 IDirectDrawSurface7_Release(texture_levels[1][0]);
1904 memset(texture_levels, 0, sizeof(texture_levels));
1906 memset(&d3dcaps, 0, sizeof(d3dcaps));
1907 hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1908 ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1910 if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1912 skip("No cubemap support\n");
1914 else
1916 /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1917 for (i = 0; i < 2; i++)
1919 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1920 ddsd.dwSize = sizeof(ddsd);
1921 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1922 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1923 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1924 ddsd.dwWidth = 128;
1925 ddsd.dwHeight = 128;
1926 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1927 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1928 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1929 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1930 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1931 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1932 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1933 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1934 if (FAILED(hr)) goto out;
1936 flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1937 for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1939 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1940 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1941 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1942 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1943 if (FAILED(hr)) goto out;
1946 for (i1 = 0; i1 < 6; i1++)
1948 /* Check the number of created mipmaps */
1949 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1950 ddsd.dwSize = sizeof(ddsd);
1951 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1952 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1953 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1954 if (U2(ddsd).dwMipMapCount != 8) goto out;
1956 for (i2 = 1; i2 < 8; i2++)
1958 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1959 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1960 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1961 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1962 if (FAILED(hr)) goto out;
1967 for (i = 0; i < 6; i++)
1968 for (i1 = 0; i1 < 8; i1++)
1970 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1971 ddsd.dwSize = sizeof(ddsd);
1972 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][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 /* face number in low 4 bits of red, x stored in green component, y in blue. */
1983 DWORD color = 0xf00000 | (i << 16) | (x << 8) | y;
1984 *textureRow++ = color;
1988 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1989 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1992 for (i = 0; i < 6; i++)
1993 for (i1 = 0; i1 < 8; i1++)
1995 memset(&ddbltfx, 0, sizeof(ddbltfx));
1996 ddbltfx.dwSize = sizeof(ddbltfx);
1997 U5(ddbltfx).dwFillColor = 0;
1998 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1999 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2002 loadpoint.x = loadpoint.y = 10;
2003 loadrect.left = 30;
2004 loadrect.top = 20;
2005 loadrect.right = 93;
2006 loadrect.bottom = 52;
2008 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2009 DDSCAPS2_CUBEMAP_ALLFACES);
2010 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2012 for (i = 0; i < 6; i++)
2014 loadpoint.x = loadpoint.y = 10;
2015 loadrect.left = 30;
2016 loadrect.top = 20;
2017 loadrect.right = 93;
2018 loadrect.bottom = 52;
2020 for (i1 = 0; i1 < 8; i1++)
2022 diff_count = 0;
2023 diff_count2 = 0;
2025 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2026 ddsd.dwSize = sizeof(ddsd);
2027 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2028 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2029 if (FAILED(hr)) goto out;
2031 for (y = 0 ; y < ddsd.dwHeight; y++)
2033 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2035 for (x = 0; x < ddsd.dwWidth; x++)
2037 DWORD color = *textureRow++;
2039 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2040 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2042 if (color & 0xffffff) diff_count++;
2044 else
2046 DWORD r = (color & 0xff0000) >> 16;
2047 DWORD g = (color & 0xff00) >> 8;
2048 DWORD b = (color & 0xff);
2050 if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2051 b != y + loadrect.top - loadpoint.y) diff_count++;
2054 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2055 technically be correct as it's not precisely defined by docs. */
2056 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2057 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2059 if (color & 0xffffff) diff_count2++;
2061 else
2063 DWORD r = (color & 0xff0000) >> 16;
2064 DWORD g = (color & 0xff00) >> 8;
2065 DWORD b = (color & 0xff);
2067 if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2068 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2073 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2074 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2076 ok(diff_count == 0 || diff_count2 == 0,
2077 "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2078 MIN(diff_count, diff_count2), i, i1);
2080 loadpoint.x /= 2;
2081 loadpoint.y /= 2;
2082 loadrect.top /= 2;
2083 loadrect.left /= 2;
2084 loadrect.right = (loadrect.right + 1) / 2;
2085 loadrect.bottom = (loadrect.bottom + 1) / 2;
2089 for (i = 0; i < 2; i++)
2090 for (i1 = 5; i1 >= 0; i1--)
2091 for (i2 = 7; i2 >= 0; i2--)
2093 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2095 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2097 /* Test cubemap loading from regular texture. */
2098 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2099 ddsd.dwSize = sizeof(ddsd);
2100 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2101 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2102 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2103 ddsd.dwWidth = 128;
2104 ddsd.dwHeight = 128;
2105 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2106 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2107 if (FAILED(hr)) goto out;
2109 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2110 ddsd.dwSize = sizeof(ddsd);
2111 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2112 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2113 ddsd.dwWidth = 128;
2114 ddsd.dwHeight = 128;
2115 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2116 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2117 if (FAILED(hr)) goto out;
2119 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2120 DDSCAPS2_CUBEMAP_ALLFACES);
2121 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2123 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2124 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2125 IDirectDrawSurface7_Release(texture_levels[0][0]);
2126 memset(texture_levels, 0, sizeof(texture_levels));
2128 /* Test cubemap loading from cubemap with different number of faces. */
2129 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2130 ddsd.dwSize = sizeof(ddsd);
2131 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2132 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2133 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2134 ddsd.dwWidth = 128;
2135 ddsd.dwHeight = 128;
2136 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2137 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2138 if (FAILED(hr)) goto out;
2140 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2141 ddsd.dwSize = sizeof(ddsd);
2142 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2143 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2144 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2145 ddsd.dwWidth = 128;
2146 ddsd.dwHeight = 128;
2147 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2148 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2149 if (FAILED(hr)) goto out;
2151 /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2152 (the above created cubemaps will have all faces. */
2153 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2154 DDSCAPS2_CUBEMAP_ALLFACES);
2155 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2157 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2158 DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2159 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2161 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2162 DDSCAPS2_CUBEMAP_POSITIVEX);
2163 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2165 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2166 DDSCAPS2_CUBEMAP_ALLFACES);
2167 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2169 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2170 DDSCAPS2_CUBEMAP_POSITIVEX);
2171 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2173 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2174 DDSCAPS2_CUBEMAP_POSITIVEZ);
2175 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2177 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2178 IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2179 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2182 /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2183 for (i = 0; i < 2; i++)
2185 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2186 ddsd.dwSize = sizeof(ddsd);
2187 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2188 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2189 ddsd.dwWidth = 128;
2190 ddsd.dwHeight = 128;
2191 U2(ddsd).dwMipMapCount = i ? 4 : 8;
2192 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2193 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2194 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2195 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2196 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2197 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2198 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2199 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2200 if (FAILED(hr)) goto out;
2202 /* Check the number of created mipmaps */
2203 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2204 ddsd.dwSize = sizeof(ddsd);
2205 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2206 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2207 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2208 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2210 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2212 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2213 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2214 if (FAILED(hr)) goto out;
2218 for (i1 = 0; i1 < 8; i1++)
2220 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2221 ddsd.dwSize = sizeof(ddsd);
2222 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2223 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2224 if (FAILED(hr)) goto out;
2226 for (y = 0 ; y < ddsd.dwHeight; y++)
2228 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2230 for (x = 0; x < ddsd.dwWidth; x++)
2232 /* x stored in green component, y in blue. */
2233 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2234 *textureRow++ = color;
2238 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2239 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2242 for (i1 = 0; i1 < 4; i1++)
2244 memset(&ddbltfx, 0, sizeof(ddbltfx));
2245 ddbltfx.dwSize = sizeof(ddbltfx);
2246 U5(ddbltfx).dwFillColor = 0;
2247 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2248 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2251 loadpoint.x = loadpoint.y = 31;
2252 loadrect.left = 30;
2253 loadrect.top = 20;
2254 loadrect.right = 93;
2255 loadrect.bottom = 52;
2257 /* Destination mip levels are a subset of source mip levels. */
2258 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2259 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2261 for (i1 = 0; i1 < 4; i1++)
2263 diff_count = 0;
2264 diff_count2 = 0;
2266 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2267 ddsd.dwSize = sizeof(ddsd);
2268 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2269 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2270 if (FAILED(hr)) goto out;
2272 for (y = 0 ; y < ddsd.dwHeight; y++)
2274 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2276 for (x = 0; x < ddsd.dwWidth; x++)
2278 DWORD color = *textureRow++;
2280 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2281 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2283 if (color & 0xffffff) diff_count++;
2285 else
2287 DWORD r = (color & 0xff0000) >> 16;
2288 DWORD g = (color & 0xff00) >> 8;
2289 DWORD b = (color & 0xff);
2291 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2292 b != y + loadrect.top - loadpoint.y) diff_count++;
2295 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2296 technically be correct as it's not precisely defined by docs. */
2297 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2298 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2300 if (color & 0xffffff) diff_count2++;
2302 else
2304 DWORD r = (color & 0xff0000) >> 16;
2305 DWORD g = (color & 0xff00) >> 8;
2306 DWORD b = (color & 0xff);
2308 if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2309 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2314 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2315 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2317 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2318 MIN(diff_count, diff_count2), i1);
2320 loadpoint.x /= 2;
2321 loadpoint.y /= 2;
2322 loadrect.top /= 2;
2323 loadrect.left /= 2;
2324 loadrect.right = (loadrect.right + 1) / 2;
2325 loadrect.bottom = (loadrect.bottom + 1) / 2;
2328 /* Destination mip levels are a superset of source mip levels (should fail). */
2329 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2330 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2332 for (i = 0; i < 2; i++)
2334 for (i1 = 7; i1 >= 0; i1--)
2336 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2339 memset(texture_levels, 0, sizeof(texture_levels));
2341 /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2342 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2343 ddsd.dwSize = sizeof(ddsd);
2344 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2345 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2346 ddsd.dwWidth = 128;
2347 ddsd.dwHeight = 128;
2348 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2349 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2350 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2351 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2352 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2353 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2354 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2355 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2356 if (FAILED(hr)) goto out;
2358 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2359 ddsd.dwSize = sizeof(ddsd);
2360 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2361 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2362 ddsd.dwWidth = 32;
2363 ddsd.dwHeight = 32;
2364 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2365 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2366 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2367 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2368 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2369 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2370 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2371 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2372 if (FAILED(hr)) goto out;
2374 for (i1 = 1; i1 < 8; i1++)
2376 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2377 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2378 if (FAILED(hr)) goto out;
2381 for (i1 = 0; i1 < 8; i1++)
2383 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2384 ddsd.dwSize = sizeof(ddsd);
2385 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2386 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2387 if (FAILED(hr)) goto out;
2389 for (y = 0 ; y < ddsd.dwHeight; y++)
2391 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2393 for (x = 0; x < ddsd.dwWidth; x++)
2395 /* x stored in green component, y in blue. */
2396 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2397 *textureRow++ = color;
2401 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2402 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2405 memset(&ddbltfx, 0, sizeof(ddbltfx));
2406 ddbltfx.dwSize = sizeof(ddbltfx);
2407 U5(ddbltfx).dwFillColor = 0;
2408 hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2409 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2411 loadpoint.x = loadpoint.y = 32;
2412 loadrect.left = 32;
2413 loadrect.top = 32;
2414 loadrect.right = 96;
2415 loadrect.bottom = 96;
2417 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2418 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2420 loadpoint.x /= 4;
2421 loadpoint.y /= 4;
2422 loadrect.top /= 4;
2423 loadrect.left /= 4;
2424 loadrect.right = (loadrect.right + 3) / 4;
2425 loadrect.bottom = (loadrect.bottom + 3) / 4;
2427 /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2428 * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2429 * copied subrectangles divided more than needed, without apparent logic. But it works
2430 * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2431 * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2432 * The following code attempts to detect broken results, actual tests will then be skipped
2434 load_mip_subset_broken = TRUE;
2435 diff_count = 0;
2437 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2438 ddsd.dwSize = sizeof(ddsd);
2439 hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2440 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2441 if (FAILED(hr)) goto out;
2443 for (y = 0 ; y < ddsd.dwHeight; y++)
2445 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2447 for (x = 0; x < ddsd.dwWidth; x++)
2449 DWORD color = *textureRow++;
2451 if (x < 2 || x >= 2 + 4 ||
2452 y < 2 || y >= 2 + 4)
2454 if (color & 0xffffff) diff_count++;
2456 else
2458 DWORD r = (color & 0xff0000) >> 16;
2460 if ((r & (0xf0)) != 0xf0) diff_count++;
2465 if (diff_count) load_mip_subset_broken = FALSE;
2467 if (load_mip_subset_broken) {
2468 skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2469 } else {
2470 diff_count = 0;
2472 for (y = 0 ; y < ddsd.dwHeight; y++)
2474 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2476 for (x = 0; x < ddsd.dwWidth; x++)
2478 DWORD color = *textureRow++;
2480 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2481 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2483 if (color & 0xffffff) diff_count++;
2485 else
2487 DWORD r = (color & 0xff0000) >> 16;
2488 DWORD g = (color & 0xff00) >> 8;
2489 DWORD b = (color & 0xff);
2491 if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2492 b != y + loadrect.top - loadpoint.y) diff_count++;
2498 hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2499 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2501 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2503 for (i = 0; i < 2; i++)
2505 for (i1 = 7; i1 >= 0; i1--)
2507 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2510 memset(texture_levels, 0, sizeof(texture_levels));
2512 if (!load_mip_subset_broken)
2514 /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2515 * surface (than first source mip level)
2517 for (i = 0; i < 2; i++)
2519 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2520 ddsd.dwSize = sizeof(ddsd);
2521 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2522 if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2523 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2524 ddsd.dwWidth = i ? 32 : 128;
2525 ddsd.dwHeight = i ? 32 : 128;
2526 if (i) U2(ddsd).dwMipMapCount = 4;
2527 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2528 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2529 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2530 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2531 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2532 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2533 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2534 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2535 if (FAILED(hr)) goto out;
2537 /* Check the number of created mipmaps */
2538 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2539 ddsd.dwSize = sizeof(ddsd);
2540 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2541 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2542 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2543 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2545 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2547 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2548 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2549 if (FAILED(hr)) goto out;
2553 for (i1 = 0; i1 < 8; i1++)
2555 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2556 ddsd.dwSize = sizeof(ddsd);
2557 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2558 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2559 if (FAILED(hr)) goto out;
2561 for (y = 0 ; y < ddsd.dwHeight; y++)
2563 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2565 for (x = 0; x < ddsd.dwWidth; x++)
2567 /* x stored in green component, y in blue. */
2568 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2569 *textureRow++ = color;
2573 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2574 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2577 for (i1 = 0; i1 < 4; i1++)
2579 memset(&ddbltfx, 0, sizeof(ddbltfx));
2580 ddbltfx.dwSize = sizeof(ddbltfx);
2581 U5(ddbltfx).dwFillColor = 0;
2582 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2583 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2586 loadpoint.x = loadpoint.y = 0;
2587 loadrect.left = 0;
2588 loadrect.top = 0;
2589 loadrect.right = 64;
2590 loadrect.bottom = 64;
2592 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2593 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2595 i = 0;
2596 for (i1 = 0; i1 < 8 && i < 4; i1++)
2598 DDSURFACEDESC2 ddsd2;
2600 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2601 ddsd.dwSize = sizeof(ddsd);
2602 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2604 memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2605 ddsd2.dwSize = sizeof(ddsd2);
2606 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2608 if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2610 diff_count = 0;
2612 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2613 ddsd.dwSize = sizeof(ddsd);
2614 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2615 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2616 if (FAILED(hr)) goto out;
2618 for (y = 0 ; y < ddsd.dwHeight; y++)
2620 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2622 for (x = 0; x < ddsd.dwWidth; x++)
2624 DWORD color = *textureRow++;
2626 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2627 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2629 if (color & 0xffffff) diff_count++;
2631 else
2633 DWORD r = (color & 0xff0000) >> 16;
2634 DWORD g = (color & 0xff00) >> 8;
2635 DWORD b = (color & 0xff);
2637 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2638 b != y + loadrect.top - loadpoint.y) diff_count++;
2643 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2644 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2646 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2648 i++;
2651 loadpoint.x /= 2;
2652 loadpoint.y /= 2;
2653 loadrect.top /= 2;
2654 loadrect.left /= 2;
2655 loadrect.right = (loadrect.right + 1) / 2;
2656 loadrect.bottom = (loadrect.bottom + 1) / 2;
2659 for (i = 0; i < 2; i++)
2661 for (i1 = 7; i1 >= 0; i1--)
2663 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2666 memset(texture_levels, 0, sizeof(texture_levels));
2669 /* Test palette copying. */
2670 for (i = 0; i < 2; i++)
2672 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2673 ddsd.dwSize = sizeof(ddsd);
2674 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2675 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2676 ddsd.dwWidth = 128;
2677 ddsd.dwHeight = 128;
2678 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2679 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2680 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2681 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2682 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2683 if (FAILED(hr)) goto out;
2685 /* Check the number of created mipmaps */
2686 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2687 ddsd.dwSize = sizeof(ddsd);
2688 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2689 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2690 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2691 if (U2(ddsd).dwMipMapCount != 8) goto out;
2693 for (i1 = 1; i1 < 8; i1++)
2695 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2696 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2697 if (FAILED(hr)) goto out;
2701 memset(table1, 0, sizeof(table1));
2702 for (i = 0; i < 3; i++)
2704 table1[0].peBlue = i + 1;
2705 hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2706 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2707 if (FAILED(hr))
2709 skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2710 goto out;
2714 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2715 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2717 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2718 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2720 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2721 ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2723 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2724 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2725 hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2726 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2728 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2729 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2731 memset(table1, 0, sizeof(table1));
2732 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2733 ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2734 if (SUCCEEDED(hr))
2736 hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2737 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2738 ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2741 /* Test colorkey copying. */
2742 ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2743 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2744 ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2745 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2746 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2748 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2749 ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2751 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2752 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2754 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2755 ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2756 ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2757 "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2759 out:
2761 for (i = 0; i < 5; i++)
2763 if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2766 for (i = 0; i < 2; i++)
2768 for (i1 = 7; i1 >= 0; i1--)
2770 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2774 for (i = 0; i < 2; i++)
2775 for (i1 = 5; i1 >= 0; i1--)
2776 for (i2 = 7; i2 >= 0; i2--)
2778 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2782 static void SetMaterialTest(void)
2784 HRESULT rc;
2786 rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2787 ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2790 static void ComputeSphereVisibility(void)
2792 D3DMATRIX proj, view, world;
2793 D3DVALUE radius[3];
2794 D3DVECTOR center[3];
2795 DWORD result[3];
2796 HRESULT rc;
2798 world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2799 world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2800 world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2801 world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2803 view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2804 view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2805 view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2806 view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2808 proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2809 proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2810 proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2811 proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2813 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2814 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2815 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2817 center[0].x=11.461533;
2818 center[0].y=-4.761727;
2819 center[0].z=-1.171646;
2821 radius[0]=38.252632;
2823 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2825 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2826 ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2828 center[0].x=-3.515620; center[0].y=-1.560661; center[0].z=-12.464638;
2829 radius[0]=4.354097;
2830 center[1].x=14.290396; center[1].y=-2.981143; center[1].z=-24.311312;
2831 radius[1]=12.500704;
2832 center[2].x=1.461626; center[2].y=-6.093709, center[2].z=-13.901010;
2833 radius[2]=17.251318;
2835 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2837 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2838 ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2839 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2840 ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2841 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2842 ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2844 view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2845 view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2846 view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2847 view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2849 proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2850 proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2851 proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2852 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2854 center[0].x=0.0;
2855 center[0].y=0.0;
2856 center[0].z=0.05;
2858 radius[0]=0.04;
2860 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2861 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2863 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2865 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2866 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2868 proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2869 proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2870 proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2871 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2873 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2875 center[0].x=0.0;
2876 center[0].y=0.0;
2877 center[0].z=0.5;
2879 radius[0]=0.5;
2881 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2883 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2884 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2886 center[0].x=0.0;
2887 center[0].y=0.0;
2888 center[0].z=0.0;
2890 radius[0]=0.0;
2892 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2894 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2895 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2897 center[0].x=-1.0;
2898 center[0].y=-1.0;
2899 center[0].z=0.50;
2901 radius[0]=0.25;
2903 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2905 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2906 ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
2908 center[0].x=-20.0;
2909 center[0].y=0.0;
2910 center[0].z=0.50;
2912 radius[0]=3.0;
2914 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2916 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2917 ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2919 center[0].x=20.0;
2920 center[0].y=0.0;
2921 center[0].z=0.50;
2923 radius[0]=3.0f;
2925 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2927 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2928 ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
2930 center[0].x=0.0;
2931 center[0].y=-20.0;
2932 center[0].z=0.50;
2934 radius[0]=3.0;
2936 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2938 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2939 ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
2941 center[0].x=0.0;
2942 center[0].y=20.0;
2943 center[0].z=0.5;
2945 radius[0]=3.0;
2947 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2949 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2950 ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
2952 center[0].x=0.0;
2953 center[0].y=0.0;
2954 center[0].z=-20;
2956 radius[0]=3.0;
2958 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2960 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2961 ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
2963 center[0].x=0.0;
2964 center[0].y=0.0;
2965 center[0].z=20.0;
2967 radius[0]=3.0;
2969 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2971 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2972 ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
2975 START_TEST(d3d)
2977 init_function_pointers();
2978 if(!pDirectDrawCreateEx) {
2979 win_skip("function DirectDrawCreateEx not available\n");
2980 return;
2983 if(!CreateDirect3D()) {
2984 skip("Skipping d3d7 tests\n");
2985 } else {
2986 LightTest();
2987 ProcessVerticesTest();
2988 StateTest();
2989 SceneTest();
2990 LimitTest();
2991 D3D7EnumTest();
2992 SetMaterialTest();
2993 ComputeSphereVisibility();
2994 CapsTest();
2995 VertexBufferDescTest();
2996 D3D7_OldRenderStateTest();
2997 DeviceLoadTest();
2998 ReleaseDirect3D();
3001 if (!D3D1_createObjects()) {
3002 skip("Skipping d3d1 tests\n");
3003 } else {
3004 Direct3D1Test();
3005 TextureLoadTest();
3006 D3D1_releaseObjects();