push c22b4aa826b27f0c6bc5101b378e6e68716a85d9
[wine/hacks.git] / dlls / ddraw / tests / d3d.c
blob3a2cd2b36c6ca120f24955eae504aa46f3548691
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 #include <assert.h>
24 #include "wine/test.h"
25 #include "initguid.h"
26 #include "ddraw.h"
27 #include "d3d.h"
29 static LPDIRECTDRAW7 lpDD = NULL;
30 static LPDIRECT3D7 lpD3D = NULL;
31 static LPDIRECTDRAWSURFACE7 lpDDS = NULL;
32 static LPDIRECTDRAWSURFACE7 lpDDSdepth = NULL;
33 static LPDIRECT3DDEVICE7 lpD3DDevice = NULL;
34 static LPDIRECT3DVERTEXBUFFER7 lpVBufSrc = NULL;
35 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest1 = NULL;
36 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest2 = NULL;
38 static IDirectDraw *DirectDraw1 = NULL;
39 static IDirectDrawSurface *Surface1 = NULL;
40 static IDirect3D *Direct3D1 = NULL;
41 static IDirect3DDevice *Direct3DDevice1 = NULL;
42 static IDirect3DExecuteBuffer *ExecuteBuffer = NULL;
43 static IDirect3DViewport *Viewport = NULL;
45 typedef struct {
46 int total;
47 int rgb;
48 int hal;
49 int tnlhal;
50 int unk;
51 } D3D7ETest;
53 /* To compare bad floating point numbers. Not the ideal way to do it,
54 * but it should be enough for here */
55 #define comparefloat(a, b) ( (((a) - (b)) < 0.0001) && (((a) - (b)) > -0.0001) )
57 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
59 typedef struct _VERTEX
61 float x, y, z; /* position */
62 } VERTEX, *LPVERTEX;
64 typedef struct _TVERTEX
66 float x, y, z; /* position */
67 float rhw;
68 } TVERTEX, *LPTVERTEX;
71 static void init_function_pointers(void)
73 HMODULE hmod = GetModuleHandleA("ddraw.dll");
74 pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
78 static BOOL CreateDirect3D(void)
80 HRESULT rc;
81 DDSURFACEDESC2 ddsd;
83 rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
84 &IID_IDirectDraw7, NULL);
85 ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
86 if (!lpDD) {
87 trace("DirectDrawCreateEx() failed with an error %x\n", rc);
88 return FALSE;
91 rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
92 ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
94 rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
95 if (rc == E_NOINTERFACE) return FALSE;
96 ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
98 memset(&ddsd, 0, sizeof(ddsd));
99 ddsd.dwSize = sizeof(ddsd);
100 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
101 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
102 ddsd.dwWidth = 256;
103 ddsd.dwHeight = 256;
104 rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
105 if (FAILED(rc))
106 return FALSE;
108 memset(&ddsd, 0, sizeof(ddsd));
109 ddsd.dwSize = sizeof(ddsd);
110 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
111 ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
112 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
113 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
114 U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 16;
115 U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
116 ddsd.dwWidth = 256;
117 ddsd.dwHeight = 256;
118 rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDSdepth, NULL);
119 ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
120 if (FAILED(rc)) {
121 lpDDSdepth = NULL;
122 } else {
123 rc = IDirectDrawSurface_AddAttachedSurface(lpDDS, lpDDSdepth);
124 ok(rc == DD_OK, "IDirectDrawSurface_AddAttachedSurface returned %x\n", rc);
125 if (FAILED(rc))
126 return FALSE;
129 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
130 &lpD3DDevice);
131 ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
132 if (!lpD3DDevice) {
133 trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
134 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
135 &lpD3DDevice);
136 if (!lpD3DDevice) {
137 trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
138 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
139 &lpD3DDevice);
140 if (!lpD3DDevice) {
141 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
142 return FALSE;
147 return TRUE;
150 static void ReleaseDirect3D(void)
152 if (lpD3DDevice != NULL)
154 IDirect3DDevice7_Release(lpD3DDevice);
155 lpD3DDevice = NULL;
158 if (lpDDSdepth != NULL)
160 IDirectDrawSurface_Release(lpDDSdepth);
161 lpDDSdepth = NULL;
164 if (lpDDS != NULL)
166 IDirectDrawSurface_Release(lpDDS);
167 lpDDS = NULL;
170 if (lpD3D != NULL)
172 IDirect3D7_Release(lpD3D);
173 lpD3D = NULL;
176 if (lpDD != NULL)
178 IDirectDraw_Release(lpDD);
179 lpDD = NULL;
183 static void LightTest(void)
185 HRESULT rc;
186 D3DLIGHT7 light;
187 D3DLIGHT7 defaultlight;
188 BOOL bEnabled = FALSE;
189 float one = 1.0f;
190 float zero= 0.0f;
191 D3DMATERIAL7 mat;
192 BOOL enabled;
193 unsigned int i;
194 D3DDEVICEDESC7 caps;
196 /* Set a few lights with funky indices. */
197 memset(&light, 0, sizeof(light));
198 light.dltType = D3DLIGHT_DIRECTIONAL;
199 U1(light.dcvDiffuse).r = 0.5f;
200 U2(light.dcvDiffuse).g = 0.6f;
201 U3(light.dcvDiffuse).b = 0.7f;
202 U2(light.dvDirection).y = 1.f;
204 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
205 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
206 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
207 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
208 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
209 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
212 /* Try to retrieve a light beyond the indices of the lights that have
213 been set. */
214 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
215 ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
216 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
217 ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
220 /* Try to retrieve one of the lights that have been set */
221 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
222 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
225 /* Enable a light that have been previously set. */
226 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
227 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
230 /* Enable some lights that have not been previously set, and verify that
231 they have been initialized with proper default values. */
232 memset(&defaultlight, 0, sizeof(D3DLIGHT7));
233 defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
234 U1(defaultlight.dcvDiffuse).r = 1.f;
235 U2(defaultlight.dcvDiffuse).g = 1.f;
236 U3(defaultlight.dcvDiffuse).b = 1.f;
237 U3(defaultlight.dvDirection).z = 1.f;
239 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
240 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
241 memset(&light, 0, sizeof(D3DLIGHT7));
242 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
243 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
244 ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
245 "light data doesn't match expected default values\n" );
247 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
248 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
249 memset(&light, 0, sizeof(D3DLIGHT7));
250 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
251 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
252 ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
253 "light data doesn't match expected default values\n" );
256 /* Disable one of the light that have been previously enabled. */
257 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
258 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
260 /* Try to retrieve the enable status of some lights */
261 /* Light 20 is supposed to be disabled */
262 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
263 ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
264 ok(!bEnabled, "GetLightEnable says the light is enabled\n");
266 /* Light 10 is supposed to be enabled */
267 bEnabled = FALSE;
268 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
269 ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
270 ok(bEnabled, "GetLightEnable says the light is disabled\n");
272 /* Light 80 has not been set */
273 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
274 ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
276 /* Light 23 has not been set */
277 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
278 ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
280 /* Set some lights with invalid parameters */
281 memset(&light, 0, sizeof(D3DLIGHT7));
282 light.dltType = 0;
283 U1(light.dcvDiffuse).r = 1.f;
284 U2(light.dcvDiffuse).g = 1.f;
285 U3(light.dcvDiffuse).b = 1.f;
286 U3(light.dvDirection).z = 1.f;
287 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
288 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
290 memset(&light, 0, sizeof(D3DLIGHT7));
291 light.dltType = 12345;
292 U1(light.dcvDiffuse).r = 1.f;
293 U2(light.dcvDiffuse).g = 1.f;
294 U3(light.dcvDiffuse).b = 1.f;
295 U3(light.dvDirection).z = 1.f;
296 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
297 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
299 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
300 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
302 memset(&light, 0, sizeof(D3DLIGHT7));
303 light.dltType = D3DLIGHT_SPOT;
304 U1(light.dcvDiffuse).r = 1.f;
305 U2(light.dcvDiffuse).g = 1.f;
306 U3(light.dcvDiffuse).b = 1.f;
307 U3(light.dvDirection).z = 1.f;
309 light.dvAttenuation0 = -one / zero; /* -INFINITY */
310 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
311 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
313 light.dvAttenuation0 = -1.0;
314 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
315 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
317 light.dvAttenuation0 = 0.0;
318 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
319 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
321 light.dvAttenuation0 = 1.0;
322 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
323 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
325 light.dvAttenuation0 = one / zero; /* +INFINITY */
326 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
327 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
329 light.dvAttenuation0 = zero / zero; /* NaN */
330 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
331 ok(rc==D3D_OK ||
332 broken(rc==DDERR_INVALIDPARAMS), "SetLight returned: %x\n", rc);
334 /* Directional light ignores attenuation */
335 light.dltType = D3DLIGHT_DIRECTIONAL;
336 light.dvAttenuation0 = -1.0;
337 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
338 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
340 memset(&mat, 0, sizeof(mat));
341 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
342 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial returned: %x\n", rc);
344 U4(mat).power = 129.0;
345 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
346 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = 129.0) returned: %x\n", rc);
347 memset(&mat, 0, sizeof(mat));
348 rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
349 ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
350 ok(U4(mat).power == 129, "Returned power is %f\n", U4(mat).power);
352 U4(mat).power = -1.0;
353 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
354 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = -1.0) returned: %x\n", rc);
355 memset(&mat, 0, sizeof(mat));
356 rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
357 ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
358 ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
360 memset(&caps, 0, sizeof(caps));
361 rc = IDirect3DDevice7_GetCaps(lpD3DDevice, &caps);
362 ok(rc == D3D_OK, "IDirect3DDevice7_GetCaps failed with %x\n", rc);
364 if ( caps.dwMaxActiveLights == (DWORD) -1) {
365 /* Some cards without T&L Support return -1 (Examples: Voodoo Banshee, RivaTNT / NV4) */
366 skip("T&L not supported\n");
367 return;
370 for(i = 1; i <= caps.dwMaxActiveLights; i++) {
371 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, TRUE);
372 ok(rc == D3D_OK, "Enabling light %u failed with %x\n", i, rc);
373 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i, &enabled);
374 ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i, rc);
375 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
378 /* TODO: Test the rendering results in this situation */
379 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, TRUE);
380 ok(rc == D3D_OK, "Enabling one light more than supported returned %x\n", rc);
381 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i + 1, &enabled);
382 ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i + 1, rc);
383 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
384 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, FALSE);
385 ok(rc == D3D_OK, "Disabling the additional returned %x\n", rc);
387 for(i = 1; i <= caps.dwMaxActiveLights; i++) {
388 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, FALSE);
389 ok(rc == D3D_OK, "Disabling light %u failed with %x\n", i, rc);
393 static void ProcessVerticesTest(void)
395 D3DVERTEXBUFFERDESC desc;
396 HRESULT rc;
397 VERTEX *in;
398 TVERTEX *out;
399 VERTEX *out2;
400 D3DVIEWPORT7 vp;
401 D3DMATRIX view = { 2.0, 0.0, 0.0, 0.0,
402 0.0, -1.0, 0.0, 0.0,
403 0.0, 0.0, 1.0, 0.0,
404 0.0, 0.0, 0.0, 3.0 };
406 D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
407 1.0, 0.0, 0.0, 0.0,
408 0.0, 0.0, 0.0, 1.0,
409 0.0, 1.0, 1.0, 1.0 };
411 D3DMATRIX proj = { 1.0, 0.0, 0.0, 1.0,
412 0.0, 1.0, 1.0, 0.0,
413 0.0, 1.0, 1.0, 0.0,
414 1.0, 0.0, 0.0, 1.0 };
415 /* Create some vertex buffers */
417 memset(&desc, 0, sizeof(desc));
418 desc.dwSize = sizeof(desc);
419 desc.dwCaps = 0;
420 desc.dwFVF = D3DFVF_XYZ;
421 desc.dwNumVertices = 16;
422 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
423 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
424 if (!lpVBufSrc)
426 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
427 goto out;
430 memset(&desc, 0, sizeof(desc));
431 desc.dwSize = sizeof(desc);
432 desc.dwCaps = 0;
433 desc.dwFVF = D3DFVF_XYZRHW;
434 desc.dwNumVertices = 16;
435 /* Msdn says that the last parameter must be 0 - check that */
436 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
437 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
438 if (!lpVBufDest1)
440 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
441 goto out;
444 memset(&desc, 0, sizeof(desc));
445 desc.dwSize = sizeof(desc);
446 desc.dwCaps = 0;
447 desc.dwFVF = D3DFVF_XYZ;
448 desc.dwNumVertices = 16;
449 /* Msdn says that the last parameter must be 0 - check that */
450 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
451 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
452 if (!lpVBufDest2)
454 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
455 goto out;
458 rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
459 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
460 if(!in) goto out;
462 /* Check basic transformation */
464 in[0].x = 0.0;
465 in[0].y = 0.0;
466 in[0].z = 0.0;
468 in[1].x = 1.0;
469 in[1].y = 1.0;
470 in[1].z = 1.0;
472 in[2].x = -1.0;
473 in[2].y = -1.0;
474 in[2].z = 0.5;
476 in[3].x = 0.5;
477 in[3].y = -0.5;
478 in[3].z = 0.25;
479 rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
480 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
482 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
483 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
485 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
486 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
488 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
489 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
490 if(!out) goto out;
492 /* Check the results */
493 ok( comparefloat(out[0].x, 128.0 ) &&
494 comparefloat(out[0].y, 128.0 ) &&
495 comparefloat(out[0].z, 0.0 ) &&
496 comparefloat(out[0].rhw, 1.0 ),
497 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
499 ok( comparefloat(out[1].x, 256.0 ) &&
500 comparefloat(out[1].y, 0.0 ) &&
501 comparefloat(out[1].z, 1.0 ) &&
502 comparefloat(out[1].rhw, 1.0 ),
503 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
505 ok( comparefloat(out[2].x, 0.0 ) &&
506 comparefloat(out[2].y, 256.0 ) &&
507 comparefloat(out[2].z, 0.5 ) &&
508 comparefloat(out[2].rhw, 1.0 ),
509 "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
511 ok( comparefloat(out[3].x, 192.0 ) &&
512 comparefloat(out[3].y, 192.0 ) &&
513 comparefloat(out[3].z, 0.25 ) &&
514 comparefloat(out[3].rhw, 1.0 ),
515 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
517 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
518 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
519 out = NULL;
521 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
522 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
523 if(!out2) goto out;
524 /* Small thing without much practical meaning, but I stumbled upon it,
525 * so let's check for it: If the output vertex buffer has to RHW value,
526 * The RHW value of the last vertex is written into the next vertex
528 ok( comparefloat(out2[4].x, 1.0 ) &&
529 comparefloat(out2[4].y, 0.0 ) &&
530 comparefloat(out2[4].z, 0.0 ),
531 "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
533 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
534 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
535 out = NULL;
537 /* Try a more complicated viewport, same vertices */
538 memset(&vp, 0, sizeof(vp));
539 vp.dwX = 10;
540 vp.dwY = 5;
541 vp.dwWidth = 246;
542 vp.dwHeight = 130;
543 vp.dvMinZ = -2.0;
544 vp.dvMaxZ = 4.0;
545 rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
546 ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
548 /* Process again */
549 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
550 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
552 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
553 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
554 if(!out) goto out;
556 /* Check the results */
557 ok( comparefloat(out[0].x, 133.0 ) &&
558 comparefloat(out[0].y, 70.0 ) &&
559 comparefloat(out[0].z, -2.0 ) &&
560 comparefloat(out[0].rhw, 1.0 ),
561 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
563 ok( comparefloat(out[1].x, 256.0 ) &&
564 comparefloat(out[1].y, 5.0 ) &&
565 comparefloat(out[1].z, 4.0 ) &&
566 comparefloat(out[1].rhw, 1.0 ),
567 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
569 ok( comparefloat(out[2].x, 10.0 ) &&
570 comparefloat(out[2].y, 135.0 ) &&
571 comparefloat(out[2].z, 1.0 ) &&
572 comparefloat(out[2].rhw, 1.0 ),
573 "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
575 ok( comparefloat(out[3].x, 194.5 ) &&
576 comparefloat(out[3].y, 102.5 ) &&
577 comparefloat(out[3].z, -0.5 ) &&
578 comparefloat(out[3].rhw, 1.0 ),
579 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
581 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
582 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
583 out = NULL;
585 /* Play with some matrices. */
587 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
588 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
590 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
591 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
593 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
594 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
596 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
597 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
599 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
600 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
601 if(!out) goto out;
603 /* Keep the viewport simpler, otherwise we get bad numbers to compare */
604 vp.dwX = 0;
605 vp.dwY = 0;
606 vp.dwWidth = 100;
607 vp.dwHeight = 100;
608 vp.dvMinZ = 1.0;
609 vp.dvMaxZ = 0.0;
610 rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
611 ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
613 /* Check the results */
614 ok( comparefloat(out[0].x, 256.0 ) && /* X coordinate is cut at the surface edges */
615 comparefloat(out[0].y, 70.0 ) &&
616 comparefloat(out[0].z, -2.0 ) &&
617 comparefloat(out[0].rhw, (1.0 / 3.0)),
618 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
620 ok( comparefloat(out[1].x, 256.0 ) &&
621 comparefloat(out[1].y, 78.125000 ) &&
622 comparefloat(out[1].z, -2.750000 ) &&
623 comparefloat(out[1].rhw, 0.125000 ),
624 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
626 ok( comparefloat(out[2].x, 256.0 ) &&
627 comparefloat(out[2].y, 44.000000 ) &&
628 comparefloat(out[2].z, 0.400000 ) &&
629 comparefloat(out[2].rhw, 0.400000 ),
630 "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
632 ok( comparefloat(out[3].x, 256.0 ) &&
633 comparefloat(out[3].y, 81.818184 ) &&
634 comparefloat(out[3].z, -3.090909 ) &&
635 comparefloat(out[3].rhw, 0.363636 ),
636 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
638 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
639 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
640 out = NULL;
642 out:
643 IDirect3DVertexBuffer7_Release(lpVBufSrc);
644 IDirect3DVertexBuffer7_Release(lpVBufDest1);
645 IDirect3DVertexBuffer7_Release(lpVBufDest2);
648 static void StateTest( void )
650 HRESULT rc;
652 /* The msdn says its undocumented, does it return an error too? */
653 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
654 ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
655 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
656 ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
660 static void SceneTest(void)
662 HRESULT hr;
664 /* Test an EndScene without beginscene. Should return an error */
665 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
666 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
668 /* Test a normal BeginScene / EndScene pair, this should work */
669 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
670 ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
671 if(SUCCEEDED(hr))
673 DDBLTFX fx;
674 memset(&fx, 0, sizeof(fx));
675 fx.dwSize = sizeof(fx);
677 if(lpDDSdepth) {
678 hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
679 ok(hr == D3D_OK, "Depthfill failed in a BeginScene / EndScene pair\n");
680 } else {
681 skip("Depth stencil creation failed at startup, skipping\n");
683 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
684 ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
687 /* Test another EndScene without having begun a new scene. Should return an error */
688 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
689 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
691 /* Two nested BeginScene and EndScene calls */
692 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
693 ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
694 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
695 ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
696 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
697 ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
698 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
699 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
701 /* TODO: Verify that blitting works in the same way as in d3d9 */
704 static void LimitTest(void)
706 IDirectDrawSurface7 *pTexture = NULL;
707 HRESULT hr;
708 int i;
709 DDSURFACEDESC2 ddsd;
711 memset(&ddsd, 0, sizeof(ddsd));
712 ddsd.dwSize = sizeof(ddsd);
713 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
714 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
715 ddsd.dwWidth = 16;
716 ddsd.dwHeight = 16;
717 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
718 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
719 if(!pTexture) return;
721 for(i = 0; i < 8; i++) {
722 hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
723 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
724 hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
725 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
726 hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
727 ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
730 IDirectDrawSurface7_Release(pTexture);
733 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
735 UINT ver = *((UINT *) ctx);
736 if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
738 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
739 "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
740 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
741 "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
742 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
743 "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
744 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
745 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
747 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
748 "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
749 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
750 "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
751 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
752 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
753 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
754 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
756 else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
758 /* pow2 is hardware dependent */
760 ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
761 "HAL Device %d hal line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
762 ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
763 "HAL Device %d hal tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
764 ok((hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
765 "HAL Device %d hel line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
766 ok((hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
767 "HAL Device %d hel tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
769 else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
771 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
772 "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
773 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
774 "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
775 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
776 "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
777 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
778 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
780 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
781 "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
782 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
783 "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
784 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
785 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
786 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
787 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
789 else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
791 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
792 "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
793 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
794 "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
795 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
796 "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
797 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
798 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
800 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
801 "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
802 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
803 "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
804 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
805 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
806 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
807 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
809 else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
811 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
812 "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
813 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
814 "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
815 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
816 "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
817 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
818 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
820 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
821 "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
822 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
823 "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
824 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
825 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
826 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
827 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
829 else
831 ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
832 if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
833 else trace("hal line does NOT have pow2 set\n");
834 if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
835 else trace("hal tri does NOT have pow2 set\n");
836 if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
837 else trace("hel line does NOT have pow2 set\n");
838 if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
839 else trace("hel tri does NOT have pow2 set\n");
841 return DDENUMRET_OK;
844 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
846 D3D7ETest *d3d7et = Context;
847 if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
848 d3d7et->rgb++;
849 else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
850 d3d7et->hal++;
851 else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
852 d3d7et->tnlhal++;
853 else
854 d3d7et->unk++;
856 d3d7et->total++;
858 return DDENUMRET_OK;
862 /* Check the deviceGUID of devices enumerated by
863 IDirect3D7_EnumDevices. */
864 static void D3D7EnumTest(void)
866 D3D7ETest d3d7et;
868 if (!lpD3D) {
869 skip("No Direct3D7 interface.\n");
870 return;
873 memset(&d3d7et, 0, sizeof(d3d7et));
874 IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et);
877 /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
878 ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
880 /* We make two additional assumptions. */
881 ok(d3d7et.rgb, "No RGB Device enumerated.\n");
883 if(d3d7et.tnlhal)
884 ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
886 return;
889 static void CapsTest(void)
891 IDirect3D3 *d3d3;
892 IDirect3D3 *d3d2;
893 IDirectDraw *dd1;
894 HRESULT hr;
895 UINT ver;
897 hr = DirectDrawCreate(NULL, &dd1, NULL);
898 ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
899 hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
900 ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
901 ver = 3;
902 IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
904 IDirect3D3_Release(d3d3);
905 IDirectDraw_Release(dd1);
907 hr = DirectDrawCreate(NULL, &dd1, NULL);
908 ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
909 hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
910 ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
911 ver = 2;
912 IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
914 IDirect3D2_Release(d3d2);
915 IDirectDraw_Release(dd1);
918 struct v_in {
919 float x, y, z;
921 struct v_out {
922 float x, y, z, rhw;
925 static BOOL D3D1_createObjects(void)
927 HRESULT hr;
928 DDSURFACEDESC ddsd;
929 D3DEXECUTEBUFFERDESC desc;
930 D3DVIEWPORT vp_data;
932 /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
933 hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
934 ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
935 if (!DirectDraw1) {
936 return FALSE;
939 hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
940 ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
942 hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
943 ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
944 if (!Direct3D1) {
945 return FALSE;
948 memset(&ddsd, 0, sizeof(ddsd));
949 ddsd.dwSize = sizeof(ddsd);
950 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
951 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
952 ddsd.dwWidth = 256;
953 ddsd.dwHeight = 256;
954 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
955 if (!Surface1) {
956 skip("DDSCAPS_3DDEVICE surface not available\n");
957 return FALSE;
960 hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRGBDevice, (void **) &Direct3DDevice1);
961 ok(hr==D3D_OK || hr==DDERR_NOPALETTEATTACHED || hr==E_OUTOFMEMORY, "CreateDevice returned: %x\n", hr);
962 if(!Direct3DDevice1) {
963 return FALSE;
966 memset(&desc, 0, sizeof(desc));
967 desc.dwSize = sizeof(desc);
968 desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
969 desc.dwCaps = D3DDEBCAPS_VIDEOMEMORY;
970 desc.dwBufferSize = 128;
971 desc.lpData = NULL;
972 hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &desc, &ExecuteBuffer, NULL);
973 ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed: %08x\n", hr);
974 if(!ExecuteBuffer) {
975 return FALSE;
978 hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
979 ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
980 if(!Viewport) {
981 return FALSE;
984 hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
985 ok(hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
987 hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
988 ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
989 vp_data.dwSize = sizeof(vp_data);
990 vp_data.dwX = 0;
991 vp_data.dwY = 0;
992 vp_data.dwWidth = 256;
993 vp_data.dwHeight = 256;
994 vp_data.dvScaleX = 1;
995 vp_data.dvScaleY = 1;
996 vp_data.dvMaxX = 256;
997 vp_data.dvMaxY = 256;
998 vp_data.dvMinZ = 0;
999 vp_data.dvMaxZ = 1;
1000 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1001 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1003 return TRUE;
1006 static void D3D1_releaseObjects(void)
1008 if (Viewport) IDirect3DViewport_Release(Viewport);
1009 if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1010 if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1011 if (Surface1) IDirectDrawSurface_Release(Surface1);
1012 if (Direct3D1) IDirect3D_Release(Direct3D1);
1013 if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1016 #define SET_VP_DATA(vp_data) \
1017 vp_data.dwSize = sizeof(vp_data); \
1018 vp_data.dwX = 0; \
1019 vp_data.dwY = 0; \
1020 vp_data.dwWidth = 256; \
1021 vp_data.dwHeight = 256; \
1022 vp_data.dvMaxX = 256; \
1023 vp_data.dvMaxY = 256; \
1024 vp_data.dvScaleX = 5; \
1025 vp_data.dvScaleY = 5; \
1026 vp_data.dvMinZ = -25; \
1027 vp_data.dvMaxZ = 60;
1029 static void Direct3D1Test(void)
1031 HRESULT hr;
1032 D3DEXECUTEBUFFERDESC desc;
1033 D3DVIEWPORT vp_data;
1034 D3DINSTRUCTION *instr;
1035 D3DBRANCH *branch;
1036 unsigned int idx = 0;
1037 static struct v_in testverts[] = {
1038 {0.0, 0.0, 0.0}, { 1.0, 1.0, 1.0}, {-1.0, -1.0, -1.0},
1039 {0.5, 0.5, 0.5}, {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1041 static struct v_in cliptest[] = {
1042 {25.59, 25.59, 1.0}, {-25.59, -25.59, 0.0},
1043 {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1045 static struct v_in offscreentest[] = {
1046 {128.1, 0.0, 0.0},
1048 struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1049 D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1050 D3DTRANSFORMDATA transformdata;
1051 DWORD i = FALSE;
1053 memset(&desc, 0, sizeof(desc));
1054 desc.dwSize = sizeof(desc);
1055 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1056 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1058 memset(desc.lpData, 0, 128);
1059 instr = desc.lpData;
1060 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1061 instr[idx].bSize = sizeof(*branch);
1062 instr[idx].wCount = 1;
1063 idx++;
1064 branch = (D3DBRANCH *) &instr[idx];
1065 branch->dwMask = 0x0;
1066 branch->dwValue = 1;
1067 branch->bNegate = TRUE;
1068 branch->dwOffset = 0;
1069 idx += (sizeof(*branch) / sizeof(*instr));
1070 instr[idx].bOpcode = D3DOP_EXIT;
1071 instr[idx].bSize = 0;
1072 instr[idx].wCount = 0;
1073 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1074 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1076 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1077 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1079 memset(&desc, 0, sizeof(desc));
1080 desc.dwSize = sizeof(desc);
1082 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1083 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1085 memset(desc.lpData, 0, 128);
1086 instr = desc.lpData;
1087 idx = 0;
1088 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1089 instr[idx].bSize = sizeof(*branch);
1090 instr[idx].wCount = 1;
1091 idx++;
1092 branch = (D3DBRANCH *) &instr[idx];
1093 branch->dwMask = 0x0;
1094 branch->dwValue = 1;
1095 branch->bNegate = TRUE;
1096 branch->dwOffset = 64;
1097 instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1098 instr[0].bOpcode = D3DOP_EXIT;
1099 instr[0].bSize = 0;
1100 instr[0].wCount = 0;
1101 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1102 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1104 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1105 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1107 /* Test rendering 0 triangles */
1108 memset(&desc, 0, sizeof(desc));
1109 desc.dwSize = sizeof(desc);
1111 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1112 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1114 memset(desc.lpData, 0, 128);
1115 instr = desc.lpData;
1116 idx = 0;
1118 instr->bOpcode = D3DOP_TRIANGLE;
1119 instr->bSize = sizeof(D3DOP_TRIANGLE);
1120 instr->wCount = 0;
1121 instr++;
1122 instr->bOpcode = D3DOP_EXIT;
1123 instr->bSize = 0;
1124 instr->wCount = 0;
1125 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1126 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1128 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1129 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1131 memset(&transformdata, 0, sizeof(transformdata));
1132 transformdata.dwSize = sizeof(transformdata);
1133 transformdata.lpIn = testverts;
1134 transformdata.dwInSize = sizeof(testverts[0]);
1135 transformdata.lpOut = out;
1136 transformdata.dwOutSize = sizeof(out[0]);
1138 transformdata.lpHOut = NULL;
1139 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1140 &transformdata, D3DTRANSFORM_UNCLIPPED,
1141 &i);
1142 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1144 transformdata.lpHOut = outH;
1145 memset(outH, 0xcc, sizeof(outH));
1146 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1147 &transformdata, D3DTRANSFORM_UNCLIPPED,
1148 &i);
1149 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1150 ok(i == 0, "Offscreen is %d\n", i);
1152 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1153 static const struct v_out cmp[] = {
1154 {128.0, 128.0, 0.0, 1}, {129.0, 127.0, 1.0, 1}, {127.0, 129.0, -1, 1},
1155 {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5, 0, 1}
1158 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1159 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1160 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1161 out[i].x, out[i].y, out[i].z, out[i].rhw,
1162 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1164 for(i = 0; i < sizeof(outH); i++) {
1165 if(((unsigned char *) outH)[i] != 0xcc) {
1166 ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1167 break;
1171 SET_VP_DATA(vp_data);
1172 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1173 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1174 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1175 &transformdata, D3DTRANSFORM_UNCLIPPED,
1176 &i);
1177 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1178 ok(i == 0, "Offscreen is %d\n", i);
1180 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1181 static const struct v_out cmp[] = {
1182 {128.0, 128.0, 0.0, 1}, {133.0, 123.0, 1.0, 1}, {123.0, 133.0, -1, 1},
1183 {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5, 0, 1}
1185 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1186 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1187 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1188 out[i].x, out[i].y, out[i].z, out[i].rhw,
1189 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1192 SET_VP_DATA(vp_data);
1193 vp_data.dwX = 10;
1194 vp_data.dwY = 20;
1195 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1196 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1197 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1198 &transformdata, D3DTRANSFORM_UNCLIPPED,
1199 &i);
1200 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1201 ok(i == 0, "Offscreen is %d\n", i);
1202 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1203 static const struct v_out cmp[] = {
1204 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, {133.0, 153.0, -1, 1},
1205 {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5, 0, 1}
1207 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1208 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1209 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1210 out[i].x, out[i].y, out[i].z, out[i].rhw,
1211 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1214 memset(out, 0xcc, sizeof(out));
1215 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1216 &transformdata, D3DTRANSFORM_CLIPPED,
1217 &i);
1218 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1219 ok(i == 0, "Offscreen is %d\n", i);
1220 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1221 static const D3DHVERTEX cmpH[] = {
1222 {0, { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1223 {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1224 {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1226 ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1227 U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1228 "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1229 outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1230 cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1232 /* No scheme has been found behind those return values. It seems to be
1233 * whatever data windows has when throwing the vertex away. Modify the
1234 * input test vertices to test this more. Depending on the input data
1235 * it can happen that the z coord gets written into y, or similar things
1237 if(0)
1239 static const struct v_out cmp[] = {
1240 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, { -1.0, -1.0, 0.5, 1},
1241 {140.5, 145.5, 0.5, 1}, { -0.5, -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1243 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1244 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1245 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1246 out[i].x, out[i].y, out[i].z, out[i].rhw,
1247 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1250 for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1251 ok(((DWORD *) out)[i] != 0xcccccccc,
1252 "Regular output DWORD %d remained untouched\n", i);
1255 transformdata.lpIn = cliptest;
1256 transformdata.dwInSize = sizeof(cliptest[0]);
1257 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1258 &transformdata, D3DTRANSFORM_CLIPPED,
1259 &i);
1260 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1261 ok(i == 0, "Offscreen is %d\n", i);
1262 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1263 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1267 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
1268 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1270 ok(Flags[i] == outH[i].dwFlags,
1271 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1272 outH[i].dwFlags, Flags[i]);
1275 SET_VP_DATA(vp_data);
1276 vp_data.dwWidth = 10;
1277 vp_data.dwHeight = 1000;
1278 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1279 i = 10;
1280 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1281 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1282 &transformdata, D3DTRANSFORM_CLIPPED,
1283 &i);
1284 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1285 ok(i == 0, "Offscreen is %d\n", i);
1286 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1287 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1289 D3DCLIP_RIGHT,
1290 D3DCLIP_LEFT,
1291 D3DCLIP_RIGHT | D3DCLIP_BACK,
1292 D3DCLIP_LEFT | D3DCLIP_FRONT,
1294 ok(Flags[i] == outH[i].dwFlags,
1295 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1296 outH[i].dwFlags, Flags[i]);
1299 SET_VP_DATA(vp_data);
1300 vp_data.dwWidth = 256;
1301 vp_data.dwHeight = 256;
1302 vp_data.dvScaleX = 1;
1303 vp_data.dvScaleY = 1;
1304 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1305 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1306 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1307 &transformdata, D3DTRANSFORM_CLIPPED,
1308 &i);
1309 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1310 ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1311 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1312 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1316 D3DCLIP_BACK,
1317 D3DCLIP_FRONT,
1319 ok(Flags[i] == outH[i].dwFlags,
1320 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1321 outH[i].dwFlags, Flags[i]);
1324 /* Finally try to figure out how the DWORD dwOffscreen works.
1325 * Apparently no vertex is offscreen with clipping off,
1326 * and with clipping on the offscreen flag is set if only one vertex
1327 * is transformed, and this vertex is offscreen.
1329 SET_VP_DATA(vp_data);
1330 vp_data.dwWidth = 5;
1331 vp_data.dwHeight = 5;
1332 vp_data.dvScaleX = 10000;
1333 vp_data.dvScaleY = 10000;
1334 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1335 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1336 transformdata.lpIn = cliptest;
1337 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1338 &transformdata, D3DTRANSFORM_UNCLIPPED,
1339 &i);
1340 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1341 ok(i == 0, "Offscreen is %d\n", i);
1342 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1343 &transformdata, D3DTRANSFORM_CLIPPED,
1344 &i);
1345 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1346 ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1347 hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1348 &transformdata, D3DTRANSFORM_CLIPPED,
1349 &i);
1350 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1351 ok(i == 0, "Offscreen is %d\n", i);
1352 transformdata.lpIn = cliptest + 1;
1353 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1354 &transformdata, D3DTRANSFORM_CLIPPED,
1355 &i);
1356 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1357 ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1359 transformdata.lpIn = offscreentest;
1360 transformdata.dwInSize = sizeof(offscreentest[0]);
1361 SET_VP_DATA(vp_data);
1362 vp_data.dwWidth = 257;
1363 vp_data.dwHeight = 257;
1364 vp_data.dvScaleX = 1;
1365 vp_data.dvScaleY = 1;
1366 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1367 i = 12345;
1368 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1369 &transformdata, D3DTRANSFORM_CLIPPED,
1370 &i);
1371 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1372 ok(i == 0, "Offscreen is %d\n", i);
1373 vp_data.dwWidth = 256;
1374 vp_data.dwHeight = 256;
1375 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1376 i = 12345;
1377 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1378 &transformdata, D3DTRANSFORM_CLIPPED,
1379 &i);
1380 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1381 ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1383 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1384 &transformdata, 0,
1385 &i);
1386 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1388 hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1389 ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1392 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1394 int i;
1396 for (i = 0; i < 256; i++) {
1397 if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1398 table1[i].peBlue != table2[i].peBlue) return FALSE;
1401 return TRUE;
1404 /* test palette handling in IDirect3DTexture_Load */
1405 static void TextureLoadTest(void)
1407 IDirectDrawSurface *TexSurface = NULL;
1408 IDirect3DTexture *Texture = NULL;
1409 IDirectDrawSurface *TexSurface2 = NULL;
1410 IDirect3DTexture *Texture2 = NULL;
1411 IDirectDrawPalette *palette = NULL;
1412 IDirectDrawPalette *palette2 = NULL;
1413 IDirectDrawPalette *palette_tmp = NULL;
1414 PALETTEENTRY table1[256], table2[256], table_tmp[256];
1415 HRESULT hr;
1416 DDSURFACEDESC ddsd;
1417 int i;
1419 memset (&ddsd, 0, sizeof (ddsd));
1420 ddsd.dwSize = sizeof (ddsd);
1421 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1422 ddsd.dwHeight = 128;
1423 ddsd.dwWidth = 128;
1424 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1425 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1426 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1427 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1429 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1430 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1431 if (FAILED(hr)) {
1432 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1433 goto cleanup;
1436 hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1437 (void *)&Texture);
1438 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1439 if (FAILED(hr)) {
1440 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1441 goto cleanup;
1444 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1445 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1446 if (FAILED(hr)) {
1447 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1448 goto cleanup;
1451 hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1452 (void *)&Texture2);
1453 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1454 if (FAILED(hr)) {
1455 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1456 goto cleanup;
1459 /* test load of Texture to Texture */
1460 hr = IDirect3DTexture_Load(Texture, Texture);
1461 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1463 /* test Load when both textures have no palette */
1464 hr = IDirect3DTexture_Load(Texture2, Texture);
1465 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1467 for (i = 0; i < 256; i++) {
1468 table1[i].peRed = i;
1469 table1[i].peGreen = i;
1470 table1[i].peBlue = i;
1471 table1[i].peFlags = 0;
1474 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1475 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1476 if (FAILED(hr)) {
1477 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1478 goto cleanup;
1481 /* test Load when source texture has palette and destination has no palette */
1482 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1483 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1484 hr = IDirect3DTexture_Load(Texture2, Texture);
1485 ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1487 for (i = 0; i < 256; i++) {
1488 table2[i].peRed = 255 - i;
1489 table2[i].peGreen = 255 - i;
1490 table2[i].peBlue = 255 - i;
1491 table2[i].peFlags = 0;
1494 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1495 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1496 if (FAILED(hr)) {
1497 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1498 goto cleanup;
1501 /* test Load when source has no palette and destination has a palette */
1502 hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1503 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1504 hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1505 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1506 hr = IDirect3DTexture_Load(Texture2, Texture);
1507 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1508 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1509 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1510 if (!palette_tmp) {
1511 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1512 goto cleanup;
1513 } else {
1514 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1515 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1516 ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1517 IDirectDrawPalette_Release(palette_tmp);
1520 /* test Load when both textures have palettes */
1521 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1522 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1523 hr = IDirect3DTexture_Load(Texture2, Texture);
1524 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1525 hr = IDirect3DTexture_Load(Texture2, Texture);
1526 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1527 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1528 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1529 if (!palette_tmp) {
1530 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1531 goto cleanup;
1532 } else {
1533 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1534 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1535 ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1536 IDirectDrawPalette_Release(palette_tmp);
1539 cleanup:
1541 if (palette) IDirectDrawPalette_Release(palette);
1542 if (palette2) IDirectDrawPalette_Release(palette2);
1543 if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1544 if (Texture) IDirect3DTexture_Release(Texture);
1545 if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1546 if (Texture2) IDirect3DTexture_Release(Texture2);
1549 static void VertexBufferDescTest(void)
1551 HRESULT rc;
1552 D3DVERTEXBUFFERDESC desc;
1553 union mem_t
1555 D3DVERTEXBUFFERDESC desc2;
1556 unsigned char buffer[512];
1557 } mem;
1559 memset(&desc, 0, sizeof(desc));
1560 desc.dwSize = sizeof(desc);
1561 desc.dwCaps = 0;
1562 desc.dwFVF = D3DFVF_XYZ;
1563 desc.dwNumVertices = 1;
1564 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1565 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1566 if (!lpVBufSrc)
1568 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1569 goto out;
1572 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1573 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1574 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1575 if(rc != D3D_OK)
1576 skip("GetVertexBuffer Failed!\n");
1577 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1578 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1579 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1580 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1581 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1583 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1584 mem.desc2.dwSize = 0;
1585 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1586 if(rc != D3D_OK)
1587 skip("GetVertexBuffer Failed!\n");
1588 ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1589 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1590 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1591 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1592 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1594 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1595 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1596 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1597 if(rc != D3D_OK)
1598 skip("GetVertexBuffer Failed!\n");
1599 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1600 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1601 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1602 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1603 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1605 out:
1606 IDirect3DVertexBuffer7_Release(lpVBufSrc);
1609 static void D3D7_OldRenderStateTest(void)
1611 HRESULT rc;
1612 DWORD val;
1614 /* Test reaction to some deprecated states in D3D7.
1616 * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1617 * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1618 * need not to be handled in D3D7.
1620 todo_wine {
1621 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1622 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1624 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1625 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1627 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1628 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1630 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1631 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1635 #define IS_VALUE_NEAR(a, b) ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1636 #define MIN(a, b) ((a) < (b) ? (a) : (b))
1638 static void DeviceLoadTest()
1640 DDSURFACEDESC2 ddsd;
1641 IDirectDrawSurface7 *texture_levels[2][8];
1642 IDirectDrawSurface7 *cube_face_levels[2][6][8];
1643 DWORD flags;
1644 HRESULT hr;
1645 DDBLTFX ddbltfx;
1646 RECT loadrect;
1647 POINT loadpoint;
1648 int i, i1, i2;
1649 unsigned diff_count = 0, diff_count2 = 0;
1650 unsigned x, y;
1651 BOOL load_mip_subset_broken = FALSE;
1652 IDirectDrawPalette *palettes[5];
1653 PALETTEENTRY table1[256];
1654 DDCOLORKEY ddckey;
1655 D3DDEVICEDESC7 d3dcaps;
1657 /* Test loading of texture subrectangle with a mipmap surface. */
1658 memset(texture_levels, 0, sizeof(texture_levels));
1659 memset(cube_face_levels, 0, sizeof(cube_face_levels));
1660 memset(palettes, 0, sizeof(palettes));
1662 for (i = 0; i < 2; i++)
1664 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1665 ddsd.dwSize = sizeof(ddsd);
1666 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1667 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1668 ddsd.dwWidth = 128;
1669 ddsd.dwHeight = 128;
1670 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1671 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1672 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1673 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1674 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1675 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1676 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1677 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1678 if (FAILED(hr)) goto out;
1680 /* Check the number of created mipmaps */
1681 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1682 ddsd.dwSize = sizeof(ddsd);
1683 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1684 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1685 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1686 if (U2(ddsd).dwMipMapCount != 8) goto out;
1688 for (i1 = 1; i1 < 8; i1++)
1690 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1691 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1692 if (FAILED(hr)) goto out;
1696 for (i1 = 0; i1 < 8; i1++)
1698 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1699 ddsd.dwSize = sizeof(ddsd);
1700 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1701 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1702 if (FAILED(hr)) goto out;
1704 for (y = 0 ; y < ddsd.dwHeight; y++)
1706 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1708 for (x = 0; x < ddsd.dwWidth; x++)
1710 /* x stored in green component, y in blue. */
1711 DWORD color = 0xff0000 | (x << 8) | y;
1712 *textureRow++ = color;
1716 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1717 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1720 for (i1 = 0; i1 < 8; i1++)
1722 memset(&ddbltfx, 0, sizeof(ddbltfx));
1723 ddbltfx.dwSize = sizeof(ddbltfx);
1724 U5(ddbltfx).dwFillColor = 0;
1725 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1726 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1729 /* First test some broken coordinates. */
1730 loadpoint.x = loadpoint.y = 0;
1731 loadrect.left = 0;
1732 loadrect.top = 0;
1733 loadrect.right = 0;
1734 loadrect.bottom = 0;
1735 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1736 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1738 loadpoint.x = loadpoint.y = 50;
1739 loadrect.left = 0;
1740 loadrect.top = 0;
1741 loadrect.right = 100;
1742 loadrect.bottom = 100;
1743 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1744 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1746 /* Test actual loading. */
1747 loadpoint.x = loadpoint.y = 31;
1748 loadrect.left = 30;
1749 loadrect.top = 20;
1750 loadrect.right = 93;
1751 loadrect.bottom = 52;
1753 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1754 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1756 for (i1 = 0; i1 < 8; i1++)
1758 diff_count = 0;
1759 diff_count2 = 0;
1761 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1762 ddsd.dwSize = sizeof(ddsd);
1763 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1764 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1765 if (FAILED(hr)) goto out;
1767 for (y = 0 ; y < ddsd.dwHeight; y++)
1769 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1771 for (x = 0; x < ddsd.dwWidth; x++)
1773 DWORD color = *textureRow++;
1775 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1776 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1778 if (color & 0xffffff) diff_count++;
1780 else
1782 DWORD r = (color & 0xff0000) >> 16;
1783 DWORD g = (color & 0xff00) >> 8;
1784 DWORD b = (color & 0xff);
1786 if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1789 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1790 technically be correct as it's not precisely defined by docs. */
1791 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1792 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1794 if (color & 0xffffff) diff_count2++;
1796 else
1798 DWORD r = (color & 0xff0000) >> 16;
1799 DWORD g = (color & 0xff00) >> 8;
1800 DWORD b = (color & 0xff);
1802 if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1803 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1808 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1809 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1811 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1812 MIN(diff_count, diff_count2), i1);
1814 loadpoint.x /= 2;
1815 loadpoint.y /= 2;
1816 loadrect.top /= 2;
1817 loadrect.left /= 2;
1818 loadrect.right = (loadrect.right + 1) / 2;
1819 loadrect.bottom = (loadrect.bottom + 1) / 2;
1822 /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1823 * qemu Win98 / directx7 / RGB software rasterizer):
1824 * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1825 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1828 /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1829 for (i = 0; i < 2; i++)
1831 for (i1 = 7; i1 >= 0; i1--)
1833 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1836 memset(texture_levels, 0, sizeof(texture_levels));
1838 /* Test texture size mismatch. */
1839 for (i = 0; i < 2; i++)
1841 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1842 ddsd.dwSize = sizeof(ddsd);
1843 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1844 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1845 ddsd.dwWidth = i ? 256 : 128;
1846 ddsd.dwHeight = 128;
1847 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1848 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1849 if (FAILED(hr)) goto out;
1852 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1853 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1855 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1856 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1858 IDirectDrawSurface7_Release(texture_levels[0][0]);
1859 IDirectDrawSurface7_Release(texture_levels[1][0]);
1860 memset(texture_levels, 0, sizeof(texture_levels));
1862 memset(&d3dcaps, 0, sizeof(d3dcaps));
1863 hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1864 ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1866 if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1868 skip("No cubemap support\n");
1870 else
1872 /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1873 for (i = 0; i < 2; i++)
1875 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1876 ddsd.dwSize = sizeof(ddsd);
1877 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1878 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1879 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1880 ddsd.dwWidth = 128;
1881 ddsd.dwHeight = 128;
1882 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1883 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1884 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1885 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1886 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1887 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1888 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1889 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1890 if (FAILED(hr)) goto out;
1892 flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1893 for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1895 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1896 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1897 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1898 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1899 if (FAILED(hr)) goto out;
1902 for (i1 = 0; i1 < 6; i1++)
1904 /* Check the number of created mipmaps */
1905 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1906 ddsd.dwSize = sizeof(ddsd);
1907 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1908 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1909 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1910 if (U2(ddsd).dwMipMapCount != 8) goto out;
1912 for (i2 = 1; i2 < 8; i2++)
1914 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1915 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1916 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1917 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1918 if (FAILED(hr)) goto out;
1923 for (i = 0; i < 6; i++)
1924 for (i1 = 0; i1 < 8; i1++)
1926 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1927 ddsd.dwSize = sizeof(ddsd);
1928 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1929 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1930 if (FAILED(hr)) goto out;
1932 for (y = 0 ; y < ddsd.dwHeight; y++)
1934 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1936 for (x = 0; x < ddsd.dwWidth; x++)
1938 /* face number in low 4 bits of red, x stored in green component, y in blue. */
1939 DWORD color = 0xf00000 | (i << 16) | (x << 8) | y;
1940 *textureRow++ = color;
1944 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1945 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1948 for (i = 0; i < 6; i++)
1949 for (i1 = 0; i1 < 8; i1++)
1951 memset(&ddbltfx, 0, sizeof(ddbltfx));
1952 ddbltfx.dwSize = sizeof(ddbltfx);
1953 U5(ddbltfx).dwFillColor = 0;
1954 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1955 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1958 loadpoint.x = loadpoint.y = 10;
1959 loadrect.left = 30;
1960 loadrect.top = 20;
1961 loadrect.right = 93;
1962 loadrect.bottom = 52;
1964 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
1965 DDSCAPS2_CUBEMAP_ALLFACES);
1966 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1968 for (i = 0; i < 6; i++)
1970 loadpoint.x = loadpoint.y = 10;
1971 loadrect.left = 30;
1972 loadrect.top = 20;
1973 loadrect.right = 93;
1974 loadrect.bottom = 52;
1976 for (i1 = 0; i1 < 8; i1++)
1978 diff_count = 0;
1979 diff_count2 = 0;
1981 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1982 ddsd.dwSize = sizeof(ddsd);
1983 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1984 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1985 if (FAILED(hr)) goto out;
1987 for (y = 0 ; y < ddsd.dwHeight; y++)
1989 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1991 for (x = 0; x < ddsd.dwWidth; x++)
1993 DWORD color = *textureRow++;
1995 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1996 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1998 if (color & 0xffffff) diff_count++;
2000 else
2002 DWORD r = (color & 0xff0000) >> 16;
2003 DWORD g = (color & 0xff00) >> 8;
2004 DWORD b = (color & 0xff);
2006 if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2007 b != y + loadrect.top - loadpoint.y) diff_count++;
2010 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2011 technically be correct as it's not precisely defined by docs. */
2012 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2013 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2015 if (color & 0xffffff) diff_count2++;
2017 else
2019 DWORD r = (color & 0xff0000) >> 16;
2020 DWORD g = (color & 0xff00) >> 8;
2021 DWORD b = (color & 0xff);
2023 if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2024 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2029 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2030 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2032 ok(diff_count == 0 || diff_count2 == 0,
2033 "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2034 MIN(diff_count, diff_count2), i, i1);
2036 loadpoint.x /= 2;
2037 loadpoint.y /= 2;
2038 loadrect.top /= 2;
2039 loadrect.left /= 2;
2040 loadrect.right = (loadrect.right + 1) / 2;
2041 loadrect.bottom = (loadrect.bottom + 1) / 2;
2045 for (i = 0; i < 2; i++)
2046 for (i1 = 5; i1 >= 0; i1--)
2047 for (i2 = 7; i2 >= 0; i2--)
2049 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2051 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2053 /* Test cubemap loading from regular texture. */
2054 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2055 ddsd.dwSize = sizeof(ddsd);
2056 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2057 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2058 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2059 ddsd.dwWidth = 128;
2060 ddsd.dwHeight = 128;
2061 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2062 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2063 if (FAILED(hr)) goto out;
2065 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2066 ddsd.dwSize = sizeof(ddsd);
2067 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2068 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2069 ddsd.dwWidth = 128;
2070 ddsd.dwHeight = 128;
2071 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2072 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2073 if (FAILED(hr)) goto out;
2075 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2076 DDSCAPS2_CUBEMAP_ALLFACES);
2077 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2079 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2080 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2081 IDirectDrawSurface7_Release(texture_levels[0][0]);
2082 memset(texture_levels, 0, sizeof(texture_levels));
2084 /* Test cubemap loading from cubemap with different number of faces. */
2085 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2086 ddsd.dwSize = sizeof(ddsd);
2087 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2088 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2089 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2090 ddsd.dwWidth = 128;
2091 ddsd.dwHeight = 128;
2092 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2093 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2094 if (FAILED(hr)) goto out;
2096 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2097 ddsd.dwSize = sizeof(ddsd);
2098 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2099 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2100 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2101 ddsd.dwWidth = 128;
2102 ddsd.dwHeight = 128;
2103 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2104 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2105 if (FAILED(hr)) goto out;
2107 /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2108 (the above created cubemaps will have all faces. */
2109 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2110 DDSCAPS2_CUBEMAP_ALLFACES);
2111 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2113 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2114 DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2115 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2117 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2118 DDSCAPS2_CUBEMAP_POSITIVEX);
2119 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2121 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2122 DDSCAPS2_CUBEMAP_ALLFACES);
2123 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2125 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2126 DDSCAPS2_CUBEMAP_POSITIVEX);
2127 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2129 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2130 DDSCAPS2_CUBEMAP_POSITIVEZ);
2131 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2133 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2134 IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2135 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2138 /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2139 for (i = 0; i < 2; i++)
2141 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2142 ddsd.dwSize = sizeof(ddsd);
2143 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2144 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2145 ddsd.dwWidth = 128;
2146 ddsd.dwHeight = 128;
2147 U2(ddsd).dwMipMapCount = i ? 4 : 8;
2148 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2149 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2150 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2151 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2152 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2153 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2154 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2155 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2156 if (FAILED(hr)) goto out;
2158 /* Check the number of created mipmaps */
2159 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2160 ddsd.dwSize = sizeof(ddsd);
2161 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2162 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2163 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2164 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2166 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2168 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2169 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2170 if (FAILED(hr)) goto out;
2174 for (i1 = 0; i1 < 8; i1++)
2176 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2177 ddsd.dwSize = sizeof(ddsd);
2178 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2179 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2180 if (FAILED(hr)) goto out;
2182 for (y = 0 ; y < ddsd.dwHeight; y++)
2184 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2186 for (x = 0; x < ddsd.dwWidth; x++)
2188 /* x stored in green component, y in blue. */
2189 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2190 *textureRow++ = color;
2194 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2195 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2198 for (i1 = 0; i1 < 4; i1++)
2200 memset(&ddbltfx, 0, sizeof(ddbltfx));
2201 ddbltfx.dwSize = sizeof(ddbltfx);
2202 U5(ddbltfx).dwFillColor = 0;
2203 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2204 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2207 loadpoint.x = loadpoint.y = 31;
2208 loadrect.left = 30;
2209 loadrect.top = 20;
2210 loadrect.right = 93;
2211 loadrect.bottom = 52;
2213 /* Destination mip levels are a subset of source mip levels. */
2214 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2215 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2217 for (i1 = 0; i1 < 4; i1++)
2219 diff_count = 0;
2220 diff_count2 = 0;
2222 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2223 ddsd.dwSize = sizeof(ddsd);
2224 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2225 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2226 if (FAILED(hr)) goto out;
2228 for (y = 0 ; y < ddsd.dwHeight; y++)
2230 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2232 for (x = 0; x < ddsd.dwWidth; x++)
2234 DWORD color = *textureRow++;
2236 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2237 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2239 if (color & 0xffffff) diff_count++;
2241 else
2243 DWORD r = (color & 0xff0000) >> 16;
2244 DWORD g = (color & 0xff00) >> 8;
2245 DWORD b = (color & 0xff);
2247 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2248 b != y + loadrect.top - loadpoint.y) diff_count++;
2251 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2252 technically be correct as it's not precisely defined by docs. */
2253 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2254 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2256 if (color & 0xffffff) diff_count2++;
2258 else
2260 DWORD r = (color & 0xff0000) >> 16;
2261 DWORD g = (color & 0xff00) >> 8;
2262 DWORD b = (color & 0xff);
2264 if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2265 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2270 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2271 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2273 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2274 MIN(diff_count, diff_count2), i1);
2276 loadpoint.x /= 2;
2277 loadpoint.y /= 2;
2278 loadrect.top /= 2;
2279 loadrect.left /= 2;
2280 loadrect.right = (loadrect.right + 1) / 2;
2281 loadrect.bottom = (loadrect.bottom + 1) / 2;
2284 /* Destination mip levels are a superset of source mip levels (should fail). */
2285 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2286 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2288 for (i = 0; i < 2; i++)
2290 for (i1 = 7; i1 >= 0; i1--)
2292 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2295 memset(texture_levels, 0, sizeof(texture_levels));
2297 /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2298 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2299 ddsd.dwSize = sizeof(ddsd);
2300 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2301 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2302 ddsd.dwWidth = 128;
2303 ddsd.dwHeight = 128;
2304 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2305 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2306 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2307 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2308 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2309 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2310 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2311 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2312 if (FAILED(hr)) goto out;
2314 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2315 ddsd.dwSize = sizeof(ddsd);
2316 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2317 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2318 ddsd.dwWidth = 32;
2319 ddsd.dwHeight = 32;
2320 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2321 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2322 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2323 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2324 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2325 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2326 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2327 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2328 if (FAILED(hr)) goto out;
2330 for (i1 = 1; i1 < 8; i1++)
2332 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2333 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2334 if (FAILED(hr)) goto out;
2337 for (i1 = 0; i1 < 8; i1++)
2339 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2340 ddsd.dwSize = sizeof(ddsd);
2341 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2342 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2343 if (FAILED(hr)) goto out;
2345 for (y = 0 ; y < ddsd.dwHeight; y++)
2347 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2349 for (x = 0; x < ddsd.dwWidth; x++)
2351 /* x stored in green component, y in blue. */
2352 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2353 *textureRow++ = color;
2357 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2358 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2361 memset(&ddbltfx, 0, sizeof(ddbltfx));
2362 ddbltfx.dwSize = sizeof(ddbltfx);
2363 U5(ddbltfx).dwFillColor = 0;
2364 hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2365 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2367 loadpoint.x = loadpoint.y = 32;
2368 loadrect.left = 32;
2369 loadrect.top = 32;
2370 loadrect.right = 96;
2371 loadrect.bottom = 96;
2373 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2374 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2376 loadpoint.x /= 4;
2377 loadpoint.y /= 4;
2378 loadrect.top /= 4;
2379 loadrect.left /= 4;
2380 loadrect.right = (loadrect.right + 3) / 4;
2381 loadrect.bottom = (loadrect.bottom + 3) / 4;
2383 /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2384 * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2385 * copied subrectangles divided more than needed, without apparent logic. But it works
2386 * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2387 * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2388 * The following code attempts to detect broken results, actual tests will then be skipped
2390 load_mip_subset_broken = TRUE;
2391 diff_count = 0;
2393 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2394 ddsd.dwSize = sizeof(ddsd);
2395 hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2396 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2397 if (FAILED(hr)) goto out;
2399 for (y = 0 ; y < ddsd.dwHeight; y++)
2401 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2403 for (x = 0; x < ddsd.dwWidth; x++)
2405 DWORD color = *textureRow++;
2407 if (x < 2 || x >= 2 + 4 ||
2408 y < 2 || y >= 2 + 4)
2410 if (color & 0xffffff) diff_count++;
2412 else
2414 DWORD r = (color & 0xff0000) >> 16;
2416 if ((r & (0xf0)) != 0xf0) diff_count++;
2421 if (diff_count) load_mip_subset_broken = FALSE;
2423 if (load_mip_subset_broken) {
2424 skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2425 } else {
2426 diff_count = 0;
2428 for (y = 0 ; y < ddsd.dwHeight; y++)
2430 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2432 for (x = 0; x < ddsd.dwWidth; x++)
2434 DWORD color = *textureRow++;
2436 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2437 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2439 if (color & 0xffffff) diff_count++;
2441 else
2443 DWORD r = (color & 0xff0000) >> 16;
2444 DWORD g = (color & 0xff00) >> 8;
2445 DWORD b = (color & 0xff);
2447 if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2448 b != y + loadrect.top - loadpoint.y) diff_count++;
2454 hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2455 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2457 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2459 for (i = 0; i < 2; i++)
2461 for (i1 = 7; i1 >= 0; i1--)
2463 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2466 memset(texture_levels, 0, sizeof(texture_levels));
2468 if (!load_mip_subset_broken)
2470 /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2471 * surface (than first source mip level)
2473 for (i = 0; i < 2; i++)
2475 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2476 ddsd.dwSize = sizeof(ddsd);
2477 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2478 if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2479 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2480 ddsd.dwWidth = i ? 32 : 128;
2481 ddsd.dwHeight = i ? 32 : 128;
2482 if (i) U2(ddsd).dwMipMapCount = 4;
2483 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2484 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2485 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2486 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2487 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2488 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2489 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2490 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2491 if (FAILED(hr)) goto out;
2493 /* Check the number of created mipmaps */
2494 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2495 ddsd.dwSize = sizeof(ddsd);
2496 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2497 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2498 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2499 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2501 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2503 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2504 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2505 if (FAILED(hr)) goto out;
2509 for (i1 = 0; i1 < 8; i1++)
2511 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2512 ddsd.dwSize = sizeof(ddsd);
2513 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2514 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2515 if (FAILED(hr)) goto out;
2517 for (y = 0 ; y < ddsd.dwHeight; y++)
2519 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2521 for (x = 0; x < ddsd.dwWidth; x++)
2523 /* x stored in green component, y in blue. */
2524 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2525 *textureRow++ = color;
2529 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2530 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2533 for (i1 = 0; i1 < 4; i1++)
2535 memset(&ddbltfx, 0, sizeof(ddbltfx));
2536 ddbltfx.dwSize = sizeof(ddbltfx);
2537 U5(ddbltfx).dwFillColor = 0;
2538 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2539 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2542 loadpoint.x = loadpoint.y = 0;
2543 loadrect.left = 0;
2544 loadrect.top = 0;
2545 loadrect.right = 64;
2546 loadrect.bottom = 64;
2548 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2549 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2551 i = 0;
2552 for (i1 = 0; i1 < 8 && i < 4; i1++)
2554 DDSURFACEDESC2 ddsd2;
2556 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2557 ddsd.dwSize = sizeof(ddsd);
2558 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2560 memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2561 ddsd2.dwSize = sizeof(ddsd2);
2562 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2564 if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2566 diff_count = 0;
2568 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2569 ddsd.dwSize = sizeof(ddsd);
2570 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2571 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2572 if (FAILED(hr)) goto out;
2574 for (y = 0 ; y < ddsd.dwHeight; y++)
2576 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2578 for (x = 0; x < ddsd.dwWidth; x++)
2580 DWORD color = *textureRow++;
2582 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2583 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2585 if (color & 0xffffff) diff_count++;
2587 else
2589 DWORD r = (color & 0xff0000) >> 16;
2590 DWORD g = (color & 0xff00) >> 8;
2591 DWORD b = (color & 0xff);
2593 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2594 b != y + loadrect.top - loadpoint.y) diff_count++;
2599 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2600 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2602 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2604 i++;
2607 loadpoint.x /= 2;
2608 loadpoint.y /= 2;
2609 loadrect.top /= 2;
2610 loadrect.left /= 2;
2611 loadrect.right = (loadrect.right + 1) / 2;
2612 loadrect.bottom = (loadrect.bottom + 1) / 2;
2615 for (i = 0; i < 2; i++)
2617 for (i1 = 7; i1 >= 0; i1--)
2619 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2622 memset(texture_levels, 0, sizeof(texture_levels));
2625 /* Test palette copying. */
2626 for (i = 0; i < 2; i++)
2628 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2629 ddsd.dwSize = sizeof(ddsd);
2630 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2631 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2632 ddsd.dwWidth = 128;
2633 ddsd.dwHeight = 128;
2634 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2635 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2636 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2637 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2638 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2639 if (FAILED(hr)) goto out;
2641 /* Check the number of created mipmaps */
2642 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2643 ddsd.dwSize = sizeof(ddsd);
2644 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2645 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2646 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2647 if (U2(ddsd).dwMipMapCount != 8) goto out;
2649 for (i1 = 1; i1 < 8; i1++)
2651 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2652 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2653 if (FAILED(hr)) goto out;
2657 memset(table1, 0, sizeof(table1));
2658 for (i = 0; i < 3; i++)
2660 table1[0].peBlue = i + 1;
2661 hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2662 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2663 if (FAILED(hr))
2665 skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2666 goto out;
2670 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2671 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2673 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2674 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2676 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2677 ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2679 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2680 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2681 hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2682 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2684 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2685 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2687 memset(table1, 0, sizeof(table1));
2688 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2689 ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2690 if (SUCCEEDED(hr))
2692 hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2693 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2694 ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2697 /* Test colorkey copying. */
2698 ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2699 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2700 ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2701 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2702 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2704 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2705 ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2707 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2708 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2710 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2711 ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2712 ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2713 "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2715 out:
2717 for (i = 0; i < 5; i++)
2719 if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2722 for (i = 0; i < 2; i++)
2724 for (i1 = 7; i1 >= 0; i1--)
2726 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2730 for (i = 0; i < 2; i++)
2731 for (i1 = 5; i1 >= 0; i1--)
2732 for (i2 = 7; i2 >= 0; i2--)
2734 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2738 static void SetMaterialTest(void)
2740 HRESULT rc;
2742 rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2743 ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2746 START_TEST(d3d)
2748 init_function_pointers();
2749 if(!pDirectDrawCreateEx) {
2750 skip("function DirectDrawCreateEx not available\n");
2751 return;
2754 if(!CreateDirect3D()) {
2755 skip("Skipping d3d7 tests\n");
2756 } else {
2757 LightTest();
2758 ProcessVerticesTest();
2759 StateTest();
2760 SceneTest();
2761 LimitTest();
2762 D3D7EnumTest();
2763 SetMaterialTest();
2764 CapsTest();
2765 VertexBufferDescTest();
2766 D3D7_OldRenderStateTest();
2767 DeviceLoadTest();
2768 ReleaseDirect3D();
2771 if (!D3D1_createObjects()) {
2772 skip("Skipping d3d1 tests\n");
2773 } else {
2774 Direct3D1Test();
2775 TextureLoadTest();
2776 D3D1_releaseObjects();