ddraw: Use ddraw_from_d3d7 to make a (IDirectDrawImpl *) from a (IDirect3D7 *).
[wine.git] / dlls / ddraw / tests / d3d.c
bloba35f520e8b66a23e34b80adcdd6289f9c0ccb972
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 IDirect3D *Direct3D_alt;
1037 unsigned int idx = 0;
1038 static struct v_in testverts[] = {
1039 {0.0, 0.0, 0.0}, { 1.0, 1.0, 1.0}, {-1.0, -1.0, -1.0},
1040 {0.5, 0.5, 0.5}, {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1042 static struct v_in cliptest[] = {
1043 {25.59, 25.59, 1.0}, {-25.59, -25.59, 0.0},
1044 {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1046 static struct v_in offscreentest[] = {
1047 {128.1, 0.0, 0.0},
1049 struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1050 D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1051 D3DTRANSFORMDATA transformdata;
1052 DWORD i = FALSE;
1054 /* Interface consistency check. */
1055 hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1056 ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1057 if (hr == D3D_OK)
1058 ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1060 memset(&desc, 0, sizeof(desc));
1061 desc.dwSize = sizeof(desc);
1062 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1063 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1065 memset(desc.lpData, 0, 128);
1066 instr = desc.lpData;
1067 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1068 instr[idx].bSize = sizeof(*branch);
1069 instr[idx].wCount = 1;
1070 idx++;
1071 branch = (D3DBRANCH *) &instr[idx];
1072 branch->dwMask = 0x0;
1073 branch->dwValue = 1;
1074 branch->bNegate = TRUE;
1075 branch->dwOffset = 0;
1076 idx += (sizeof(*branch) / sizeof(*instr));
1077 instr[idx].bOpcode = D3DOP_EXIT;
1078 instr[idx].bSize = 0;
1079 instr[idx].wCount = 0;
1080 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1081 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1083 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1084 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1086 memset(&desc, 0, sizeof(desc));
1087 desc.dwSize = sizeof(desc);
1089 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1090 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1092 memset(desc.lpData, 0, 128);
1093 instr = desc.lpData;
1094 idx = 0;
1095 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1096 instr[idx].bSize = sizeof(*branch);
1097 instr[idx].wCount = 1;
1098 idx++;
1099 branch = (D3DBRANCH *) &instr[idx];
1100 branch->dwMask = 0x0;
1101 branch->dwValue = 1;
1102 branch->bNegate = TRUE;
1103 branch->dwOffset = 64;
1104 instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1105 instr[0].bOpcode = D3DOP_EXIT;
1106 instr[0].bSize = 0;
1107 instr[0].wCount = 0;
1108 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1109 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1111 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1112 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1114 /* Test rendering 0 triangles */
1115 memset(&desc, 0, sizeof(desc));
1116 desc.dwSize = sizeof(desc);
1118 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1119 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1121 memset(desc.lpData, 0, 128);
1122 instr = desc.lpData;
1123 idx = 0;
1125 instr->bOpcode = D3DOP_TRIANGLE;
1126 instr->bSize = sizeof(D3DOP_TRIANGLE);
1127 instr->wCount = 0;
1128 instr++;
1129 instr->bOpcode = D3DOP_EXIT;
1130 instr->bSize = 0;
1131 instr->wCount = 0;
1132 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1133 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1135 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1136 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1138 memset(&transformdata, 0, sizeof(transformdata));
1139 transformdata.dwSize = sizeof(transformdata);
1140 transformdata.lpIn = testverts;
1141 transformdata.dwInSize = sizeof(testverts[0]);
1142 transformdata.lpOut = out;
1143 transformdata.dwOutSize = sizeof(out[0]);
1145 transformdata.lpHOut = NULL;
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);
1151 transformdata.lpHOut = outH;
1152 memset(outH, 0xcc, sizeof(outH));
1153 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1154 &transformdata, D3DTRANSFORM_UNCLIPPED,
1155 &i);
1156 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1157 ok(i == 0, "Offscreen is %d\n", i);
1159 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1160 static const struct v_out cmp[] = {
1161 {128.0, 128.0, 0.0, 1}, {129.0, 127.0, 1.0, 1}, {127.0, 129.0, -1, 1},
1162 {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5, 0, 1}
1165 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1166 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1167 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1168 out[i].x, out[i].y, out[i].z, out[i].rhw,
1169 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1171 for(i = 0; i < sizeof(outH); i++) {
1172 if(((unsigned char *) outH)[i] != 0xcc) {
1173 ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1174 break;
1178 SET_VP_DATA(vp_data);
1179 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1180 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1181 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1182 &transformdata, D3DTRANSFORM_UNCLIPPED,
1183 &i);
1184 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1185 ok(i == 0, "Offscreen is %d\n", i);
1187 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1188 static const struct v_out cmp[] = {
1189 {128.0, 128.0, 0.0, 1}, {133.0, 123.0, 1.0, 1}, {123.0, 133.0, -1, 1},
1190 {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5, 0, 1}
1192 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1193 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1194 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1195 out[i].x, out[i].y, out[i].z, out[i].rhw,
1196 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1199 SET_VP_DATA(vp_data);
1200 vp_data.dwX = 10;
1201 vp_data.dwY = 20;
1202 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1203 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1204 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1205 &transformdata, D3DTRANSFORM_UNCLIPPED,
1206 &i);
1207 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1208 ok(i == 0, "Offscreen is %d\n", i);
1209 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1210 static const struct v_out cmp[] = {
1211 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, {133.0, 153.0, -1, 1},
1212 {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5, 0, 1}
1214 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1215 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1216 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1217 out[i].x, out[i].y, out[i].z, out[i].rhw,
1218 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1221 memset(out, 0xcc, sizeof(out));
1222 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1223 &transformdata, D3DTRANSFORM_CLIPPED,
1224 &i);
1225 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1226 ok(i == 0, "Offscreen is %d\n", i);
1227 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1228 static const D3DHVERTEX cmpH[] = {
1229 {0, { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1230 {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1231 {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1233 ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1234 U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1235 "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1236 outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1237 cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1239 /* No scheme has been found behind those return values. It seems to be
1240 * whatever data windows has when throwing the vertex away. Modify the
1241 * input test vertices to test this more. Depending on the input data
1242 * it can happen that the z coord gets written into y, or similar things
1244 if(0)
1246 static const struct v_out cmp[] = {
1247 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, { -1.0, -1.0, 0.5, 1},
1248 {140.5, 145.5, 0.5, 1}, { -0.5, -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1250 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1251 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1252 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1253 out[i].x, out[i].y, out[i].z, out[i].rhw,
1254 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1257 for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1258 ok(((DWORD *) out)[i] != 0xcccccccc,
1259 "Regular output DWORD %d remained untouched\n", i);
1262 transformdata.lpIn = cliptest;
1263 transformdata.dwInSize = sizeof(cliptest[0]);
1264 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1265 &transformdata, D3DTRANSFORM_CLIPPED,
1266 &i);
1267 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1268 ok(i == 0, "Offscreen is %d\n", i);
1269 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1270 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1274 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
1275 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1277 ok(Flags[i] == outH[i].dwFlags,
1278 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1279 outH[i].dwFlags, Flags[i]);
1282 SET_VP_DATA(vp_data);
1283 vp_data.dwWidth = 10;
1284 vp_data.dwHeight = 1000;
1285 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1286 i = 10;
1287 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1288 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1289 &transformdata, D3DTRANSFORM_CLIPPED,
1290 &i);
1291 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1292 ok(i == 0, "Offscreen is %d\n", i);
1293 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1294 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1296 D3DCLIP_RIGHT,
1297 D3DCLIP_LEFT,
1298 D3DCLIP_RIGHT | D3DCLIP_BACK,
1299 D3DCLIP_LEFT | D3DCLIP_FRONT,
1301 ok(Flags[i] == outH[i].dwFlags,
1302 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1303 outH[i].dwFlags, Flags[i]);
1306 SET_VP_DATA(vp_data);
1307 vp_data.dwWidth = 256;
1308 vp_data.dwHeight = 256;
1309 vp_data.dvScaleX = 1;
1310 vp_data.dvScaleY = 1;
1311 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1312 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1313 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1314 &transformdata, D3DTRANSFORM_CLIPPED,
1315 &i);
1316 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1317 ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1318 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1319 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1323 D3DCLIP_BACK,
1324 D3DCLIP_FRONT,
1326 ok(Flags[i] == outH[i].dwFlags,
1327 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1328 outH[i].dwFlags, Flags[i]);
1331 /* Finally try to figure out how the DWORD dwOffscreen works.
1332 * Apparently no vertex is offscreen with clipping off,
1333 * and with clipping on the offscreen flag is set if only one vertex
1334 * is transformed, and this vertex is offscreen.
1336 SET_VP_DATA(vp_data);
1337 vp_data.dwWidth = 5;
1338 vp_data.dwHeight = 5;
1339 vp_data.dvScaleX = 10000;
1340 vp_data.dvScaleY = 10000;
1341 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1342 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1343 transformdata.lpIn = cliptest;
1344 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1345 &transformdata, D3DTRANSFORM_UNCLIPPED,
1346 &i);
1347 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1348 ok(i == 0, "Offscreen is %d\n", i);
1349 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1350 &transformdata, D3DTRANSFORM_CLIPPED,
1351 &i);
1352 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1353 ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1354 hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1355 &transformdata, D3DTRANSFORM_CLIPPED,
1356 &i);
1357 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1358 ok(i == 0, "Offscreen is %d\n", i);
1359 transformdata.lpIn = cliptest + 1;
1360 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1361 &transformdata, D3DTRANSFORM_CLIPPED,
1362 &i);
1363 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1364 ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1366 transformdata.lpIn = offscreentest;
1367 transformdata.dwInSize = sizeof(offscreentest[0]);
1368 SET_VP_DATA(vp_data);
1369 vp_data.dwWidth = 257;
1370 vp_data.dwHeight = 257;
1371 vp_data.dvScaleX = 1;
1372 vp_data.dvScaleY = 1;
1373 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1374 i = 12345;
1375 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1376 &transformdata, D3DTRANSFORM_CLIPPED,
1377 &i);
1378 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1379 ok(i == 0, "Offscreen is %d\n", i);
1380 vp_data.dwWidth = 256;
1381 vp_data.dwHeight = 256;
1382 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1383 i = 12345;
1384 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1385 &transformdata, D3DTRANSFORM_CLIPPED,
1386 &i);
1387 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1388 ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1390 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1391 &transformdata, 0,
1392 &i);
1393 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1395 hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1396 ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1399 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1401 int i;
1403 for (i = 0; i < 256; i++) {
1404 if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1405 table1[i].peBlue != table2[i].peBlue) return FALSE;
1408 return TRUE;
1411 /* test palette handling in IDirect3DTexture_Load */
1412 static void TextureLoadTest(void)
1414 IDirectDrawSurface *TexSurface = NULL;
1415 IDirect3DTexture *Texture = NULL;
1416 IDirectDrawSurface *TexSurface2 = NULL;
1417 IDirect3DTexture *Texture2 = NULL;
1418 IDirectDrawPalette *palette = NULL;
1419 IDirectDrawPalette *palette2 = NULL;
1420 IDirectDrawPalette *palette_tmp = NULL;
1421 PALETTEENTRY table1[256], table2[256], table_tmp[256];
1422 HRESULT hr;
1423 DDSURFACEDESC ddsd;
1424 int i;
1426 memset (&ddsd, 0, sizeof (ddsd));
1427 ddsd.dwSize = sizeof (ddsd);
1428 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1429 ddsd.dwHeight = 128;
1430 ddsd.dwWidth = 128;
1431 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1432 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1433 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1434 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1436 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1437 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1438 if (FAILED(hr)) {
1439 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1440 goto cleanup;
1443 hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1444 (void *)&Texture);
1445 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1446 if (FAILED(hr)) {
1447 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1448 goto cleanup;
1451 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1452 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1453 if (FAILED(hr)) {
1454 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1455 goto cleanup;
1458 hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1459 (void *)&Texture2);
1460 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1461 if (FAILED(hr)) {
1462 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1463 goto cleanup;
1466 /* test load of Texture to Texture */
1467 hr = IDirect3DTexture_Load(Texture, Texture);
1468 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1470 /* test Load when both textures have no palette */
1471 hr = IDirect3DTexture_Load(Texture2, Texture);
1472 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1474 for (i = 0; i < 256; i++) {
1475 table1[i].peRed = i;
1476 table1[i].peGreen = i;
1477 table1[i].peBlue = i;
1478 table1[i].peFlags = 0;
1481 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1482 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1483 if (FAILED(hr)) {
1484 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1485 goto cleanup;
1488 /* test Load when source texture has palette and destination has no palette */
1489 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1490 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1491 hr = IDirect3DTexture_Load(Texture2, Texture);
1492 ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1494 for (i = 0; i < 256; i++) {
1495 table2[i].peRed = 255 - i;
1496 table2[i].peGreen = 255 - i;
1497 table2[i].peBlue = 255 - i;
1498 table2[i].peFlags = 0;
1501 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1502 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1503 if (FAILED(hr)) {
1504 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1505 goto cleanup;
1508 /* test Load when source has no palette and destination has a palette */
1509 hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1510 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1511 hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1512 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1513 hr = IDirect3DTexture_Load(Texture2, Texture);
1514 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1515 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1516 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1517 if (!palette_tmp) {
1518 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1519 goto cleanup;
1520 } else {
1521 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1522 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1523 ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1524 IDirectDrawPalette_Release(palette_tmp);
1527 /* test Load when both textures have palettes */
1528 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1529 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1530 hr = IDirect3DTexture_Load(Texture2, Texture);
1531 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1532 hr = IDirect3DTexture_Load(Texture2, Texture);
1533 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1534 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1535 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1536 if (!palette_tmp) {
1537 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1538 goto cleanup;
1539 } else {
1540 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1541 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1542 ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1543 IDirectDrawPalette_Release(palette_tmp);
1546 cleanup:
1548 if (palette) IDirectDrawPalette_Release(palette);
1549 if (palette2) IDirectDrawPalette_Release(palette2);
1550 if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1551 if (Texture) IDirect3DTexture_Release(Texture);
1552 if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1553 if (Texture2) IDirect3DTexture_Release(Texture2);
1556 static void VertexBufferDescTest(void)
1558 HRESULT rc;
1559 D3DVERTEXBUFFERDESC desc;
1560 union mem_t
1562 D3DVERTEXBUFFERDESC desc2;
1563 unsigned char buffer[512];
1564 } mem;
1566 memset(&desc, 0, sizeof(desc));
1567 desc.dwSize = sizeof(desc);
1568 desc.dwCaps = 0;
1569 desc.dwFVF = D3DFVF_XYZ;
1570 desc.dwNumVertices = 1;
1571 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1572 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1573 if (!lpVBufSrc)
1575 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1576 goto out;
1579 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1580 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1581 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1582 if(rc != D3D_OK)
1583 skip("GetVertexBuffer Failed!\n");
1584 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1585 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1586 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1587 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1588 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1590 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1591 mem.desc2.dwSize = 0;
1592 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1593 if(rc != D3D_OK)
1594 skip("GetVertexBuffer Failed!\n");
1595 ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1596 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1597 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1598 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1599 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1601 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1602 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1603 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1604 if(rc != D3D_OK)
1605 skip("GetVertexBuffer Failed!\n");
1606 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1607 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1608 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1609 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1610 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1612 out:
1613 IDirect3DVertexBuffer7_Release(lpVBufSrc);
1616 static void D3D7_OldRenderStateTest(void)
1618 HRESULT rc;
1619 DWORD val;
1621 /* Test reaction to some deprecated states in D3D7.
1623 * IDirect3DDevice7 in Wine currently relays such states to wined3d where they are do-nothing and return 0, instead
1624 * of INVALIDPARAMS. Unless an app is found which cares this is probably ok. What this test shows is that these states
1625 * need not to be handled in D3D7.
1627 todo_wine {
1628 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1629 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1631 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1632 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1634 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1635 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %08x\n", rc);
1637 rc = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1638 ok(rc == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %08x\n", rc);
1642 #define IS_VALUE_NEAR(a, b) ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1643 #define MIN(a, b) ((a) < (b) ? (a) : (b))
1645 static void DeviceLoadTest(void)
1647 DDSURFACEDESC2 ddsd;
1648 IDirectDrawSurface7 *texture_levels[2][8];
1649 IDirectDrawSurface7 *cube_face_levels[2][6][8];
1650 DWORD flags;
1651 HRESULT hr;
1652 DDBLTFX ddbltfx;
1653 RECT loadrect;
1654 POINT loadpoint;
1655 int i, i1, i2;
1656 unsigned diff_count = 0, diff_count2 = 0;
1657 unsigned x, y;
1658 BOOL load_mip_subset_broken = FALSE;
1659 IDirectDrawPalette *palettes[5];
1660 PALETTEENTRY table1[256];
1661 DDCOLORKEY ddckey;
1662 D3DDEVICEDESC7 d3dcaps;
1664 /* Test loading of texture subrectangle with a mipmap surface. */
1665 memset(texture_levels, 0, sizeof(texture_levels));
1666 memset(cube_face_levels, 0, sizeof(cube_face_levels));
1667 memset(palettes, 0, sizeof(palettes));
1669 for (i = 0; i < 2; i++)
1671 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1672 ddsd.dwSize = sizeof(ddsd);
1673 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1674 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1675 ddsd.dwWidth = 128;
1676 ddsd.dwHeight = 128;
1677 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1678 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1679 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1680 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1681 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1682 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1683 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1684 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1685 if (FAILED(hr)) goto out;
1687 /* Check the number of created mipmaps */
1688 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1689 ddsd.dwSize = sizeof(ddsd);
1690 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1691 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1692 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1693 if (U2(ddsd).dwMipMapCount != 8) goto out;
1695 for (i1 = 1; i1 < 8; i1++)
1697 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1698 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1699 if (FAILED(hr)) goto out;
1703 for (i1 = 0; i1 < 8; i1++)
1705 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1706 ddsd.dwSize = sizeof(ddsd);
1707 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1708 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1709 if (FAILED(hr)) goto out;
1711 for (y = 0 ; y < ddsd.dwHeight; y++)
1713 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1715 for (x = 0; x < ddsd.dwWidth; x++)
1717 /* x stored in green component, y in blue. */
1718 DWORD color = 0xff0000 | (x << 8) | y;
1719 *textureRow++ = color;
1723 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1724 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1727 for (i1 = 0; i1 < 8; i1++)
1729 memset(&ddbltfx, 0, sizeof(ddbltfx));
1730 ddbltfx.dwSize = sizeof(ddbltfx);
1731 U5(ddbltfx).dwFillColor = 0;
1732 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1733 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1736 /* First test some broken coordinates. */
1737 loadpoint.x = loadpoint.y = 0;
1738 loadrect.left = 0;
1739 loadrect.top = 0;
1740 loadrect.right = 0;
1741 loadrect.bottom = 0;
1742 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1743 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1745 loadpoint.x = loadpoint.y = 50;
1746 loadrect.left = 0;
1747 loadrect.top = 0;
1748 loadrect.right = 100;
1749 loadrect.bottom = 100;
1750 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1751 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1753 /* Test actual loading. */
1754 loadpoint.x = loadpoint.y = 31;
1755 loadrect.left = 30;
1756 loadrect.top = 20;
1757 loadrect.right = 93;
1758 loadrect.bottom = 52;
1760 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1761 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1763 for (i1 = 0; i1 < 8; i1++)
1765 diff_count = 0;
1766 diff_count2 = 0;
1768 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1769 ddsd.dwSize = sizeof(ddsd);
1770 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1771 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1772 if (FAILED(hr)) goto out;
1774 for (y = 0 ; y < ddsd.dwHeight; y++)
1776 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1778 for (x = 0; x < ddsd.dwWidth; x++)
1780 DWORD color = *textureRow++;
1782 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1783 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1785 if (color & 0xffffff) diff_count++;
1787 else
1789 DWORD r = (color & 0xff0000) >> 16;
1790 DWORD g = (color & 0xff00) >> 8;
1791 DWORD b = (color & 0xff);
1793 if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1796 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1797 technically be correct as it's not precisely defined by docs. */
1798 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1799 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1801 if (color & 0xffffff) diff_count2++;
1803 else
1805 DWORD r = (color & 0xff0000) >> 16;
1806 DWORD g = (color & 0xff00) >> 8;
1807 DWORD b = (color & 0xff);
1809 if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1810 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1815 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1816 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1818 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
1819 MIN(diff_count, diff_count2), i1);
1821 loadpoint.x /= 2;
1822 loadpoint.y /= 2;
1823 loadrect.top /= 2;
1824 loadrect.left /= 2;
1825 loadrect.right = (loadrect.right + 1) / 2;
1826 loadrect.bottom = (loadrect.bottom + 1) / 2;
1829 /* This crashes on native (tested on real windows XP / directx9 / nvidia and
1830 * qemu Win98 / directx7 / RGB software rasterizer):
1831 * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
1832 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
1835 /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
1836 for (i = 0; i < 2; i++)
1838 for (i1 = 7; i1 >= 0; i1--)
1840 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
1843 memset(texture_levels, 0, sizeof(texture_levels));
1845 /* Test texture size mismatch. */
1846 for (i = 0; i < 2; i++)
1848 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1849 ddsd.dwSize = sizeof(ddsd);
1850 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1851 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1852 ddsd.dwWidth = i ? 256 : 128;
1853 ddsd.dwHeight = 128;
1854 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1855 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1856 if (FAILED(hr)) goto out;
1859 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
1860 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1862 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
1863 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1865 IDirectDrawSurface7_Release(texture_levels[0][0]);
1866 IDirectDrawSurface7_Release(texture_levels[1][0]);
1867 memset(texture_levels, 0, sizeof(texture_levels));
1869 memset(&d3dcaps, 0, sizeof(d3dcaps));
1870 hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
1871 ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
1873 if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1875 skip("No cubemap support\n");
1877 else
1879 /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
1880 for (i = 0; i < 2; i++)
1882 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1883 ddsd.dwSize = sizeof(ddsd);
1884 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1885 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1886 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1887 ddsd.dwWidth = 128;
1888 ddsd.dwHeight = 128;
1889 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1890 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1891 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1892 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1893 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1894 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1895 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
1896 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1897 if (FAILED(hr)) goto out;
1899 flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
1900 for (i1 = 1; i1 < 6; i1++, flags <<= 1)
1902 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1903 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
1904 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
1905 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1906 if (FAILED(hr)) goto out;
1909 for (i1 = 0; i1 < 6; i1++)
1911 /* Check the number of created mipmaps */
1912 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1913 ddsd.dwSize = sizeof(ddsd);
1914 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
1915 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1916 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1917 if (U2(ddsd).dwMipMapCount != 8) goto out;
1919 for (i2 = 1; i2 < 8; i2++)
1921 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
1922 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
1923 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
1924 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1925 if (FAILED(hr)) goto out;
1930 for (i = 0; i < 6; i++)
1931 for (i1 = 0; i1 < 8; i1++)
1933 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1934 ddsd.dwSize = sizeof(ddsd);
1935 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1936 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1937 if (FAILED(hr)) goto out;
1939 for (y = 0 ; y < ddsd.dwHeight; y++)
1941 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1943 for (x = 0; x < ddsd.dwWidth; x++)
1945 /* face number in low 4 bits of red, x stored in green component, y in blue. */
1946 DWORD color = 0xf00000 | (i << 16) | (x << 8) | y;
1947 *textureRow++ = color;
1951 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
1952 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1955 for (i = 0; i < 6; i++)
1956 for (i1 = 0; i1 < 8; i1++)
1958 memset(&ddbltfx, 0, sizeof(ddbltfx));
1959 ddbltfx.dwSize = sizeof(ddbltfx);
1960 U5(ddbltfx).dwFillColor = 0;
1961 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1962 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1965 loadpoint.x = loadpoint.y = 10;
1966 loadrect.left = 30;
1967 loadrect.top = 20;
1968 loadrect.right = 93;
1969 loadrect.bottom = 52;
1971 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
1972 DDSCAPS2_CUBEMAP_ALLFACES);
1973 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1975 for (i = 0; i < 6; i++)
1977 loadpoint.x = loadpoint.y = 10;
1978 loadrect.left = 30;
1979 loadrect.top = 20;
1980 loadrect.right = 93;
1981 loadrect.bottom = 52;
1983 for (i1 = 0; i1 < 8; i1++)
1985 diff_count = 0;
1986 diff_count2 = 0;
1988 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1989 ddsd.dwSize = sizeof(ddsd);
1990 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1991 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1992 if (FAILED(hr)) goto out;
1994 for (y = 0 ; y < ddsd.dwHeight; y++)
1996 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1998 for (x = 0; x < ddsd.dwWidth; x++)
2000 DWORD color = *textureRow++;
2002 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2003 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2005 if (color & 0xffffff) diff_count++;
2007 else
2009 DWORD r = (color & 0xff0000) >> 16;
2010 DWORD g = (color & 0xff00) >> 8;
2011 DWORD b = (color & 0xff);
2013 if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2014 b != y + loadrect.top - loadpoint.y) diff_count++;
2017 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2018 technically be correct as it's not precisely defined by docs. */
2019 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2020 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2022 if (color & 0xffffff) diff_count2++;
2024 else
2026 DWORD r = (color & 0xff0000) >> 16;
2027 DWORD g = (color & 0xff00) >> 8;
2028 DWORD b = (color & 0xff);
2030 if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2031 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2036 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2037 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2039 ok(diff_count == 0 || diff_count2 == 0,
2040 "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2041 MIN(diff_count, diff_count2), i, i1);
2043 loadpoint.x /= 2;
2044 loadpoint.y /= 2;
2045 loadrect.top /= 2;
2046 loadrect.left /= 2;
2047 loadrect.right = (loadrect.right + 1) / 2;
2048 loadrect.bottom = (loadrect.bottom + 1) / 2;
2052 for (i = 0; i < 2; i++)
2053 for (i1 = 5; i1 >= 0; i1--)
2054 for (i2 = 7; i2 >= 0; i2--)
2056 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2058 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2060 /* Test cubemap loading from regular texture. */
2061 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2062 ddsd.dwSize = sizeof(ddsd);
2063 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2064 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2065 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2066 ddsd.dwWidth = 128;
2067 ddsd.dwHeight = 128;
2068 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2069 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2070 if (FAILED(hr)) goto out;
2072 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2073 ddsd.dwSize = sizeof(ddsd);
2074 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2075 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2076 ddsd.dwWidth = 128;
2077 ddsd.dwHeight = 128;
2078 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2079 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2080 if (FAILED(hr)) goto out;
2082 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2083 DDSCAPS2_CUBEMAP_ALLFACES);
2084 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2086 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2087 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2088 IDirectDrawSurface7_Release(texture_levels[0][0]);
2089 memset(texture_levels, 0, sizeof(texture_levels));
2091 /* Test cubemap loading from cubemap with different number of faces. */
2092 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2093 ddsd.dwSize = sizeof(ddsd);
2094 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2095 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2096 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2097 ddsd.dwWidth = 128;
2098 ddsd.dwHeight = 128;
2099 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2100 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2101 if (FAILED(hr)) goto out;
2103 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2104 ddsd.dwSize = sizeof(ddsd);
2105 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2106 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2107 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2108 ddsd.dwWidth = 128;
2109 ddsd.dwHeight = 128;
2110 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2111 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2112 if (FAILED(hr)) goto out;
2114 /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2115 (the above created cubemaps will have all faces. */
2116 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2117 DDSCAPS2_CUBEMAP_ALLFACES);
2118 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2120 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2121 DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2122 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2124 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2125 DDSCAPS2_CUBEMAP_POSITIVEX);
2126 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2128 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2129 DDSCAPS2_CUBEMAP_ALLFACES);
2130 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2132 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2133 DDSCAPS2_CUBEMAP_POSITIVEX);
2134 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2136 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2137 DDSCAPS2_CUBEMAP_POSITIVEZ);
2138 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2140 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2141 IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2142 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2145 /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2146 for (i = 0; i < 2; i++)
2148 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2149 ddsd.dwSize = sizeof(ddsd);
2150 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2151 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2152 ddsd.dwWidth = 128;
2153 ddsd.dwHeight = 128;
2154 U2(ddsd).dwMipMapCount = i ? 4 : 8;
2155 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2156 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2157 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2158 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2159 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2160 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2161 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2162 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2163 if (FAILED(hr)) goto out;
2165 /* Check the number of created mipmaps */
2166 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2167 ddsd.dwSize = sizeof(ddsd);
2168 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2169 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2170 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2171 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2173 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2175 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2176 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2177 if (FAILED(hr)) goto out;
2181 for (i1 = 0; i1 < 8; i1++)
2183 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2184 ddsd.dwSize = sizeof(ddsd);
2185 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2186 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2187 if (FAILED(hr)) goto out;
2189 for (y = 0 ; y < ddsd.dwHeight; y++)
2191 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2193 for (x = 0; x < ddsd.dwWidth; x++)
2195 /* x stored in green component, y in blue. */
2196 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2197 *textureRow++ = color;
2201 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2202 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2205 for (i1 = 0; i1 < 4; i1++)
2207 memset(&ddbltfx, 0, sizeof(ddbltfx));
2208 ddbltfx.dwSize = sizeof(ddbltfx);
2209 U5(ddbltfx).dwFillColor = 0;
2210 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2211 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2214 loadpoint.x = loadpoint.y = 31;
2215 loadrect.left = 30;
2216 loadrect.top = 20;
2217 loadrect.right = 93;
2218 loadrect.bottom = 52;
2220 /* Destination mip levels are a subset of source mip levels. */
2221 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2222 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2224 for (i1 = 0; i1 < 4; i1++)
2226 diff_count = 0;
2227 diff_count2 = 0;
2229 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2230 ddsd.dwSize = sizeof(ddsd);
2231 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2232 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2233 if (FAILED(hr)) goto out;
2235 for (y = 0 ; y < ddsd.dwHeight; y++)
2237 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2239 for (x = 0; x < ddsd.dwWidth; x++)
2241 DWORD color = *textureRow++;
2243 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2244 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2246 if (color & 0xffffff) diff_count++;
2248 else
2250 DWORD r = (color & 0xff0000) >> 16;
2251 DWORD g = (color & 0xff00) >> 8;
2252 DWORD b = (color & 0xff);
2254 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2255 b != y + loadrect.top - loadpoint.y) diff_count++;
2258 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2259 technically be correct as it's not precisely defined by docs. */
2260 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2261 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2263 if (color & 0xffffff) diff_count2++;
2265 else
2267 DWORD r = (color & 0xff0000) >> 16;
2268 DWORD g = (color & 0xff00) >> 8;
2269 DWORD b = (color & 0xff);
2271 if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2272 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2277 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2278 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2280 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2281 MIN(diff_count, diff_count2), i1);
2283 loadpoint.x /= 2;
2284 loadpoint.y /= 2;
2285 loadrect.top /= 2;
2286 loadrect.left /= 2;
2287 loadrect.right = (loadrect.right + 1) / 2;
2288 loadrect.bottom = (loadrect.bottom + 1) / 2;
2291 /* Destination mip levels are a superset of source mip levels (should fail). */
2292 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2293 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2295 for (i = 0; i < 2; i++)
2297 for (i1 = 7; i1 >= 0; i1--)
2299 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2302 memset(texture_levels, 0, sizeof(texture_levels));
2304 /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2305 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2306 ddsd.dwSize = sizeof(ddsd);
2307 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2308 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2309 ddsd.dwWidth = 128;
2310 ddsd.dwHeight = 128;
2311 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2312 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2313 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2314 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2315 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2316 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2317 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2318 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2319 if (FAILED(hr)) goto out;
2321 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2322 ddsd.dwSize = sizeof(ddsd);
2323 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2324 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2325 ddsd.dwWidth = 32;
2326 ddsd.dwHeight = 32;
2327 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2328 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2329 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2330 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2331 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2332 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2333 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2334 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2335 if (FAILED(hr)) goto out;
2337 for (i1 = 1; i1 < 8; i1++)
2339 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2340 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2341 if (FAILED(hr)) goto out;
2344 for (i1 = 0; i1 < 8; i1++)
2346 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2347 ddsd.dwSize = sizeof(ddsd);
2348 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2349 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2350 if (FAILED(hr)) goto out;
2352 for (y = 0 ; y < ddsd.dwHeight; y++)
2354 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2356 for (x = 0; x < ddsd.dwWidth; x++)
2358 /* x stored in green component, y in blue. */
2359 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2360 *textureRow++ = color;
2364 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2365 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2368 memset(&ddbltfx, 0, sizeof(ddbltfx));
2369 ddbltfx.dwSize = sizeof(ddbltfx);
2370 U5(ddbltfx).dwFillColor = 0;
2371 hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2372 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2374 loadpoint.x = loadpoint.y = 32;
2375 loadrect.left = 32;
2376 loadrect.top = 32;
2377 loadrect.right = 96;
2378 loadrect.bottom = 96;
2380 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2381 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2383 loadpoint.x /= 4;
2384 loadpoint.y /= 4;
2385 loadrect.top /= 4;
2386 loadrect.left /= 4;
2387 loadrect.right = (loadrect.right + 3) / 4;
2388 loadrect.bottom = (loadrect.bottom + 3) / 4;
2390 /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2391 * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2392 * copied subrectangles divided more than needed, without apparent logic. But it works
2393 * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2394 * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2395 * The following code attempts to detect broken results, actual tests will then be skipped
2397 load_mip_subset_broken = TRUE;
2398 diff_count = 0;
2400 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2401 ddsd.dwSize = sizeof(ddsd);
2402 hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2403 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2404 if (FAILED(hr)) goto out;
2406 for (y = 0 ; y < ddsd.dwHeight; y++)
2408 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2410 for (x = 0; x < ddsd.dwWidth; x++)
2412 DWORD color = *textureRow++;
2414 if (x < 2 || x >= 2 + 4 ||
2415 y < 2 || y >= 2 + 4)
2417 if (color & 0xffffff) diff_count++;
2419 else
2421 DWORD r = (color & 0xff0000) >> 16;
2423 if ((r & (0xf0)) != 0xf0) diff_count++;
2428 if (diff_count) load_mip_subset_broken = FALSE;
2430 if (load_mip_subset_broken) {
2431 skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2432 } else {
2433 diff_count = 0;
2435 for (y = 0 ; y < ddsd.dwHeight; y++)
2437 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2439 for (x = 0; x < ddsd.dwWidth; x++)
2441 DWORD color = *textureRow++;
2443 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2444 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2446 if (color & 0xffffff) diff_count++;
2448 else
2450 DWORD r = (color & 0xff0000) >> 16;
2451 DWORD g = (color & 0xff00) >> 8;
2452 DWORD b = (color & 0xff);
2454 if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2455 b != y + loadrect.top - loadpoint.y) diff_count++;
2461 hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2462 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2464 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2466 for (i = 0; i < 2; i++)
2468 for (i1 = 7; i1 >= 0; i1--)
2470 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2473 memset(texture_levels, 0, sizeof(texture_levels));
2475 if (!load_mip_subset_broken)
2477 /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2478 * surface (than first source mip level)
2480 for (i = 0; i < 2; i++)
2482 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2483 ddsd.dwSize = sizeof(ddsd);
2484 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2485 if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2486 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2487 ddsd.dwWidth = i ? 32 : 128;
2488 ddsd.dwHeight = i ? 32 : 128;
2489 if (i) U2(ddsd).dwMipMapCount = 4;
2490 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2491 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2492 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2493 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2494 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2495 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2496 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2497 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2498 if (FAILED(hr)) goto out;
2500 /* Check the number of created mipmaps */
2501 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2502 ddsd.dwSize = sizeof(ddsd);
2503 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2504 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2505 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2506 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2508 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2510 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2511 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2512 if (FAILED(hr)) goto out;
2516 for (i1 = 0; i1 < 8; i1++)
2518 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2519 ddsd.dwSize = sizeof(ddsd);
2520 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2521 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2522 if (FAILED(hr)) goto out;
2524 for (y = 0 ; y < ddsd.dwHeight; y++)
2526 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2528 for (x = 0; x < ddsd.dwWidth; x++)
2530 /* x stored in green component, y in blue. */
2531 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2532 *textureRow++ = color;
2536 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2537 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2540 for (i1 = 0; i1 < 4; i1++)
2542 memset(&ddbltfx, 0, sizeof(ddbltfx));
2543 ddbltfx.dwSize = sizeof(ddbltfx);
2544 U5(ddbltfx).dwFillColor = 0;
2545 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2546 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2549 loadpoint.x = loadpoint.y = 0;
2550 loadrect.left = 0;
2551 loadrect.top = 0;
2552 loadrect.right = 64;
2553 loadrect.bottom = 64;
2555 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2556 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2558 i = 0;
2559 for (i1 = 0; i1 < 8 && i < 4; i1++)
2561 DDSURFACEDESC2 ddsd2;
2563 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2564 ddsd.dwSize = sizeof(ddsd);
2565 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2567 memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2568 ddsd2.dwSize = sizeof(ddsd2);
2569 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2571 if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2573 diff_count = 0;
2575 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2576 ddsd.dwSize = sizeof(ddsd);
2577 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2578 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2579 if (FAILED(hr)) goto out;
2581 for (y = 0 ; y < ddsd.dwHeight; y++)
2583 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2585 for (x = 0; x < ddsd.dwWidth; x++)
2587 DWORD color = *textureRow++;
2589 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2590 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2592 if (color & 0xffffff) diff_count++;
2594 else
2596 DWORD r = (color & 0xff0000) >> 16;
2597 DWORD g = (color & 0xff00) >> 8;
2598 DWORD b = (color & 0xff);
2600 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2601 b != y + loadrect.top - loadpoint.y) diff_count++;
2606 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2607 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2609 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2611 i++;
2614 loadpoint.x /= 2;
2615 loadpoint.y /= 2;
2616 loadrect.top /= 2;
2617 loadrect.left /= 2;
2618 loadrect.right = (loadrect.right + 1) / 2;
2619 loadrect.bottom = (loadrect.bottom + 1) / 2;
2622 for (i = 0; i < 2; i++)
2624 for (i1 = 7; i1 >= 0; i1--)
2626 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2629 memset(texture_levels, 0, sizeof(texture_levels));
2632 /* Test palette copying. */
2633 for (i = 0; i < 2; i++)
2635 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2636 ddsd.dwSize = sizeof(ddsd);
2637 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2638 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2639 ddsd.dwWidth = 128;
2640 ddsd.dwHeight = 128;
2641 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2642 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2643 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2644 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2645 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2646 if (FAILED(hr)) goto out;
2648 /* Check the number of created mipmaps */
2649 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2650 ddsd.dwSize = sizeof(ddsd);
2651 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2652 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2653 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2654 if (U2(ddsd).dwMipMapCount != 8) goto out;
2656 for (i1 = 1; i1 < 8; i1++)
2658 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2659 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2660 if (FAILED(hr)) goto out;
2664 memset(table1, 0, sizeof(table1));
2665 for (i = 0; i < 3; i++)
2667 table1[0].peBlue = i + 1;
2668 hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2669 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2670 if (FAILED(hr))
2672 skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2673 goto out;
2677 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2678 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2680 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2681 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2683 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2684 ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2686 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2687 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2688 hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2689 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2691 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2692 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2694 memset(table1, 0, sizeof(table1));
2695 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2696 ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2697 if (SUCCEEDED(hr))
2699 hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2700 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2701 ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2704 /* Test colorkey copying. */
2705 ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2706 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2707 ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2708 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2709 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2711 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2712 ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2714 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2715 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2717 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2718 ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2719 ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2720 "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2722 out:
2724 for (i = 0; i < 5; i++)
2726 if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2729 for (i = 0; i < 2; i++)
2731 for (i1 = 7; i1 >= 0; i1--)
2733 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2737 for (i = 0; i < 2; i++)
2738 for (i1 = 5; i1 >= 0; i1--)
2739 for (i2 = 7; i2 >= 0; i2--)
2741 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2745 static void SetMaterialTest(void)
2747 HRESULT rc;
2749 rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2750 ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2753 static void ComputeSphereVisibility(void)
2755 D3DMATRIX proj, view, world;
2756 D3DVALUE radius;
2757 D3DVECTOR center;
2758 DWORD result[1];
2759 HRESULT rc;
2761 world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2762 world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2763 world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2764 world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2766 view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2767 view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2768 view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2769 view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2771 proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2772 proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2773 proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2774 proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2776 center.x=11.461533;
2777 center.y=-4.761727;
2778 center.z=-1.171646;
2780 radius=38.252632;
2782 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2783 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2784 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2786 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, &center, &radius, 1, 0, result);
2788 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2789 todo_wine ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2791 world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2792 world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2793 world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2794 world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2796 view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2797 view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2798 view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2799 view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2801 proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2802 proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2803 proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
2804 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2806 center.x=0.0;
2807 center.y=0.0;
2808 center.z=0.05;
2810 radius=0.04;
2812 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2813 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2814 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2816 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, &center, &radius, 1, 0, result);
2818 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2819 todo_wine ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2821 world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2822 world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2823 world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2824 world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2826 view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2827 view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2828 view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2829 view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2831 proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2832 proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2833 proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2834 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2836 center.x=0.0;
2837 center.y=0.0;
2838 center.z=0.5;
2840 radius=0.5;
2842 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2843 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2844 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2846 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, &center, &radius, 1, 0, result);
2848 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2849 todo_wine ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2851 world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2852 world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2853 world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2854 world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2856 view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2857 view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2858 view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2859 view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2861 proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2862 proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
2863 proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
2864 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
2866 center.x=0.0;
2867 center.y=0.0;
2868 center.z=0.0;
2870 radius=0.0;
2872 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2873 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2874 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2876 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, &center, &radius, 1, 0, result);
2878 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2879 todo_wine ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
2882 START_TEST(d3d)
2884 init_function_pointers();
2885 if(!pDirectDrawCreateEx) {
2886 skip("function DirectDrawCreateEx not available\n");
2887 return;
2890 if(!CreateDirect3D()) {
2891 skip("Skipping d3d7 tests\n");
2892 } else {
2893 LightTest();
2894 ProcessVerticesTest();
2895 StateTest();
2896 SceneTest();
2897 LimitTest();
2898 D3D7EnumTest();
2899 SetMaterialTest();
2900 ComputeSphereVisibility();
2901 CapsTest();
2902 VertexBufferDescTest();
2903 D3D7_OldRenderStateTest();
2904 DeviceLoadTest();
2905 ReleaseDirect3D();
2908 if (!D3D1_createObjects()) {
2909 skip("Skipping d3d1 tests\n");
2910 } else {
2911 Direct3D1Test();
2912 TextureLoadTest();
2913 D3D1_releaseObjects();