push 8c61147e396035865ef2da2e6aa2d0f3b0907179
[wine/hacks.git] / dlls / ddraw / tests / d3d.c
blobf4cd07b3fa070565f794592814d30fd53769c78f
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 if (hr == E_NOINTERFACE) return FALSE;
955 ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
956 if (!Direct3D1) {
957 return FALSE;
960 memset(&ddsd, 0, sizeof(ddsd));
961 ddsd.dwSize = sizeof(ddsd);
962 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
963 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
964 ddsd.dwWidth = 256;
965 ddsd.dwHeight = 256;
966 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
967 if (!Surface1) {
968 skip("DDSCAPS_3DDEVICE surface not available\n");
969 return FALSE;
972 hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
973 ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
974 if(!Direct3DDevice1) {
975 return FALSE;
978 memset(&desc, 0, sizeof(desc));
979 desc.dwSize = sizeof(desc);
980 desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
981 desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
982 desc.dwBufferSize = 128;
983 desc.lpData = NULL;
984 hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
985 ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
986 if(!ExecuteBuffer) {
987 return FALSE;
990 hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
991 ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
992 if(!Viewport) {
993 return FALSE;
996 hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
997 ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
999 hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
1000 ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1001 vp_data.dwSize = sizeof(vp_data);
1002 vp_data.dwX = 0;
1003 vp_data.dwY = 0;
1004 vp_data.dwWidth = 256;
1005 vp_data.dwHeight = 256;
1006 vp_data.dvScaleX = 1;
1007 vp_data.dvScaleY = 1;
1008 vp_data.dvMaxX = 256;
1009 vp_data.dvMaxY = 256;
1010 vp_data.dvMinZ = 0;
1011 vp_data.dvMaxZ = 1;
1012 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1013 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1015 hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1016 ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1017 if (!Light)
1018 return FALSE;
1020 return TRUE;
1023 static void D3D1_releaseObjects(void)
1025 if (Light) IDirect3DLight_Release(Light);
1026 if (Viewport) IDirect3DViewport_Release(Viewport);
1027 if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1028 if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1029 if (Surface1) IDirectDrawSurface_Release(Surface1);
1030 if (Direct3D1) IDirect3D_Release(Direct3D1);
1031 if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1034 #define SET_VP_DATA(vp_data) \
1035 vp_data.dwSize = sizeof(vp_data); \
1036 vp_data.dwX = 0; \
1037 vp_data.dwY = 0; \
1038 vp_data.dwWidth = 256; \
1039 vp_data.dwHeight = 256; \
1040 vp_data.dvMaxX = 256; \
1041 vp_data.dvMaxY = 256; \
1042 vp_data.dvScaleX = 5; \
1043 vp_data.dvScaleY = 5; \
1044 vp_data.dvMinZ = -25; \
1045 vp_data.dvMaxZ = 60;
1047 static void Direct3D1Test(void)
1049 HRESULT hr;
1050 D3DEXECUTEBUFFERDESC desc;
1051 D3DVIEWPORT vp_data;
1052 D3DINSTRUCTION *instr;
1053 D3DBRANCH *branch;
1054 IDirect3D *Direct3D_alt;
1055 IDirect3DLight *d3dlight;
1056 ULONG refcount;
1057 unsigned int idx = 0;
1058 static struct v_in testverts[] = {
1059 {0.0, 0.0, 0.0}, { 1.0, 1.0, 1.0}, {-1.0, -1.0, -1.0},
1060 {0.5, 0.5, 0.5}, {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1062 static struct v_in cliptest[] = {
1063 {25.59, 25.59, 1.0}, {-25.59, -25.59, 0.0},
1064 {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1066 static struct v_in offscreentest[] = {
1067 {128.1, 0.0, 0.0},
1069 struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1070 D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1071 D3DTRANSFORMDATA transformdata;
1072 DWORD i = FALSE;
1074 /* Interface consistency check. */
1075 hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1076 ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1077 if (hr == D3D_OK)
1078 ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1080 memset(&desc, 0, sizeof(desc));
1081 desc.dwSize = sizeof(desc);
1082 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1083 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1085 memset(desc.lpData, 0, 128);
1086 instr = desc.lpData;
1087 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1088 instr[idx].bSize = sizeof(*branch);
1089 instr[idx].wCount = 1;
1090 idx++;
1091 branch = (D3DBRANCH *) &instr[idx];
1092 branch->dwMask = 0x0;
1093 branch->dwValue = 1;
1094 branch->bNegate = TRUE;
1095 branch->dwOffset = 0;
1096 idx += (sizeof(*branch) / sizeof(*instr));
1097 instr[idx].bOpcode = D3DOP_EXIT;
1098 instr[idx].bSize = 0;
1099 instr[idx].wCount = 0;
1100 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1101 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1103 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1104 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1106 memset(&desc, 0, sizeof(desc));
1107 desc.dwSize = sizeof(desc);
1109 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1110 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1112 memset(desc.lpData, 0, 128);
1113 instr = desc.lpData;
1114 idx = 0;
1115 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1116 instr[idx].bSize = sizeof(*branch);
1117 instr[idx].wCount = 1;
1118 idx++;
1119 branch = (D3DBRANCH *) &instr[idx];
1120 branch->dwMask = 0x0;
1121 branch->dwValue = 1;
1122 branch->bNegate = TRUE;
1123 branch->dwOffset = 64;
1124 instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1125 instr[0].bOpcode = D3DOP_EXIT;
1126 instr[0].bSize = 0;
1127 instr[0].wCount = 0;
1128 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1129 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1131 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1132 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1134 /* Test rendering 0 triangles */
1135 memset(&desc, 0, sizeof(desc));
1136 desc.dwSize = sizeof(desc);
1138 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1139 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1141 memset(desc.lpData, 0, 128);
1142 instr = desc.lpData;
1143 idx = 0;
1145 instr->bOpcode = D3DOP_TRIANGLE;
1146 instr->bSize = sizeof(D3DOP_TRIANGLE);
1147 instr->wCount = 0;
1148 instr++;
1149 instr->bOpcode = D3DOP_EXIT;
1150 instr->bSize = 0;
1151 instr->wCount = 0;
1152 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1153 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1155 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1156 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1158 memset(&transformdata, 0, sizeof(transformdata));
1159 transformdata.dwSize = sizeof(transformdata);
1160 transformdata.lpIn = testverts;
1161 transformdata.dwInSize = sizeof(testverts[0]);
1162 transformdata.lpOut = out;
1163 transformdata.dwOutSize = sizeof(out[0]);
1165 transformdata.lpHOut = NULL;
1166 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1167 &transformdata, D3DTRANSFORM_UNCLIPPED,
1168 &i);
1169 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1171 transformdata.lpHOut = outH;
1172 memset(outH, 0xcc, sizeof(outH));
1173 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1174 &transformdata, D3DTRANSFORM_UNCLIPPED,
1175 &i);
1176 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1177 ok(i == 0, "Offscreen is %d\n", i);
1179 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1180 static const struct v_out cmp[] = {
1181 {128.0, 128.0, 0.0, 1}, {129.0, 127.0, 1.0, 1}, {127.0, 129.0, -1, 1},
1182 {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5, 0, 1}
1185 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1186 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1187 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1188 out[i].x, out[i].y, out[i].z, out[i].rhw,
1189 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1191 for(i = 0; i < sizeof(outH); i++) {
1192 if(((unsigned char *) outH)[i] != 0xcc) {
1193 ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1194 break;
1198 SET_VP_DATA(vp_data);
1199 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1200 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1201 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1202 &transformdata, D3DTRANSFORM_UNCLIPPED,
1203 &i);
1204 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1205 ok(i == 0, "Offscreen is %d\n", i);
1207 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1208 static const struct v_out cmp[] = {
1209 {128.0, 128.0, 0.0, 1}, {133.0, 123.0, 1.0, 1}, {123.0, 133.0, -1, 1},
1210 {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5, 0, 1}
1212 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1213 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1214 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1215 out[i].x, out[i].y, out[i].z, out[i].rhw,
1216 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1219 SET_VP_DATA(vp_data);
1220 vp_data.dwX = 10;
1221 vp_data.dwY = 20;
1222 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1223 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1224 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1225 &transformdata, D3DTRANSFORM_UNCLIPPED,
1226 &i);
1227 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1228 ok(i == 0, "Offscreen is %d\n", i);
1229 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1230 static const struct v_out cmp[] = {
1231 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, {133.0, 153.0, -1, 1},
1232 {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5, 0, 1}
1234 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1235 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1236 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1237 out[i].x, out[i].y, out[i].z, out[i].rhw,
1238 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1241 memset(out, 0xcc, sizeof(out));
1242 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1243 &transformdata, D3DTRANSFORM_CLIPPED,
1244 &i);
1245 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1246 ok(i == 0, "Offscreen is %d\n", i);
1247 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1248 static const D3DHVERTEX cmpH[] = {
1249 {0, { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1250 {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1251 {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1253 ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1254 U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1255 "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1256 outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1257 cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1259 /* No scheme has been found behind those return values. It seems to be
1260 * whatever data windows has when throwing the vertex away. Modify the
1261 * input test vertices to test this more. Depending on the input data
1262 * it can happen that the z coord gets written into y, or similar things
1264 if(0)
1266 static const struct v_out cmp[] = {
1267 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, { -1.0, -1.0, 0.5, 1},
1268 {140.5, 145.5, 0.5, 1}, { -0.5, -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1270 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1271 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1272 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1273 out[i].x, out[i].y, out[i].z, out[i].rhw,
1274 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1277 for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1278 ok(((DWORD *) out)[i] != 0xcccccccc,
1279 "Regular output DWORD %d remained untouched\n", i);
1282 transformdata.lpIn = cliptest;
1283 transformdata.dwInSize = sizeof(cliptest[0]);
1284 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1285 &transformdata, D3DTRANSFORM_CLIPPED,
1286 &i);
1287 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1288 ok(i == 0, "Offscreen is %d\n", i);
1289 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1290 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1294 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
1295 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1297 ok(Flags[i] == outH[i].dwFlags,
1298 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1299 outH[i].dwFlags, Flags[i]);
1302 SET_VP_DATA(vp_data);
1303 vp_data.dwWidth = 10;
1304 vp_data.dwHeight = 1000;
1305 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1306 i = 10;
1307 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1308 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1309 &transformdata, D3DTRANSFORM_CLIPPED,
1310 &i);
1311 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1312 ok(i == 0, "Offscreen is %d\n", i);
1313 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1314 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1316 D3DCLIP_RIGHT,
1317 D3DCLIP_LEFT,
1318 D3DCLIP_RIGHT | D3DCLIP_BACK,
1319 D3DCLIP_LEFT | D3DCLIP_FRONT,
1321 ok(Flags[i] == outH[i].dwFlags,
1322 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1323 outH[i].dwFlags, Flags[i]);
1326 SET_VP_DATA(vp_data);
1327 vp_data.dwWidth = 256;
1328 vp_data.dwHeight = 256;
1329 vp_data.dvScaleX = 1;
1330 vp_data.dvScaleY = 1;
1331 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1332 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1333 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1334 &transformdata, D3DTRANSFORM_CLIPPED,
1335 &i);
1336 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1337 ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1338 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1339 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1343 D3DCLIP_BACK,
1344 D3DCLIP_FRONT,
1346 ok(Flags[i] == outH[i].dwFlags,
1347 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1348 outH[i].dwFlags, Flags[i]);
1351 /* Finally try to figure out how the DWORD dwOffscreen works.
1352 * Apparently no vertex is offscreen with clipping off,
1353 * and with clipping on the offscreen flag is set if only one vertex
1354 * is transformed, and this vertex is offscreen.
1356 SET_VP_DATA(vp_data);
1357 vp_data.dwWidth = 5;
1358 vp_data.dwHeight = 5;
1359 vp_data.dvScaleX = 10000;
1360 vp_data.dvScaleY = 10000;
1361 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1362 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1363 transformdata.lpIn = cliptest;
1364 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1365 &transformdata, D3DTRANSFORM_UNCLIPPED,
1366 &i);
1367 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1368 ok(i == 0, "Offscreen is %d\n", i);
1369 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1370 &transformdata, D3DTRANSFORM_CLIPPED,
1371 &i);
1372 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1373 ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1374 hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1375 &transformdata, D3DTRANSFORM_CLIPPED,
1376 &i);
1377 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1378 ok(i == 0, "Offscreen is %d\n", i);
1379 transformdata.lpIn = cliptest + 1;
1380 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1381 &transformdata, D3DTRANSFORM_CLIPPED,
1382 &i);
1383 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1384 ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1386 transformdata.lpIn = offscreentest;
1387 transformdata.dwInSize = sizeof(offscreentest[0]);
1388 SET_VP_DATA(vp_data);
1389 vp_data.dwWidth = 257;
1390 vp_data.dwHeight = 257;
1391 vp_data.dvScaleX = 1;
1392 vp_data.dvScaleY = 1;
1393 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1394 i = 12345;
1395 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1396 &transformdata, D3DTRANSFORM_CLIPPED,
1397 &i);
1398 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1399 ok(i == 0, "Offscreen is %d\n", i);
1400 vp_data.dwWidth = 256;
1401 vp_data.dwHeight = 256;
1402 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1403 i = 12345;
1404 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1405 &transformdata, D3DTRANSFORM_CLIPPED,
1406 &i);
1407 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1408 ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1410 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1411 &transformdata, 0,
1412 &i);
1413 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1415 hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1416 ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1418 hr = IDirect3DViewport_AddLight(Viewport, Light);
1419 ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1420 refcount = getRefcount((IUnknown*) Light);
1421 ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1423 hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1424 ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1425 ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1426 refcount = getRefcount((IUnknown*) Light);
1427 ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1429 hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1430 ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1431 refcount = getRefcount((IUnknown*) Light);
1432 ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1434 IDirect3DLight_Release(Light);
1437 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1439 int i;
1441 for (i = 0; i < 256; i++) {
1442 if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1443 table1[i].peBlue != table2[i].peBlue) return FALSE;
1446 return TRUE;
1449 /* test palette handling in IDirect3DTexture_Load */
1450 static void TextureLoadTest(void)
1452 IDirectDrawSurface *TexSurface = NULL;
1453 IDirect3DTexture *Texture = NULL;
1454 IDirectDrawSurface *TexSurface2 = NULL;
1455 IDirect3DTexture *Texture2 = NULL;
1456 IDirectDrawPalette *palette = NULL;
1457 IDirectDrawPalette *palette2 = NULL;
1458 IDirectDrawPalette *palette_tmp = NULL;
1459 PALETTEENTRY table1[256], table2[256], table_tmp[256];
1460 HRESULT hr;
1461 DDSURFACEDESC ddsd;
1462 int i;
1464 memset (&ddsd, 0, sizeof (ddsd));
1465 ddsd.dwSize = sizeof (ddsd);
1466 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1467 ddsd.dwHeight = 128;
1468 ddsd.dwWidth = 128;
1469 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1470 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1471 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1472 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1474 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1475 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1476 if (FAILED(hr)) {
1477 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1478 goto cleanup;
1481 hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1482 (void *)&Texture);
1483 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1484 if (FAILED(hr)) {
1485 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1486 goto cleanup;
1489 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1490 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1491 if (FAILED(hr)) {
1492 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1493 goto cleanup;
1496 hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1497 (void *)&Texture2);
1498 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1499 if (FAILED(hr)) {
1500 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1501 goto cleanup;
1504 /* test load of Texture to Texture */
1505 hr = IDirect3DTexture_Load(Texture, Texture);
1506 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1508 /* test Load when both textures have no palette */
1509 hr = IDirect3DTexture_Load(Texture2, Texture);
1510 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1512 for (i = 0; i < 256; i++) {
1513 table1[i].peRed = i;
1514 table1[i].peGreen = i;
1515 table1[i].peBlue = i;
1516 table1[i].peFlags = 0;
1519 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1520 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1521 if (FAILED(hr)) {
1522 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1523 goto cleanup;
1526 /* test Load when source texture has palette and destination has no palette */
1527 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1528 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1529 hr = IDirect3DTexture_Load(Texture2, Texture);
1530 ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1532 for (i = 0; i < 256; i++) {
1533 table2[i].peRed = 255 - i;
1534 table2[i].peGreen = 255 - i;
1535 table2[i].peBlue = 255 - i;
1536 table2[i].peFlags = 0;
1539 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1540 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1541 if (FAILED(hr)) {
1542 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1543 goto cleanup;
1546 /* test Load when source has no palette and destination has a palette */
1547 hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1548 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1549 hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1550 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1551 hr = IDirect3DTexture_Load(Texture2, Texture);
1552 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1553 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1554 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1555 if (!palette_tmp) {
1556 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1557 goto cleanup;
1558 } else {
1559 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1560 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1561 ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1562 IDirectDrawPalette_Release(palette_tmp);
1565 /* test Load when both textures have palettes */
1566 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1567 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1568 hr = IDirect3DTexture_Load(Texture2, Texture);
1569 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1570 hr = IDirect3DTexture_Load(Texture2, Texture);
1571 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1572 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1573 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1574 if (!palette_tmp) {
1575 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1576 goto cleanup;
1577 } else {
1578 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1579 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1580 ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1581 IDirectDrawPalette_Release(palette_tmp);
1584 cleanup:
1586 if (palette) IDirectDrawPalette_Release(palette);
1587 if (palette2) IDirectDrawPalette_Release(palette2);
1588 if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1589 if (Texture) IDirect3DTexture_Release(Texture);
1590 if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1591 if (Texture2) IDirect3DTexture_Release(Texture2);
1594 static void VertexBufferDescTest(void)
1596 HRESULT rc;
1597 D3DVERTEXBUFFERDESC desc;
1598 union mem_t
1600 D3DVERTEXBUFFERDESC desc2;
1601 unsigned char buffer[512];
1602 } mem;
1604 memset(&desc, 0, sizeof(desc));
1605 desc.dwSize = sizeof(desc);
1606 desc.dwCaps = 0;
1607 desc.dwFVF = D3DFVF_XYZ;
1608 desc.dwNumVertices = 1;
1609 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1610 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1611 if (!lpVBufSrc)
1613 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1614 goto out;
1617 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1618 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1619 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1620 if(rc != D3D_OK)
1621 skip("GetVertexBuffer Failed!\n");
1622 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1623 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1624 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1625 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1626 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1628 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1629 mem.desc2.dwSize = 0;
1630 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1631 if(rc != D3D_OK)
1632 skip("GetVertexBuffer Failed!\n");
1633 ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1634 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1635 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1636 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1637 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1639 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1640 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1641 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1642 if(rc != D3D_OK)
1643 skip("GetVertexBuffer Failed!\n");
1644 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1645 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1646 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1647 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1648 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1650 out:
1651 IDirect3DVertexBuffer7_Release(lpVBufSrc);
1654 static void D3D7_OldRenderStateTest(void)
1656 HRESULT rc;
1657 DWORD val;
1659 /* Test reaction to some deprecated states in D3D7.
1661 * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1662 * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1663 * need not to be handled in D3D7.
1665 todo_wine {
1666 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1667 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1669 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1670 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1672 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1673 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1675 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1676 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1680 #define IS_VALUE_NEAR(a, b) ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1681 #define MIN(a, b) ((a) < (b) ? (a) : (b))
1683 static void DeviceLoadTest(void)
1685 DDSURFACEDESC2 ddsd;
1686 IDirectDrawSurface7 *texture_levels[2][8];
1687 IDirectDrawSurface7 *cube_face_levels[2][6][8];
1688 DWORD flags;
1689 HRESULT hr;
1690 DDBLTFX ddbltfx;
1691 RECT loadrect;
1692 POINT loadpoint;
1693 int i, i1, i2;
1694 unsigned diff_count = 0, diff_count2 = 0;
1695 unsigned x, y;
1696 BOOL load_mip_subset_broken = FALSE;
1697 IDirectDrawPalette *palettes[5];
1698 PALETTEENTRY table1[256];
1699 DDCOLORKEY ddckey;
1700 D3DDEVICEDESC7 d3dcaps;
1702 /* Test loading of texture subrectangle with a mipmap surface. */
1703 memset(texture_levels, 0, sizeof(texture_levels));
1704 memset(cube_face_levels, 0, sizeof(cube_face_levels));
1705 memset(palettes, 0, sizeof(palettes));
1707 for (i = 0; i < 2; i++)
1709 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1710 ddsd.dwSize = sizeof(ddsd);
1711 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1712 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1713 ddsd.dwWidth = 128;
1714 ddsd.dwHeight = 128;
1715 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1716 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1717 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1718 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1719 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1720 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1721 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1722 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1723 if (FAILED(hr)) goto out;
1725 /* Check the number of created mipmaps */
1726 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1727 ddsd.dwSize = sizeof(ddsd);
1728 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1729 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1730 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1731 if (U2(ddsd).dwMipMapCount != 8) goto out;
1733 for (i1 = 1; i1 < 8; i1++)
1735 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1736 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1737 if (FAILED(hr)) goto out;
1741 for (i1 = 0; i1 < 8; i1++)
1743 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1744 ddsd.dwSize = sizeof(ddsd);
1745 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1746 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1747 if (FAILED(hr)) goto out;
1749 for (y = 0 ; y < ddsd.dwHeight; y++)
1751 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1753 for (x = 0; x < ddsd.dwWidth; x++)
1755 /* x stored in green component, y in blue. */
1756 DWORD color = 0xff0000 | (x << 8) | y;
1757 *textureRow++ = color;
1761 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1762 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1765 for (i1 = 0; i1 < 8; i1++)
1767 memset(&ddbltfx, 0, sizeof(ddbltfx));
1768 ddbltfx.dwSize = sizeof(ddbltfx);
1769 U5(ddbltfx).dwFillColor = 0;
1770 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1771 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1774 /* First test some broken coordinates. */
1775 loadpoint.x = loadpoint.y = 0;
1776 loadrect.left = 0;
1777 loadrect.top = 0;
1778 loadrect.right = 0;
1779 loadrect.bottom = 0;
1780 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1781 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1783 loadpoint.x = loadpoint.y = 50;
1784 loadrect.left = 0;
1785 loadrect.top = 0;
1786 loadrect.right = 100;
1787 loadrect.bottom = 100;
1788 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1789 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1791 /* Test actual loading. */
1792 loadpoint.x = loadpoint.y = 31;
1793 loadrect.left = 30;
1794 loadrect.top = 20;
1795 loadrect.right = 93;
1796 loadrect.bottom = 52;
1798 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1799 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1801 for (i1 = 0; i1 < 8; i1++)
1803 diff_count = 0;
1804 diff_count2 = 0;
1806 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1807 ddsd.dwSize = sizeof(ddsd);
1808 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1809 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1810 if (FAILED(hr)) goto out;
1812 for (y = 0 ; y < ddsd.dwHeight; y++)
1814 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1816 for (x = 0; x < ddsd.dwWidth; x++)
1818 DWORD color = *textureRow++;
1820 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1821 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1823 if (color & 0xffffff) diff_count++;
1825 else
1827 DWORD r = (color & 0xff0000) >> 16;
1828 DWORD g = (color & 0xff00) >> 8;
1829 DWORD b = (color & 0xff);
1831 if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1834 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1835 technically be correct as it's not precisely defined by docs. */
1836 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1837 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1839 if (color & 0xffffff) diff_count2++;
1841 else
1843 DWORD r = (color & 0xff0000) >> 16;
1844 DWORD g = (color & 0xff00) >> 8;
1845 DWORD b = (color & 0xff);
1847 if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1848 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1853 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1854 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1856 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1857 MIN(diff_count, diff_count2), i1);
1859 loadpoint.x /= 2;
1860 loadpoint.y /= 2;
1861 loadrect.top /= 2;
1862 loadrect.left /= 2;
1863 loadrect.right = (loadrect.right + 1) / 2;
1864 loadrect.bottom = (loadrect.bottom + 1) / 2;
1867 /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1868 * qemu Win98 / directx7 / RGB software rasterizer):
1869 * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1870 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1873 /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1874 for (i = 0; i < 2; i++)
1876 for (i1 = 7; i1 >= 0; i1--)
1878 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1881 memset(texture_levels, 0, sizeof(texture_levels));
1883 /* Test texture size mismatch. */
1884 for (i = 0; i < 2; i++)
1886 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1887 ddsd.dwSize = sizeof(ddsd);
1888 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1889 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1890 ddsd.dwWidth = i ? 256 : 128;
1891 ddsd.dwHeight = 128;
1892 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1893 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1894 if (FAILED(hr)) goto out;
1897 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1898 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1900 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1901 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1903 IDirectDrawSurface7_Release(texture_levels[0][0]);
1904 IDirectDrawSurface7_Release(texture_levels[1][0]);
1905 memset(texture_levels, 0, sizeof(texture_levels));
1907 memset(&d3dcaps, 0, sizeof(d3dcaps));
1908 hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1909 ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1911 if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1913 skip("No cubemap support\n");
1915 else
1917 /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1918 for (i = 0; i < 2; i++)
1920 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1921 ddsd.dwSize = sizeof(ddsd);
1922 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1923 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1924 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1925 ddsd.dwWidth = 128;
1926 ddsd.dwHeight = 128;
1927 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1928 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1929 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1930 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1931 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1932 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1933 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1934 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1935 if (FAILED(hr)) goto out;
1937 flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1938 for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1940 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1941 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1942 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1943 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1944 if (FAILED(hr)) goto out;
1947 for (i1 = 0; i1 < 6; i1++)
1949 /* Check the number of created mipmaps */
1950 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1951 ddsd.dwSize = sizeof(ddsd);
1952 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1953 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1954 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1955 if (U2(ddsd).dwMipMapCount != 8) goto out;
1957 for (i2 = 1; i2 < 8; i2++)
1959 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1960 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1961 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1962 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1963 if (FAILED(hr)) goto out;
1968 for (i = 0; i < 6; i++)
1969 for (i1 = 0; i1 < 8; i1++)
1971 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1972 ddsd.dwSize = sizeof(ddsd);
1973 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1974 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1975 if (FAILED(hr)) goto out;
1977 for (y = 0 ; y < ddsd.dwHeight; y++)
1979 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1981 for (x = 0; x < ddsd.dwWidth; x++)
1983 /* face number in low 4 bits of red, x stored in green component, y in blue. */
1984 DWORD color = 0xf00000 | (i << 16) | (x << 8) | y;
1985 *textureRow++ = color;
1989 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1990 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1993 for (i = 0; i < 6; i++)
1994 for (i1 = 0; i1 < 8; i1++)
1996 memset(&ddbltfx, 0, sizeof(ddbltfx));
1997 ddbltfx.dwSize = sizeof(ddbltfx);
1998 U5(ddbltfx).dwFillColor = 0;
1999 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2000 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2003 loadpoint.x = loadpoint.y = 10;
2004 loadrect.left = 30;
2005 loadrect.top = 20;
2006 loadrect.right = 93;
2007 loadrect.bottom = 52;
2009 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2010 DDSCAPS2_CUBEMAP_ALLFACES);
2011 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2013 for (i = 0; i < 6; i++)
2015 loadpoint.x = loadpoint.y = 10;
2016 loadrect.left = 30;
2017 loadrect.top = 20;
2018 loadrect.right = 93;
2019 loadrect.bottom = 52;
2021 for (i1 = 0; i1 < 8; i1++)
2023 diff_count = 0;
2024 diff_count2 = 0;
2026 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2027 ddsd.dwSize = sizeof(ddsd);
2028 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2029 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2030 if (FAILED(hr)) goto out;
2032 for (y = 0 ; y < ddsd.dwHeight; y++)
2034 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2036 for (x = 0; x < ddsd.dwWidth; x++)
2038 DWORD color = *textureRow++;
2040 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2041 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2043 if (color & 0xffffff) diff_count++;
2045 else
2047 DWORD r = (color & 0xff0000) >> 16;
2048 DWORD g = (color & 0xff00) >> 8;
2049 DWORD b = (color & 0xff);
2051 if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2052 b != y + loadrect.top - loadpoint.y) diff_count++;
2055 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2056 technically be correct as it's not precisely defined by docs. */
2057 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2058 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2060 if (color & 0xffffff) diff_count2++;
2062 else
2064 DWORD r = (color & 0xff0000) >> 16;
2065 DWORD g = (color & 0xff00) >> 8;
2066 DWORD b = (color & 0xff);
2068 if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2069 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2074 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2075 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2077 ok(diff_count == 0 || diff_count2 == 0,
2078 "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2079 MIN(diff_count, diff_count2), i, i1);
2081 loadpoint.x /= 2;
2082 loadpoint.y /= 2;
2083 loadrect.top /= 2;
2084 loadrect.left /= 2;
2085 loadrect.right = (loadrect.right + 1) / 2;
2086 loadrect.bottom = (loadrect.bottom + 1) / 2;
2090 for (i = 0; i < 2; i++)
2091 for (i1 = 5; i1 >= 0; i1--)
2092 for (i2 = 7; i2 >= 0; i2--)
2094 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2096 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2098 /* Test cubemap loading from regular texture. */
2099 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2100 ddsd.dwSize = sizeof(ddsd);
2101 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2102 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2103 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2104 ddsd.dwWidth = 128;
2105 ddsd.dwHeight = 128;
2106 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2107 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2108 if (FAILED(hr)) goto out;
2110 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2111 ddsd.dwSize = sizeof(ddsd);
2112 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2113 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2114 ddsd.dwWidth = 128;
2115 ddsd.dwHeight = 128;
2116 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2117 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2118 if (FAILED(hr)) goto out;
2120 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2121 DDSCAPS2_CUBEMAP_ALLFACES);
2122 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2124 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2125 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2126 IDirectDrawSurface7_Release(texture_levels[0][0]);
2127 memset(texture_levels, 0, sizeof(texture_levels));
2129 /* Test cubemap loading from cubemap with different number of faces. */
2130 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2131 ddsd.dwSize = sizeof(ddsd);
2132 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2133 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2134 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2135 ddsd.dwWidth = 128;
2136 ddsd.dwHeight = 128;
2137 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2138 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2139 if (FAILED(hr)) goto out;
2141 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2142 ddsd.dwSize = sizeof(ddsd);
2143 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2144 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2145 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2146 ddsd.dwWidth = 128;
2147 ddsd.dwHeight = 128;
2148 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2149 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2150 if (FAILED(hr)) goto out;
2152 /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2153 (the above created cubemaps will have all faces. */
2154 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2155 DDSCAPS2_CUBEMAP_ALLFACES);
2156 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2158 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2159 DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2160 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2162 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2163 DDSCAPS2_CUBEMAP_POSITIVEX);
2164 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2166 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2167 DDSCAPS2_CUBEMAP_ALLFACES);
2168 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2170 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2171 DDSCAPS2_CUBEMAP_POSITIVEX);
2172 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2174 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2175 DDSCAPS2_CUBEMAP_POSITIVEZ);
2176 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2178 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2179 IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2180 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2183 /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2184 for (i = 0; i < 2; i++)
2186 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2187 ddsd.dwSize = sizeof(ddsd);
2188 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2189 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2190 ddsd.dwWidth = 128;
2191 ddsd.dwHeight = 128;
2192 U2(ddsd).dwMipMapCount = i ? 4 : 8;
2193 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2194 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2195 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2196 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2197 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2198 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2199 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2200 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2201 if (FAILED(hr)) goto out;
2203 /* Check the number of created mipmaps */
2204 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2205 ddsd.dwSize = sizeof(ddsd);
2206 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2207 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2208 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2209 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2211 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2213 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2214 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2215 if (FAILED(hr)) goto out;
2219 for (i1 = 0; i1 < 8; i1++)
2221 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2222 ddsd.dwSize = sizeof(ddsd);
2223 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2224 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2225 if (FAILED(hr)) goto out;
2227 for (y = 0 ; y < ddsd.dwHeight; y++)
2229 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2231 for (x = 0; x < ddsd.dwWidth; x++)
2233 /* x stored in green component, y in blue. */
2234 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2235 *textureRow++ = color;
2239 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2240 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2243 for (i1 = 0; i1 < 4; i1++)
2245 memset(&ddbltfx, 0, sizeof(ddbltfx));
2246 ddbltfx.dwSize = sizeof(ddbltfx);
2247 U5(ddbltfx).dwFillColor = 0;
2248 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2249 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2252 loadpoint.x = loadpoint.y = 31;
2253 loadrect.left = 30;
2254 loadrect.top = 20;
2255 loadrect.right = 93;
2256 loadrect.bottom = 52;
2258 /* Destination mip levels are a subset of source mip levels. */
2259 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2260 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2262 for (i1 = 0; i1 < 4; i1++)
2264 diff_count = 0;
2265 diff_count2 = 0;
2267 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2268 ddsd.dwSize = sizeof(ddsd);
2269 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2270 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2271 if (FAILED(hr)) goto out;
2273 for (y = 0 ; y < ddsd.dwHeight; y++)
2275 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2277 for (x = 0; x < ddsd.dwWidth; x++)
2279 DWORD color = *textureRow++;
2281 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2282 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2284 if (color & 0xffffff) diff_count++;
2286 else
2288 DWORD r = (color & 0xff0000) >> 16;
2289 DWORD g = (color & 0xff00) >> 8;
2290 DWORD b = (color & 0xff);
2292 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2293 b != y + loadrect.top - loadpoint.y) diff_count++;
2296 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2297 technically be correct as it's not precisely defined by docs. */
2298 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2299 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2301 if (color & 0xffffff) diff_count2++;
2303 else
2305 DWORD r = (color & 0xff0000) >> 16;
2306 DWORD g = (color & 0xff00) >> 8;
2307 DWORD b = (color & 0xff);
2309 if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2310 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2315 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2316 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2318 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2319 MIN(diff_count, diff_count2), i1);
2321 loadpoint.x /= 2;
2322 loadpoint.y /= 2;
2323 loadrect.top /= 2;
2324 loadrect.left /= 2;
2325 loadrect.right = (loadrect.right + 1) / 2;
2326 loadrect.bottom = (loadrect.bottom + 1) / 2;
2329 /* Destination mip levels are a superset of source mip levels (should fail). */
2330 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2331 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2333 for (i = 0; i < 2; i++)
2335 for (i1 = 7; i1 >= 0; i1--)
2337 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2340 memset(texture_levels, 0, sizeof(texture_levels));
2342 /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2343 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2344 ddsd.dwSize = sizeof(ddsd);
2345 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2346 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2347 ddsd.dwWidth = 128;
2348 ddsd.dwHeight = 128;
2349 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2350 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2351 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2352 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2353 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2354 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2355 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2356 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2357 if (FAILED(hr)) goto out;
2359 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2360 ddsd.dwSize = sizeof(ddsd);
2361 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2362 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2363 ddsd.dwWidth = 32;
2364 ddsd.dwHeight = 32;
2365 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2366 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2367 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2368 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2369 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2370 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2371 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2372 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2373 if (FAILED(hr)) goto out;
2375 for (i1 = 1; i1 < 8; i1++)
2377 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2378 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2379 if (FAILED(hr)) goto out;
2382 for (i1 = 0; i1 < 8; i1++)
2384 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2385 ddsd.dwSize = sizeof(ddsd);
2386 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2387 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2388 if (FAILED(hr)) goto out;
2390 for (y = 0 ; y < ddsd.dwHeight; y++)
2392 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2394 for (x = 0; x < ddsd.dwWidth; x++)
2396 /* x stored in green component, y in blue. */
2397 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2398 *textureRow++ = color;
2402 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2403 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2406 memset(&ddbltfx, 0, sizeof(ddbltfx));
2407 ddbltfx.dwSize = sizeof(ddbltfx);
2408 U5(ddbltfx).dwFillColor = 0;
2409 hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2410 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2412 loadpoint.x = loadpoint.y = 32;
2413 loadrect.left = 32;
2414 loadrect.top = 32;
2415 loadrect.right = 96;
2416 loadrect.bottom = 96;
2418 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2419 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2421 loadpoint.x /= 4;
2422 loadpoint.y /= 4;
2423 loadrect.top /= 4;
2424 loadrect.left /= 4;
2425 loadrect.right = (loadrect.right + 3) / 4;
2426 loadrect.bottom = (loadrect.bottom + 3) / 4;
2428 /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2429 * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2430 * copied subrectangles divided more than needed, without apparent logic. But it works
2431 * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2432 * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2433 * The following code attempts to detect broken results, actual tests will then be skipped
2435 load_mip_subset_broken = TRUE;
2436 diff_count = 0;
2438 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2439 ddsd.dwSize = sizeof(ddsd);
2440 hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2441 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2442 if (FAILED(hr)) goto out;
2444 for (y = 0 ; y < ddsd.dwHeight; y++)
2446 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2448 for (x = 0; x < ddsd.dwWidth; x++)
2450 DWORD color = *textureRow++;
2452 if (x < 2 || x >= 2 + 4 ||
2453 y < 2 || y >= 2 + 4)
2455 if (color & 0xffffff) diff_count++;
2457 else
2459 DWORD r = (color & 0xff0000) >> 16;
2461 if ((r & (0xf0)) != 0xf0) diff_count++;
2466 if (diff_count) load_mip_subset_broken = FALSE;
2468 if (load_mip_subset_broken) {
2469 skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2470 } else {
2471 diff_count = 0;
2473 for (y = 0 ; y < ddsd.dwHeight; y++)
2475 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2477 for (x = 0; x < ddsd.dwWidth; x++)
2479 DWORD color = *textureRow++;
2481 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2482 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2484 if (color & 0xffffff) diff_count++;
2486 else
2488 DWORD r = (color & 0xff0000) >> 16;
2489 DWORD g = (color & 0xff00) >> 8;
2490 DWORD b = (color & 0xff);
2492 if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2493 b != y + loadrect.top - loadpoint.y) diff_count++;
2499 hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2500 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2502 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2504 for (i = 0; i < 2; i++)
2506 for (i1 = 7; i1 >= 0; i1--)
2508 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2511 memset(texture_levels, 0, sizeof(texture_levels));
2513 if (!load_mip_subset_broken)
2515 /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2516 * surface (than first source mip level)
2518 for (i = 0; i < 2; i++)
2520 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2521 ddsd.dwSize = sizeof(ddsd);
2522 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2523 if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2524 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2525 ddsd.dwWidth = i ? 32 : 128;
2526 ddsd.dwHeight = i ? 32 : 128;
2527 if (i) U2(ddsd).dwMipMapCount = 4;
2528 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2529 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2530 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2531 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2532 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2533 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2534 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2535 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2536 if (FAILED(hr)) goto out;
2538 /* Check the number of created mipmaps */
2539 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2540 ddsd.dwSize = sizeof(ddsd);
2541 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2542 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2543 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2544 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2546 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2548 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2549 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2550 if (FAILED(hr)) goto out;
2554 for (i1 = 0; i1 < 8; i1++)
2556 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2557 ddsd.dwSize = sizeof(ddsd);
2558 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2559 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2560 if (FAILED(hr)) goto out;
2562 for (y = 0 ; y < ddsd.dwHeight; y++)
2564 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2566 for (x = 0; x < ddsd.dwWidth; x++)
2568 /* x stored in green component, y in blue. */
2569 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2570 *textureRow++ = color;
2574 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2575 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2578 for (i1 = 0; i1 < 4; i1++)
2580 memset(&ddbltfx, 0, sizeof(ddbltfx));
2581 ddbltfx.dwSize = sizeof(ddbltfx);
2582 U5(ddbltfx).dwFillColor = 0;
2583 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2584 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2587 loadpoint.x = loadpoint.y = 0;
2588 loadrect.left = 0;
2589 loadrect.top = 0;
2590 loadrect.right = 64;
2591 loadrect.bottom = 64;
2593 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2594 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2596 i = 0;
2597 for (i1 = 0; i1 < 8 && i < 4; i1++)
2599 DDSURFACEDESC2 ddsd2;
2601 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2602 ddsd.dwSize = sizeof(ddsd);
2603 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2605 memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2606 ddsd2.dwSize = sizeof(ddsd2);
2607 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2609 if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2611 diff_count = 0;
2613 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2614 ddsd.dwSize = sizeof(ddsd);
2615 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2616 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2617 if (FAILED(hr)) goto out;
2619 for (y = 0 ; y < ddsd.dwHeight; y++)
2621 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2623 for (x = 0; x < ddsd.dwWidth; x++)
2625 DWORD color = *textureRow++;
2627 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2628 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2630 if (color & 0xffffff) diff_count++;
2632 else
2634 DWORD r = (color & 0xff0000) >> 16;
2635 DWORD g = (color & 0xff00) >> 8;
2636 DWORD b = (color & 0xff);
2638 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2639 b != y + loadrect.top - loadpoint.y) diff_count++;
2644 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2645 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2647 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2649 i++;
2652 loadpoint.x /= 2;
2653 loadpoint.y /= 2;
2654 loadrect.top /= 2;
2655 loadrect.left /= 2;
2656 loadrect.right = (loadrect.right + 1) / 2;
2657 loadrect.bottom = (loadrect.bottom + 1) / 2;
2660 for (i = 0; i < 2; i++)
2662 for (i1 = 7; i1 >= 0; i1--)
2664 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2667 memset(texture_levels, 0, sizeof(texture_levels));
2670 /* Test palette copying. */
2671 for (i = 0; i < 2; i++)
2673 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2674 ddsd.dwSize = sizeof(ddsd);
2675 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2676 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2677 ddsd.dwWidth = 128;
2678 ddsd.dwHeight = 128;
2679 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2680 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2681 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2682 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2683 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2684 if (FAILED(hr)) goto out;
2686 /* Check the number of created mipmaps */
2687 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2688 ddsd.dwSize = sizeof(ddsd);
2689 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2690 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2691 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2692 if (U2(ddsd).dwMipMapCount != 8) goto out;
2694 for (i1 = 1; i1 < 8; i1++)
2696 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2697 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2698 if (FAILED(hr)) goto out;
2702 memset(table1, 0, sizeof(table1));
2703 for (i = 0; i < 3; i++)
2705 table1[0].peBlue = i + 1;
2706 hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2707 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2708 if (FAILED(hr))
2710 skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2711 goto out;
2715 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2716 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2718 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2719 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2721 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2722 ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2724 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2725 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2726 hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2727 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2729 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2730 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2732 memset(table1, 0, sizeof(table1));
2733 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2734 ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2735 if (SUCCEEDED(hr))
2737 hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2738 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2739 ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2742 /* Test colorkey copying. */
2743 ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2744 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2745 ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2746 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2747 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2749 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2750 ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2752 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2753 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2755 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2756 ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2757 ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2758 "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2760 out:
2762 for (i = 0; i < 5; i++)
2764 if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2767 for (i = 0; i < 2; i++)
2769 for (i1 = 7; i1 >= 0; i1--)
2771 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2775 for (i = 0; i < 2; i++)
2776 for (i1 = 5; i1 >= 0; i1--)
2777 for (i2 = 7; i2 >= 0; i2--)
2779 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2783 static void SetMaterialTest(void)
2785 HRESULT rc;
2787 rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2788 ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2791 static void ComputeSphereVisibility(void)
2793 D3DMATRIX proj, view, world;
2794 D3DVALUE radius[3];
2795 D3DVECTOR center[3];
2796 DWORD result[3];
2797 HRESULT rc;
2799 world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2800 world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2801 world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2802 world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2804 view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2805 view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2806 view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2807 view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2809 proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2810 proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2811 proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2812 proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2814 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2815 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2816 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2818 center[0].x=11.461533;
2819 center[0].y=-4.761727;
2820 center[0].z=-1.171646;
2822 radius[0]=38.252632;
2824 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2826 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2827 ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2829 center[0].x=-3.515620; center[0].y=-1.560661; center[0].z=-12.464638;
2830 radius[0]=4.354097;
2831 center[1].x=14.290396; center[1].y=-2.981143; center[1].z=-24.311312;
2832 radius[1]=12.500704;
2833 center[2].x=1.461626; center[2].y=-6.093709, center[2].z=-13.901010;
2834 radius[2]=17.251318;
2836 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2838 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2839 ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2840 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2841 ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2842 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2843 ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2845 view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2846 view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2847 view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2848 view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2850 proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2851 proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2852 proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2853 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2855 center[0].x=0.0;
2856 center[0].y=0.0;
2857 center[0].z=0.05;
2859 radius[0]=0.04;
2861 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2862 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2864 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2866 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2867 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2869 proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2870 proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2871 proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2872 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2874 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2876 center[0].x=0.0;
2877 center[0].y=0.0;
2878 center[0].z=0.5;
2880 radius[0]=0.5;
2882 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2884 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2885 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2887 center[0].x=0.0;
2888 center[0].y=0.0;
2889 center[0].z=0.0;
2891 radius[0]=0.0;
2893 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2895 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2896 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2898 center[0].x=-1.0;
2899 center[0].y=-1.0;
2900 center[0].z=0.50;
2902 radius[0]=0.25;
2904 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2906 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2907 ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
2909 center[0].x=-20.0;
2910 center[0].y=0.0;
2911 center[0].z=0.50;
2913 radius[0]=3.0;
2915 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2917 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2918 ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2920 center[0].x=20.0;
2921 center[0].y=0.0;
2922 center[0].z=0.50;
2924 radius[0]=3.0f;
2926 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2928 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2929 ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
2931 center[0].x=0.0;
2932 center[0].y=-20.0;
2933 center[0].z=0.50;
2935 radius[0]=3.0;
2937 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2939 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2940 ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
2942 center[0].x=0.0;
2943 center[0].y=20.0;
2944 center[0].z=0.5;
2946 radius[0]=3.0;
2948 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2950 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2951 ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
2953 center[0].x=0.0;
2954 center[0].y=0.0;
2955 center[0].z=-20;
2957 radius[0]=3.0;
2959 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2961 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2962 ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
2964 center[0].x=0.0;
2965 center[0].y=0.0;
2966 center[0].z=20.0;
2968 radius[0]=3.0;
2970 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2972 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2973 ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
2976 START_TEST(d3d)
2978 init_function_pointers();
2979 if(!pDirectDrawCreateEx) {
2980 win_skip("function DirectDrawCreateEx not available\n");
2981 return;
2984 if(!CreateDirect3D()) {
2985 skip("Skipping d3d7 tests\n");
2986 } else {
2987 LightTest();
2988 ProcessVerticesTest();
2989 StateTest();
2990 SceneTest();
2991 LimitTest();
2992 D3D7EnumTest();
2993 SetMaterialTest();
2994 ComputeSphereVisibility();
2995 CapsTest();
2996 VertexBufferDescTest();
2997 D3D7_OldRenderStateTest();
2998 DeviceLoadTest();
2999 ReleaseDirect3D();
3002 if (!D3D1_createObjects()) {
3003 skip("Skipping d3d1 tests\n");
3004 } else {
3005 Direct3D1Test();
3006 TextureLoadTest();
3007 D3D1_releaseObjects();